mescla.emma.model.EMMA

class mescla.emma.model.EMMA(k=None, rule='one', standardize=True, variance_threshold=0.9)[source]

Bases: object

End-Member Mixing Analysis.

Parameters:
  • k (int, optional) – Force the rank. When None (the default) it is chosen by rule.

  • rule ({"one", "variance", "broken_stick", "parallel"}, default "one") – Retention criterion. "one" is the classical rule of one (Kaiser); it is also the weakest, so check rank_summary() and the residual diagnostics before accepting its answer.

  • standardize (bool, default True) – Z-score the species first (correlation PCA). Turn off only when all species share units and you want large concentrations to dominate.

  • variance_threshold (float, default 0.9) – Target for rule="variance".

Variables:

Examples

>>> from mescla import EMMA
>>> model = EMMA().fit(samples)
>>> model.n_endmembers
3
>>> model.diagnostics().to_frame()
>>> model.project(candidates)                        # U-space coordinates
fit(X)[source]

Fit on mixed water samples.

Candidate end-members are not part of the fit – they are projected in afterwards with project(). Including them would let them influence the subspace they are supposed to be tested against.

Parameters:

X (Any)

Return type:

EMMA

property k: int

the dimension of the mixing subspace.

Type:

Retained rank

property n_endmembers: int

k + 1 – the number of end-members the data require.

property eigenvalues_: ndarray
property scores_: ndarray

Mixed samples in U-space.

property fitted_: ndarray

Concentrations predicted by the rank-k mixing model.

property residuals_: ndarray
transform(X)[source]

Project any water into the fitted U-space (samples or end-members alike).

Parameters:

X (Any)

Return type:

ndarray

project(X)

Alias reading better when the argument is a set of candidate end-members.

Parameters:

X (Any)

Return type:

ndarray

inverse_transform(U)[source]

Map U-space coordinates back to concentrations.

Parameters:

U (ndarray)

Return type:

ndarray

subspace_distance(X)[source]

Distance of each water from the mixing subspace, in standardised units.

Parameters:

X (Any)

Return type:

ndarray

diagnostics(**kwargs)[source]

Per-species relative bias and RRMSE of the rank-k model (Hooper, 2003).

Parameters:

kwargs (Any)

Return type:

DiagnosticsReport

residual_structure(alpha=0.05)[source]

Test each species’ residuals for structure – the real lack-of-fit check.

Parameters:

alpha (float)

Return type:

pd.DataFrame

rank_summary()[source]

Every rank-retention criterion side by side.

Return type:

pd.DataFrame

loadings_frame()[source]

Eigenvector loadings: which species drive which component.

Return type:

pd.DataFrame

screen_candidates(candidates)[source]

Score candidate end-members for extremeness and subspace membership.

Parameters:

candidates (Any)

Return type:

pd.DataFrame

suggest_endmembers(candidates, n_endmembers=None)[source]

Rank combinations of candidates by how well they bound the samples.

Parameters:
  • candidates (Any)

  • n_endmembers (int | None)

Return type:

pd.DataFrame

archetypes(n_archetypes=None, *, n_restarts=10, seed=0, max_iter=200, tol=1e-06)[source]

Propose end-member candidates by archetypal analysis in the fitted U-space.

suggest_endmembers() picks vertices from candidates you supply; this asks what the best k+1 vertices would be if the data chose them. Use it as a check on your candidates – do the algorithm’s vertices look like the sources your conceptual model named, before you looked? – and as a fallback when you have no candidate waters at all.

Read mescla.emma.archetypes before using the output. In short: the weights are not mixing ratios, the archetypes are still biased inward relative to the true sources, the method proposes rather than discovers, and the objective is non-convex so the answer depends on seed.

Parameters:
Returns:

ArchetypeResult

Return type:

ArchetypeResult

Examples

>>> model = EMMA().fit(samples)
>>> arch = model.archetypes()
>>> print(arch.summary())                            # cautions included
>>> arch.archetypes_frame()                          # candidate compositions
>>> arch.support_frame()                             # how many samples support each
hull_fraction(endmembers)[source]

Fraction of samples enclosed by the given end-members in U-space.

Parameters:

endmembers (Any)

Return type:

float

summary()[source]

A readable paragraph describing the fit – paste it into your notes.

Return type:

str