A good match to an assay does not necessarily identify a unique mineral mixture. This worked synthetic example shows how to distinguish what the chemistry supports, what depends on assumptions, and which additional measurement could improve the decision.
Read the interpretation first; expand the code when you want to examine the implementation.
Problem Statement
Mine planning and geometallurgical decisions often need mineralogical information, while routine bulk assays are usually cheaper, denser and easier to collect than quantitative mineralogy. That gap is why element-to-mineral conversion (EMC) is appealing: could a standard XRF assay suite tell us enough about mineral modes to make the next decision?
Sometimes it can, but not by calculation alone. EMC combines the assay with a declared mineral list, mineral chemistry and rules such as non-negativity or closure. Different mineral mixtures can give the same bulk chemistry. And an assay does not reveal texture, liberation, oxidation state or process response. So a neat numerical output is not automatically a measured mineral mode.
This article works through what the assay can identify, what it leaves unresolved, and which extra measurement would actually help. It starts with a little EMC history and uses one invented mixture to make the ideas visible. The goal is not a universal conversion formula. It is an auditable answer: what is recoverable, what is still ambiguous, how much residual is left, and what to measure next.
Can routine chemistry support a mineral decision?
The mineral hosting an element can matter to separation and treatment, but a bulk assay alone does not predict liberation, recovery or plant performance. The practical question is therefore not whether EMC can return numbers, but whether the distinctions it can recover are enough for the next decision.
An assay is a chemical measurement. Mineral modes are phase proportions; a weight fraction is a phase’s mass divided by total sample mass. Thus 0.25 means 25 wt%, or 25 g in a 100 g sample. Element-to-mineral conversion (EMC) estimates modes by matching chemical contributions from a declared mineral list. It is a model-based, or normative, allocation. Measured reference mineralogy has measurement error and grouping choices of its own.
This article follows one wholly invented mixture through forward calculation, ambiguity, optimisation, search, labels and Bayesian updating. The recurring question is: which parts of the answer come from measurements, and which come from assumptions?
A brief history of element-to-mineral conversion
EMC is not a new trick. A few landmarks are useful here because they point to the same practical caution: a good fit is not necessarily a unique mineralogical answer.
Start with simultaneous equations, then admit the chemistry can move (1985). Johnson, Chu and Hussey (1985) used simultaneous linear equations to estimate clay-mineral proportions from chemical and physical properties. Their workflow identified candidate minerals, measured the properties, bounded plausible component values, checked residuals and iterated. The lesson still matters: mineral proportions and the coefficients used to estimate them can both be uncertain, so a small residual is not proof that one mineral split is right.
Whiten (2008) expressed the calculation as
\[
a = Cm,
\]
and used singular-value decomposition and the pseudoinverse to show the whole family of solutions. The null space makes the limitation plain: if the assay cannot tell two candidate minerals apart, an exact fit can still leave their split unresolved. Closure, ratios and similar constraints choose within that family. They do not put chemical information back into the assay.
Bring in QXRD and calibration (2011–2015). Berry, Hunt and McKnight (2011) treated EMC as a practical bulk-mineralogy tool: sparse QXRD can calibrate linear-programming preferences, while assay and QXRD information can be combined by error-weighted non-negative least squares. Their warning is just as useful as the method: results depend on the mineral list, mineral chemistry and assay coverage; direct H2O and CO2 measurements, or LOI when those are unavailable, can make a real difference. Parian et al. (2015) used quantitative Rietveld XRD to organise sequential EMC and constrained non-negative factorisation for iron-ore and process samples. That improved a deposit-specific workflow. It did not produce a response matrix or weighting scheme that can be lifted unchanged into every deposit.
Build operational models, then make uncertainty explicit (2018–2023). Mena Silva et al. (2018) compared least-squares and regression-based EMC against XRD for the Nabbaren nepheline-syenite deposit. The regression mapping did better there, but it learned a particular mineral system rather than a general conversion. Rodrigues et al. (2023) point toward Bayesian modal-mineralogy approximation from assays. The available conference abstract supports that broad direction, but not a detailed claim about its likelihood, priors or validation.
The pattern across this history is simple. EMC becomes more useful when it is treated as a constrained, deposit-specific inference problem and paired with independent mineralogical or mineral-chemistry measurements. It is a poor substitute when the decision rests on mineral distinctions that bulk chemistry has already lost.
One invented mixture, first forwards
Question. If the mineral recipe were known, what assay would it produce?
Imagine 60 g quartz, 25 g anatase and 15 g rutile in a 100 g mixture. Anatase and rutile are polymorphs: distinct crystal structures with the same ideal formula, TiO2. In this deliberately simple oxide basis, quartz contributes only SiO2 and both titanium phases contribute only TiO2.
Before writing \(a=Cm\), give each symbol a job. Start with a 100 g toy sample. Its assay reports 60 g SiO2 and 40 g TiO2, so the assay vector is a column of the measured oxide fractions:
The remaining object, \(C\), is the mineral-to-assay response matrix. Entry \(c_{ij}\) says how much of assay component \(i\) is contributed by one unit mass of mineral \(j\). Rows are assay components, columns are minerals. For the idealised chemistry in this example,
Read the first column as “one unit of quartz contributes one unit of SiO2 and no TiO2”. Read the second and third columns as “one unit of anatase or rutile contributes TiO2 only”. Mineral chemistry supplies these columns; it is not estimated from this toy assay.
For any assay component \(i\), the forward calculation is a weighted sum over minerals:
\[
a_i=\sum_{j=1}^{p}c_{ij}m_j.
\tag{4}\]
Here \(p\) is the number of minerals in the declared list. Each term \(c_{ij}m_j\) is one mineral’s contribution to one assay component.
Writing every component sum at once gives the compact matrix form used by Whiten (2008):
\[
a=Cm.
\tag{5}\]
The dimensions make the multiplication checkable. Here \(C\) is \(2\times3\), \(m\) is \(3\times1\), and the result \(a\) is \(2\times1\). In words: multiply each mineral column by its fraction, then add the columns. If the recipe is 60% quartz, 25% anatase and 15% rutile, the calculation is
This is the easy direction: mineral recipe to assay. The inverse problem starts with the final column, \(a\), and asks which non-negative, closed mineral vectors \(m\) could have produced it. There is no general operation called “divide by \(C\)”. Whether a reverse calculation is unique depends on the columns of \(C\) and on the constraints we are willing to state.
All displayed cells below are one visible, top-to-bottom program. Inputs are embedded; later cells use only objects defined in earlier visible cells. Random work uses named local generators with declared seeds. Calculations use fractions and displays use wt%.
Here (n_{ij}) is the count of element (i) in mineral (j), (M) is molar mass and () is the relevant element count in the oxide. If FeO is converted to Fe2O3-equivalent, the multiplier (159.69/143.69) changes the reporting basis; it does not infer oxidation state. Measured grain chemistry can replace ideal formulae. Missing water, CO2, unassayed elements and solid solution mean real columns need not sum to one.
What this means. A declared recipe and response matrix determine a forward assay. What it does not mean. Reversing the calculation will necessarily recover the recipe.
From an assay back to minerals
The inverse problem starts with the assay vector \(a\) and asks for the mineral-fraction vector \(m\). The matrix relation has not changed:
\[
a=Cm.
\]
What changes is which quantity is known. In the forward calculation, we knew \(m\) and multiplied. In inversion, we know \(a\) and need to solve for \(m\).
The special case: an ordinary inverse
An ordinary matrix inverse exists only when \(C\) is square and full rank. In plain terms, there must be the same number of independent assay components as unknown minerals, and no mineral column can be reproduced by a combination of the others. If those conditions hold, multiply both sides on the left by \(C^{-1}\):
\[
C^{-1}a=C^{-1}Cm=Im=m.
\]
So the ordinary inverse formula is
\[
m=C^{-1}a.
\tag{7}\]
The order matters. It is not \(a=Cb^{-1}\): \(b\) is not part of the notation here, and a matrix inverse acts on the left of the assay vector. Some papers instead write the same relationship as \(b=Ax\), with \(b\) for assays, \(A\) for mineral chemistry and \(x\) for mineral fractions. The letters change; the calculation does not.
This tidy case is useful for understanding the algebra, but it is uncommon in EMC. Our toy \(C\) is \(2\times3\), so it has two assay rows and three mineral columns. It cannot have an ordinary inverse: there is no \(C^{-1}\) for a non-square matrix.
The usual cases
There are three practical possibilities.
More independent assays than minerals. If \(C\) has more rows than columns and full column rank, assay noise can still prevent an exact match. Weighted least squares finds the mineral vector whose reconstructed assay is closest to the measured assay after accounting for assay uncertainty:
Here \(\Sigma_a\) describes assay uncertainty. The formula is a least-squares estimate, not an ordinary inverse, and it can still return negative mineral fractions.
Fewer independent assays than minerals, or duplicate mineral signatures. This is our toy case. There can be many exact solutions, because a change along a null direction leaves \(Cm\) unchanged. The Moore-Penrose pseudoinverse gives one conventional answer,
\[
m^+=C^+a,
\tag{9}\]
usually the solution with the smallest Euclidean length. It is useful for exposing the geometry, but it is not evidence that this particular mineral split occurred.
Physical constraints or additional measurements are available. We can state the inverse as an optimisation problem instead:
\[
\begin{aligned}
\underset{m}{\operatorname{minimise}}\quad &
\left\|\Sigma_a^{-1/2}(Cm-a)\right\|_2^2\\
\text{subject to}\quad &m_j\geq0\quad\text{for every mineral }j,\\
&\mathbf{1}^\mathsf{T}m=1.
\end{aligned}
\tag{10}\]
The objective says “match the assay within its uncertainty”; non-negativity prevents negative mineral mass; closure makes the mineral fractions sum to one. Extra measurements can add more rows to the problem. For example, a phase-sensitive observation or a QXRD result adds a constraint only if it changes across the mineral alternatives we want to separate.
Berry, Hunt and McKnight (2011) make the same practical point in a bulk-mineralogy workflow. They use linear programming when sparse QXRD helps set a calculation standard, and error-weighted least squares when chemical and QXRD information are both available. Neither method makes an ambiguous chemical signature unique by itself. It states which measurements, weights and constraints are being used to choose among compatible mineral vectors.
Why the assay has several answers
Question. Can the 60/40 assay distinguish anatase from rutile?
has the same assay. Closure says fractions sum to one; non-negativity excludes negative mass. The matrix has rank two for three fractions. Its null direction (v=(0,1,-1)^T) changes the polymorph split while (Cv=0). SVD and the pseudoinverse expose this geometry (Whiten, 2008; NumPy Developers, n.d.).
Which synthetic recipes share one assay? Quartz remains 60 wt% while anatase rises and rutile falls; every point reconstructs 60 wt% SiO2 and 40 wt% TiO2.
What this means. The assay identifies quartz and total titanium phase. What it does not mean. More precision in the same bulk channels can identify the polymorph split. Exact duplicate columns lose a distinction completely; near-collinear columns instead make it unstable.
Deterministic methods choose different representatives
Question. What do common constrained methods return on the same assay?
Weighted least squares minimises
\[
Q(m)=\tfrac12\lVert W(Cm-a)\rVert_2^2,
\]
with (W=I) here. NNLS adds (m); equality-constrained fitting also adds (^Tm=1). LP reports feasible extrema rather than a preferred point (SciPy Community, n.d.b, n.d.c, n.d.d).
Do deterministic conventions agree? Five exact synthetic solutions reconstruct the assay, yet their anatase/rutile allocations differ; residual norms are multiplied by one quadrillion only to make floating-point differences visible.
Mineral
LP minimum wt%
LP maximum wt%
0
Quartz
60.0
60.0
1
Anatase
0.0
40.0
2
Rutile
0.0
40.0
LP’s 0–40 wt% phase ranges are feasibility intervals, not probabilities, credible intervals or repeated-sample coverage. Noisy assays can make the exact feasible set empty; widening a numerical tolerance is not a measurement-error model.
What this means. Constraints prevent some physically impossible answers and LP displays what remains possible. What it does not mean. A solver-selected exact fit is newly measured truth.
Allocation order is a visible convention
Question. How can a staged recipe change the story?
At each synthetic stage below, one analyte is allocated to a compatible phase. The two declared recipes reverse the analyte order and use opposite titanium tie-breaks:
When does each synthetic phase receive mass? The Si-first/anatase-first recipe and Ti-first/rutile-first recipe both end at an exact assay fit, but the intermediate path and final polymorph differ.
What this means. A staged recipe can encode auditable geological conventions. What it does not mean. Changing order resolves the chemistry’s missing polymorph information.
Genetic search: seeds are not phase discovery
Question. Does a flexible search find the real mineral list?
This teaching genetic search normalises non-negative chromosomes to the simplex, ranks them by
and uses 80 candidates, 160 generations, 20 elites, convex crossover and Gaussian mutation. It is deliberately small. The scientific model is the candidate set (J). We compare exactly four lists:
quartz + anatase: identified exact fit;
quartz + rutile: identified exact fit;
quartz + anatase + rutile: exact but structurally ambiguous;
What changes across genetic-search seeds and candidate lists? Identified two-phase lists are stable, the three-phase list preserves about 40 wt% total titanium phase while its split varies, and the no-quartz list cannot represent the true recipe.
Can each candidate list reconstruct the synthetic assay? Exact lists reach negligible residuals; omitting quartz leaves a material residual near 0.85 on the fraction scale.
Repeated seeds expose numerical search variability. Changing the candidate list changes the scientific model. The three-phase ridge is structural ambiguity; the no-quartz residual is misspecification. A genetic algorithm cannot discover the real phase list unless phase inclusion is encoded and selected with justified penalties.
What this means. Search can navigate a chosen objective. What it does not mean. Seed spread is posterior uncertainty, or a good residual proves the declared phases are real.
Labels can calibrate a choice
Question. What changes when paired modal labels are available?
Suppose held-back synthetic calibration labels give weights 0.70 and 0.30 to the two LP endpoints. Their convex average is
Where does a label-calibrated answer come from? The upper panel shows two synthetic exact candidates and their 70/30 weighted result; the lower panel separates label supervision from the mass-balance reconstruction check in a learned route.
In a neural route, paired modal labels supervise the assay-to-mode mapping; a mass-balance decoder or penalty checks predicted chemistry against the chosen response matrix. Labels are new evidence of a different kind. The reconstruction penalty is not a second modal label. No large model is trained here, and this toy graphic is only an illustration.
What this means. Labels can teach how to choose among chemistry-compatible candidates. What it does not mean. Averaging adds chemical information or identifies the null direction from the assay alone.
Bayesian inference, one definition at a time
Bayesian language can make a simple idea sound harder than it is, so let us keep each piece tied to the mixture. In this toy example, the only unknown is the anatase fraction \(t\); quartz is fixed at 60 wt% and rutile is whatever remains of the 40 wt% titanium phase.
A prior says which values of \(t\) were plausible before this sample’s observations.
A forward prediction turns a proposed \(t\) into predicted measurements.
A likelihood asks how compatible those predictions are with the measurements.
A posterior combines the prior and likelihood, then rescales the result so it is a probability distribution.
A posterior draw is one self-consistent sampled state from that distribution.
A credible interval is conditional: it contains a stated posterior probability only if the model, prior and data assumptions are reasonable.
A posterior predictive distribution asks what a new measurement would look like if the fitted model were used to generate it.
The top line says, “start with a plausible split, then favour the values that predict what we observed.” The bottom line is just the normalising constant: it makes the posterior add up to one. Here \(a\) is the bulk assay and \(y\) is an additional, invented phase-sensitive measurement. The point is to keep those two sources of information separate.
The assay can constrain anything that changes \(Cm(t)\). The phase-sensitive observation can constrain \(t\) directly. If neither changes along a possible mineral split, neither can resolve it.
Dirichlet priors describe closed compositions
Question. What do a prior centre and concentration do?
For \(m\sim\operatorname{Dirichlet}(\alpha)\), write \(\alpha=\kappa\mu\), where the centre \(\mu\) is a composition that sums to one and the concentration is \(\kappa=\sum_j\alpha_j\). Then \(E[m]=\mu\). In plain terms, \(\mu\) says where the prior is centred and \(\kappa\) says how tightly it is held there. Closure means the fractions compete: if one rises, at least one other must fall.
How do Dirichlet centre and concentration alter prior compositions? Synthetic prior marginals move with the centre and tighten as concentration rises; all draws close to one.
Quartz
Anatase
Rutile
Quartz
0.021644
-0.010498
-0.011146
Anatase
-0.010498
0.013535
-0.003037
Rutile
-0.011146
-0.003037
0.014183
These are prior-only synthetic draws, not assay evidence. Parameters below one favour simplex boundaries but do not create an exact-zero point mass; zero Dirichlet parameters are invalid (SciPy Community, n.d.a). For the one-dimensional grid below, the same Dirichlet density is evaluated only along the feasible line \(m(t)\); equal grid spacing makes the normalised values a discrete approximation to \(p(t)\).
The assay likelihood stays flat along the null direction
In this example, every \(m(t)\) gives the same \(Cm(t)\). So the assay likelihood is flat across the entire feasible split:
The assay-only posterior therefore equals the prior along this ridge. That is not a failure of Bayesian inference; it is an honest statement that the assay learned nothing about the anatase– rutile split.
Question. What happens if we add genuinely phase-sensitive information?
For teaching only, invent an observation \(y=0.28\) with known scale \(\sigma_y=0.04\), where \(y\mid t\sim N(t,\sigma_y^2)\). Treat it as a generic phase-sensitive instrument response on the same fraction scale. It is an invented measurement, not bulk chemistry.
What updates the synthetic polymorph split? The assay-only likelihood is flat, so the assay-only posterior equals the prior; the invented phase-sensitive observation shifts and tightens the normalised grid posterior.
The prior and posterior curves integrate to one; the likelihood panel is explicitly relative to its own maximum. The central 90% credible interval is a posterior probability statement conditional on this invented model. It is neither the LP range nor a guarantee of 90% repeated-sample coverage. This Gaussian-likelihood/Dirichlet-prior construction is not conjugate, which is why the example uses a numerical grid rather than a closed-form update.
What this means. An additional phase-sensitive measurement can update the split because it changes along \(t\). What it does not mean. Bayesian inference created information absent from the assay.
A practical Python route: PyMC, NumPyro, Bambi and ArviZ
The grid is useful here because it lets us see the flat assay likelihood. For a model with more minerals, samples or uncertain chemistry, use a sampler instead. The tools have different jobs:
PyMC is a good default for writing the custom mineral model in Python.
NumPyro expresses the same sort of model with JAX and NUTS. It can be a fast option for a larger model, but it does not change the identifiability problem, so benchmark it on the model you actually need.
Bambi is a formula interface built on PyMC. It is handy when calibrating a phase-sensitive instrument from known modal fractions, but it is not the right abstraction for the custom deterministic mass-balance relationship below.
ArviZ reads output from both PyMC and NumPyro, then gives the same summaries, trace plots and posterior-predictive checks.
These roles follow the projects’ own documentation (Bambi, n.d.; PyMC Developers, n.d.; NumPyro Contributors, n.d.; ArviZ Developers, n.d.).
The model below leaves the assay as a deterministic calculation because, in this toy mixture, \(Cm(t)\) does not vary with \(t\). Giving that constant quantity a Gaussian likelihood would make the code longer without adding information. The invented phase-sensitive response is the only observation that updates the anatase-rutile split.
View code
import arviz as azimport pymc as pmimport pytensor.tensor as ptwith pm.Model(coords={"oxide": oxides, "mineral": names}) as toy_pymc:# The Beta prior is the two-part Dirichlet prior written on the 0 to 0.40 ridge. t_share = pm.Beta("t_share", alpha=2, beta=2) t = pm.Deterministic("anatase_fraction", 0.40* t_share) m = pm.Deterministic("mineral_fraction", pt.stack([0.60, t, 0.40- t]), dims="mineral") pm.Deterministic("assay_mean", pt.dot(C, m), dims="oxide") pm.Normal("phase_response", mu=t, sigma=sigma_y, observed=y_observed) idata_pymc = pm.sample(draws=2_000, tune=1_000, chains=4, target_accept=0.90, random_seed=20260907) pm.sample_posterior_predictive(idata_pymc, var_names=["phase_response"], extend_inferencedata=True, random_seed=20260908)display(az.summary(idata_pymc, var_names=["anatase_fraction"], kind="all"))az.plot_trace(idata_pymc, var_names=["anatase_fraction"])az.plot_ppc(idata_pymc, num_pp_samples=100)
The PyMC cell uses NUTS and returns an ArviZ InferenceData object. The three ArviZ calls answer three separate questions: what values were estimated; whether the chains mix; and whether the invented response looks plausible under the fitted model. Do not treat a good trace or a good posterior-predictive plot as proof that the mineral list is complete.
Here is the same toy model in NumPyro. It is deliberately a second implementation, not an extra source of evidence. Run either this cell or the PyMC cell for one analysis.
View code
from jax import randomimport jax.numpy as jnpimport numpyroimport numpyro.distributions as distfrom numpyro.infer import MCMC, NUTS, Predictivedef toy_numpyro_model(y=y_observed, sigma=sigma_y): t_share = numpyro.sample("t_share", dist.Beta(2, 2)) t = numpyro.deterministic("anatase_fraction", 0.40* t_share) m = numpyro.deterministic("mineral_fraction", jnp.array([0.60, t, 0.40- t])) numpyro.deterministic("assay_mean", jnp.asarray(C) @ m) numpyro.sample("phase_response", dist.Normal(t, sigma), obs=y)mcmc = MCMC(NUTS(toy_numpyro_model), num_warmup=1_000, num_samples=2_000, num_chains=4)mcmc.run(random.PRNGKey(20260907))posterior_predictive = Predictive( toy_numpyro_model, posterior_samples=mcmc.get_samples())(random.PRNGKey(20260908))idata_numpyro = az.from_numpyro(mcmc, posterior_predictive=posterior_predictive)display(az.summary(idata_numpyro, var_names=["anatase_fraction"], kind="all"))az.plot_trace(idata_numpyro, var_names=["anatase_fraction"])az.plot_ppc(idata_numpyro, num_pp_samples=100)
Use Bambi one step earlier, when there are calibration measurements for a phase-sensitive instrument. In this deliberately small example, the calibration rows are invented. The model learns how the response changes with a known anatase fraction; it does not replace the custom mineral inversion above.
Is the invented phase-sensitive observation compatible with its teaching model? The observed 28 wt% lies within the central 90% posterior-predictive interval.
Central 90% posterior-predictive interval: 18.07 to 36.21 wt%
What this means. The invented datum is compatible with the stated prior, likelihood and noise scale. What it does not mean. The chemistry is correct, the phases are identified in reality, or the intervals are calibrated. Sensitivity to the prior centre, concentration and \(\sigma_y\) remains part of the analysis.
From the grid to high-dimensional NUTS
The grid is deliberately small enough to see. It works only because this example has one unknown direction. A larger model might let several mineral fractions and parts of the chemistry vary at once. That creates a posterior with many constrained, correlated unknowns, where the No-U-Turn Sampler (NUTS) is more useful than a rectangular grid.
Getting samples out of NUTS is only the start. Split rank-normalised \(\widehat R\), bulk and tail effective sample sizes, divergences and tree-depth hits tell us whether the chains were explored well enough to summarise them. Assay reconstruction and posterior-predictive checks ask something else: can the stated observation model reproduce the relevant parts of the data? Prior and likelihood sensitivity then show how much the answer depends on modelling choices. None of that, by itself, proves the geology is right.
When chemistry is uncertain, an abundance draw and its matching chemistry draw need to stay together:
Here \(s\) indexes a sample and \(d\) indexes one posterior draw. The reconstruction \(\widehat a_s^{(d)}\) is therefore a prediction from one internally consistent model state:
Multiplying separate posterior means \(E[C]E[m]\) discards their dependence and may describe no posterior state at all. Independent grain chemistry can inform a chemistry prior; paired modal labels supervise a predictive map; geological groupings structure a prior; and phase-sensitive measurements change the likelihood. They are different sources of information, not interchangeable decorations.
Conclusion
EMC earns its place because routine assays are cheap, dense and already part of most mining workflows. With a credible phase list and mineral chemistry, it can give a fast, consistent first estimate of mineral groups, check samples against their chemistry, and show where scarce mineralogical work will matter most. That is useful, especially when the decision is about an aggregate the assay can actually identify.
The trouble starts when a neat output is treated as a measurement. Two minerals can have the same bulk-chemical signature; omitted phases, unsuitable mineral chemistry, unmeasured volatiles, inconsistent units and analytical error can all make an exact-looking allocation wrong. Closure, optimisation, a Bayesian prior and a neural network can make a calculation more useful. None of them manufactures the phase-specific information the assay does not contain.
The most useful EMC result is often a boundary rather than one more precise-looking number: this total is recoverable; this split is not; here is the residual; and here is the next measurement that would change the decision. For the toy mixture, “40 wt% total titanium phase, with anatase and rutile unresolved” is more honest and more useful than a made-up polymorph split.
Use EMC to work through a set of assays, then say plainly which parts of the answer were measured, which were assumed, and where direct mineralogy still has to do the work.
Method family
Information added
Useful role
Practical burden
Main failure mode
Pseudoinverse / NNLS / closure
Constraints or a selection convention
Fast baseline and transparent reconstruction
Low; requires a declared phase list and units
Reports a convention as if it were identified mineralogy
LP bounds
Feasibility constraints
Honest ranges for identifiable totals and endpoints
Low–moderate; exact or tolerance choices need documenting
Empty or misleading feasible set under noisy/misaligned assays
Explore nonlinear or combinatorial candidate recipes
Moderate–high; repeated seeds and residual checks are needed
Seed variability or misspecified phases mistaken for discovery
Labels / neural models
Paired modal labels and learned mapping
Fast prediction when deployment data resemble training data
High; needs representative labels and out-of-domain checks
Shortcut learning, poor calibration or mass-balance mismatch
Bayesian model
Prior structure, likelihood and any extra measurements
Quantify conditional uncertainty and sensitivity
High; diagnostics, posterior checks and matched draws
Prior/likelihood assumptions mistaken for new chemical information
This table is a decision aid, not a ranking. The right family depends on what information is available and, more importantly, what decision needs to be defended.
NoteReproducing the toy example
For the visible toy program, use Python 3.11+ with:
No cell reads external data, discovers a project root or accesses a network. The setup cell imports standard scientific Python libraries. NumPy supplies linear algebra and random generators; SciPy supplies explicit optimisation primitives; pandas DataFrames hold tables and every visual’s data; Plotnine authors the figures (Plotnine contributors, n.d.). Quarto is needed only to render the article.
The toy mixture ends where a real EMC study should end: the assay supports 40 wt% total anatase plus rutile, but it cannot separate the two. That is not an incomplete answer. It tells us whether the total is enough for the decision at hand, and, if it is not, what needs to be measured next.
If you are working through a mineral-allocation decision, start by auditing the assay basis and phase list. Then ask what is genuinely recoverable before deciding on the smallest additional measurement that would change the decision.
The explanatory rhythm and recurring-example approach were inspired by Heiss (2024) and Robinson (2014); the prose, calculations, visuals and code here are original.
Working with assay data and limited mineralogy?
Get in touch to discuss whether your conversion method supports the decision you need to make.
Berry, R.F., Hunt, J.A. and McKnight, S.W. (2011) ‘Estimating mineralogy in bulk samples’, in Proceedings of the 1st International Geometallurgy Conference (GeoMet 2011). Perth: AusIMM. [Local background paper.]
Heiss, A. (2024) ‘Demystifying causal inference estimands: ATE, ATT, and ATU’, Andrew Heiss, 21 March. Available at: https://doi.org/10.59350/c9z3a-rcq16 (Accessed: 7 September 2026).
Johnson, L.J., Chu, C.H. and Hussey, G.A. (1985) ‘Quantitative clay mineral analysis using simultaneous linear equations’, Clays and Clay Minerals, 33(2), pp. 107–117. [Local background paper.]
Mena Silva, C., Sorensen, B.E., Aasly, K. and Ellefmo, S.L. (2018) ‘Geometallurgical approach to the element-to-mineral conversion for the Nabbaren nepheline syenite deposit’, Minerals, 8(8), 325. Available at: https://doi.org/10.3390/min8080325.
Parian, M., Lamberg, P., Mockel, R. and Rosenkranz, J. (2015) ‘Analysis of mineral grades for geometallurgy: Combined element-to-mineral conversion and quantitative X-ray diffraction’, Minerals Engineering, 82, pp. 25–35. Available at: https://doi.org/10.1016/j.mineng.2015.04.023.
Plotnine contributors (n.d.) Plotnine documentation. Available at: https://plotnine.org/ (Accessed: 7 September 2026).
Rodrigues, A.A., Grose, L., Ailleres, L., Halley, S., Escolme, A., Armit, R., Harandi, M. and Cracknell, M. (2023) ‘Pedras: Modal mineralogy approximations from assay data using Bayesian inference’, GeoBerlin 2023. Available at: https://doi.org/10.48380/2r85-w395.
Whiten, W.J. (2008) ‘Calculation of mineral composition from chemical assays’, Mineral Processing and Extractive Metallurgy Review, 29(2), pp. 83–97. Available at: https://doi.org/10.1080/08827500701257860.