Topography UMAP API¶
Project components from a newly-trained model into the published pan-cancer topography UMAP — a shared space built from each component’s normalized mutation-rate profile across chr2 10 kb bins.
Requires the optional umap-learn dependency:
pip install mutopia[umap]
Quick start¶
import mutopia.analysis as mu
# Layout only: ~15 kB, pandas alone, no umap-learn needed.
coords = mu.load_reference_coordinates()
# The full projector.
ref = mu.load_reference_umap()
data = mu.gt.load_dataset("my_cohort.annotated.nc", with_samples=False)
ref.transform(data) # coordinates, topo-cluster, novelty score
ref.kneighbors(data, k=5) # nearest reference components
Projecting a model trained on a different grid¶
The reference feature space is defined on a specific ordered locus axis — the
same regions bed and the same mesoscale features. A gTensor built differently
cannot be matched to it, because mesoscale-split loci share (chrom, start)
and no stored column separates them.
A model, however, is a function of genomic features, so evaluate it on a reference-axis gTensor instead and the projection stays on the strict path:
model = mu.load_model("my_cohort.model.pkl")
grid = mu.gt.load_dataset(reference_nc, with_samples=False, with_state=False)
ref.transform_model(model, grid)
ref.kneighbors_model(model, grid, k=5)
# The annotated gTensor itself, e.g. for mutopia.plot.track_plot
annotated = mu.annot_component_rates(model, grid)
Pass with_state=False: a previous model’s corpus state must be shed, and the
pan-cancer models convolve each feature over neighbouring bins, leaving a
51-long feature coordinate that a different model will reject.
Interpreting the output¶
The 2D coordinates are for display. transform is an approximate
re-optimization of new points against a frozen layout of a few hundred points.
The nearest-neighbour table and the cluster vote — both computed in the
full-dimensional cosine space — are the defensible readouts.
Two failure modes are reported explicitly, because neither is visible in the coordinates:
is_outlier/outlier_scoreA local outlier factor over the reference. Structureless input (noise, shuffled loci) still lands somewhere plausible and receives a confident cluster call; this is what catches it. Nearest-neighbour distance does not, because a bland profile sits near the centroid where the reference is densest.
set_is_degenerate/set_spreadA set-level check. Components that are near-identical to one another each land beside whatever reference point is closest to the centroid, and every per-component statistic looks normal. This fires when the projected set’s median pairwise cosine distance falls below that of the least diverse reference cohort.
Limitations¶
The reference space is chr2 only; a new gTensor must span it.
Cluster labels are hand-curated, so the k-NN vote’s in-sample ceiling is ~0.82, not 1.0.
on_grid_mismatch="aggregate"exists for gTensors that cannot match the axis, but is lossy — pairwise cosine distances correlate r = 0.89 with the raw axis and only 61% of components keep the same nearest neighbour. It warns at runtime. Prefer the model route above.
Reference¶
- class mutopia.analysis.topography_umap.TopographyUMAP(n_neighbors=5, min_dist=0.1, random_state=101, negative_sample_rate=3, metric='cosine', n_components=2, cluster_n_neighbors=10, on_grid_mismatch='error', min_bin_coverage=0.9, outlier_quantile=0.99)[source]¶
Bases:
BaseEstimatorReference UMAP of component topographies, with projection of new components.
- Parameters:
n_neighbors – Passed straight to
umap.UMAP. The defaults are the parameters the pan-cancer reference space was built with.min_dist – Passed straight to
umap.UMAP. The defaults are the parameters the pan-cancer reference space was built with.random_state – Passed straight to
umap.UMAP. The defaults are the parameters the pan-cancer reference space was built with.negative_sample_rate – Passed straight to
umap.UMAP. The defaults are the parameters the pan-cancer reference space was built with.metric – Passed straight to
umap.UMAP. The defaults are the parameters the pan-cancer reference space was built with.n_components – Passed straight to
umap.UMAP. The defaults are the parameters the pan-cancer reference space was built with.cluster_n_neighbors (int, default=10) – Neighbours used for the k-NN cluster vote. The vote happens in the full feature space, matching how the reference clusters were defined.
on_grid_mismatch ({"error", "aggregate"}, default="error") – What to do when an incoming dataset’s locus axis does not reproduce the reference axis.
"error"raises and explains."aggregate"falls back to a second, lossy reference space in which mesoscale-split loci are pooled into unique(chrom, start)bins – see_aggregate_space()for the measured cost.min_bin_coverage (float, default=0.9) – Under
"aggregate", the minimum fraction of aggregated reference bins that must receive data before the projection is refused.outlier_quantile (float, default=0.99) – Quantile of the reference’s own local-outlier-factor scores used as the
is_outlierthreshold.
- reducer_¶
The fitted reducer.
reducer_.embedding_is the reference layout.- Type:
umap.UMAP
- X_ref_¶
- Type:
ndarray of shape (n_reference, n_bins)
- embedding_¶
- Type:
ndarray of shape (n_reference, n_components)
- components_¶
- Type:
ndarray of str
- metadata_¶
- Type:
DataFrame indexed by component
- bin_chrom_, bin_start_, bin_length_
The reference locus axis. Note that
(chrom, start)is not unique: mesoscale features split a bin into several loci sharing coordinates. The axis is matched positionally – see_axis_matches().- Type:
ndarray
- build_features(dataset, source=None)[source]¶
Turn a gTensor into a reference-aligned feature matrix.
- Returns:
X (ndarray of shape (n_components, n_bins), float32)
components (ndarray of str)
space ({“strict”, “aggregate”}) – Which reference space
Xlives in.
- features_from_model(model, dataset, source=None, threads=1)[source]¶
Reference-aligned features for a trained model, via
annot_component_rates().Use when the model was trained on a different regions bed than the reference: evaluating it on a reference-axis gTensor keeps the projection on the strict path.
- fit(data, metadata=None, source=None, bins=None, embedding=None)[source]¶
Fit the reference space.
- Parameters:
data (gTensor Dataset, or (X, components) tuple) – When a tuple is passed,
binsmust give the(chrom, start, length)locus axis its columns correspond to.metadata (DataFrame, optional) – Indexed by component;
tumor_type/class/cluster_id/cluster_namecolumns are carried into the outputs.embedding (ndarray, optional) – Pin the reference layout to these coordinates instead of the fitted ones. Used to preserve a published layout that a current
umap-learnno longer reproduces bit-for-bit;transformoptimizes new points againstembedding_held fixed, so any fixed layout of the reference points defines a valid projection.
- kneighbors(data, k=10, source=None)[source]¶
Nearest reference components for each input component (long form).
This is the most robust readout – it depends only on cosine distance in the original feature space, not on UMAP’s approximate
transform.
- kneighbors_model(model, dataset, k=10, source=None, threads=1)[source]¶
Nearest reference components for a trained model’s components.
- classmethod load(path, verify=True, atol=0.001)[source]¶
Rebuild a reference space from a
.npzwritten bysave().
- predict_cluster(data, source=None)[source]¶
k-NN vote for the topography cluster, in the full feature space.
- save(path, provenance=None, dtype=<class 'numpy.float16'>)[source]¶
Write the reference space to a compressed
.npz.The fitted
umap.UMAPis deliberately not pickled – it carries apynndescentindex with numba-typed internals whose unpickling is fragile across umap/numba versions.load_reference_umap()reconstructs the reducer by refitting on the stored matrix, which is cheap at reference scale and version-robust.
- set_fit_request(*, bins='$UNCHANGED$', data='$UNCHANGED$', embedding='$UNCHANGED$', metadata='$UNCHANGED$', source='$UNCHANGED$')¶
Request metadata passed to the
fitmethod.Note that this method is only relevant if
enable_metadata_routing=True(seesklearn.set_config()). Please see User Guide on how the routing mechanism works.The options for each parameter are:
True: metadata is requested, and passed tofitif provided. The request is ignored if metadata is not provided.False: metadata is not requested and the meta-estimator will not pass it tofit.None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.str: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (
sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.Added in version 1.3.
Note
This method is only relevant if this estimator is used as a sub-estimator of a meta-estimator, e.g. used inside a
Pipeline. Otherwise it has no effect.- Parameters:
bins (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
binsparameter infit.data (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
dataparameter infit.embedding (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
embeddingparameter infit.metadata (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
metadataparameter infit.source (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
sourceparameter infit.
- Returns:
self – The updated object.
- Return type:
object
- set_transform_request(*, data='$UNCHANGED$', source='$UNCHANGED$')¶
Request metadata passed to the
transformmethod.Note that this method is only relevant if
enable_metadata_routing=True(seesklearn.set_config()). Please see User Guide on how the routing mechanism works.The options for each parameter are:
True: metadata is requested, and passed totransformif provided. The request is ignored if metadata is not provided.False: metadata is not requested and the meta-estimator will not pass it totransform.None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.str: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (
sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.Added in version 1.3.
Note
This method is only relevant if this estimator is used as a sub-estimator of a meta-estimator, e.g. used inside a
Pipeline. Otherwise it has no effect.- Parameters:
data (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
dataparameter intransform.source (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
sourceparameter intransform.
- Returns:
self – The updated object.
- Return type:
object
- transform(data, source=None)[source]¶
Project components into the reference layout.
- Returns:
DataFrame indexed by component with the embedding coordinates, the
predicted cluster, the nearest reference component and its cosine
distance, and a local-outlier-factor novelty score with its flag.
- transform_model(model, dataset, source=None, threads=1)[source]¶
Project a trained model’s components, evaluating it on
dataset’s axis.>>> ref = mu.load_reference_umap() >>> model = mu.load_model("my_cohort.model.pkl") >>> grid = mu.gt.load_dataset(reference_nc, with_samples=False, with_state=False) >>> ref.transform_model(model, grid)
- property umap_params¶
- write_coordinates(path)[source]¶
Write the coordinates-only fixture read by
load_reference_coordinates().
- mutopia.analysis.topography_umap.load_reference_umap(path=None, verify=False, download=True)[source]¶
Load the pan-cancer topography UMAP reference.
The ~11 MB feature matrix is a release asset, not a committed file, so the first call downloads it and caches it under
~/.cache/mutopia(override withMUTOPIA_CACHE_DIR). Subsequent calls are local. A source checkout that has already built the artifact in place uses that copy instead.If you only need the layout – to draw it, or to check coordinates – use
load_reference_coordinates(), which ships in the wheel and needs neither the download norumap-learn.- Parameters:
path (str, optional) – Explicit artifact to load, bypassing discovery and download.
verify (bool, default=False) – Refit UMAP on the reference matrix and warn if this environment does not reproduce the stored layout. Off by default because it doubles load time.
download (bool, default=True) – Whether to fetch the artifact when it is not already present.
- mutopia.analysis.topography_umap.load_reference_coordinates(path=None)[source]¶
The canonical reference layout as a DataFrame – coordinates only.
The full artifact carries an 11 MB feature matrix and needs
umap-learnto rebuild its reducer, which is a lot to pay for drawing the backdrop of a plot or asserting against fixed coordinates in a test. This reads a small TSV with pandas alone.Use it to plot the reference space or to check published coordinates; use
load_reference_umap()when you need to project new components.- Returns:
DataFrame indexed by component, with
tumor_type,class,cluster_id,cluster_name,UMAP1andUMAP2.
- mutopia.analysis.topography_umap.annot_component_rates(model, dataset, source=None, threads=1, key='component_distributions_locus')[source]¶
Evaluate a trained model’s component locus rates on any gTensor’s axis.
model.annot_component_distributionsroutes throughsetup_corpus, which initializes the locals model and therefore iterates the dataset’s samples. Datasets written withwrite_samples=Falsehave norawgroup, so that path raisesValueError: Sample ... not found— for every model, not just unusual ones. Component locus distributions depend only on the factor model (context + theta), so this initializes just that half and skips the sample-dependent step.The point of doing this is comparability. A model is a function of genomic features, so evaluating it on the reference gTensor puts its components on the reference locus axis — which lets
TopographyUMAP.transform()take the strict path instead of the lossy aggregate one, even when the model was trained on a completely different regions bed.- Parameters:
model (TopographyModel) – A trained model, e.g. from
mu.load_model(...).dataset (gTensor Dataset) – The axis to evaluate on. Load it with
with_state=Falseso the previous model’s corpus state is shed (mu.gt.load_dataset(path, with_samples=False, with_state=False)).source (str, optional) – Cell type / source for multi-source models.
- Returns:
The dataset with
component_distributions_locusadded, dims(component, locus)andcomponentcoordinates taken frommodel.component_names. Suitable forTopographyUMAP.transform()and formutopia.plot.track_plot.