Mapping API reference#

A mapping workflow retains every boundary explicitly:

reference_ref = reference_ds.mapping.build_reference(neighbors_ref)
reference = reference_ds.mapping.load_reference(reference_ref)
query_cells = query_ds.snapshot_cell_selection("I")
result_ref = query_ds.mapping.run(reference, query_cells)
result = query_ds.mapping.load_result(result_ref, reference=reference)
transfer_ref = query_ds.mapping.transfer_labels(
    result_ref,
    reference=reference,
    reference_labels="cell_type",
)
transfer = query_ds.mapping.load_label_transfer(transfer_ref)

MappingReference pins the exact feature selection and reference model. Query overlap is another feature-selection artifact. mapping.run returns only the projection ref; loaders, label transfer, score readers, and score plots require that ref plus the explicit reference. There is no named mapping registry, live cell_key routing, omitted-result lookup, or reference fallback.

A handle is validated against its store in full when mapping.load_reference loads it. Every later operation that takes the handle checks the stored artifact record and its attributes against the handle, validates the cell selection against the current ordered cell IDs, and recomputes the digest of the handle’s arrays. Repeated label transfer and score calls avoid reading the reference model payload, index and neighbours. Each operation also compares the prepared dataset fingerprint stored on the reference assay with the fingerprint the handle carries; an unprepared or different reference dataset is rejected. Reading reference cell metadata also validates the stored selection against the current ordered cell IDs. A handle whose arrays or references changed is rejected with does not match its stored artifact; reload it with mapping.load_reference.

A query projection records the prepared dataset fingerprint of the query assay and reuses a complete projection only for the same query dataset, cells, overlap, reference, and options. A query cell is uninformative when its raw counts are zero in every reference feature that the query measured. Such a cell keeps its projection row but is flagged in uninformative; it receives no transferred label, adds no mapping score, and does not enter Symphony query-batch statistics or queryScaledDispersion. diagnostics["uninformativeCellCount"] counts these cells. queryScaledDispersion averages the squared reference-scaled deviation of informative cells over the measured reference features only, so it does not depend on missing_feature_policy. Projections written before this contract are rejected with an instruction to re-run mapping.run.

Label transfer#

mapping.transfer_labels saves a label transfer as two query-owned artifacts. It first reads reference_labels, a cell-metadata column of the reference datastore or a cell-label artifact in it such as cluster_labels, cluster_cut, or clusters.relabel_by_overlap, and freezes those labels into the query datastore as a datastore-scoped reference_labels artifact. That artifact holds the reference classes and one class code per selected reference cell. Its identity records the mapping reference, the source column or the source artifact as an ExternalArtifactRef, and a fingerprint of the labels, so unchanged labels reuse one frozen copy and changed labels create another. A missing, blank, or masked reference label never votes.

It then saves a label_transfer artifact in the projection’s assay. Its inputs are the projection, the frozen reference labels, and the projection’s query cell selection; its parameters are threshold_fraction, max_distance, and the vote algorithm version. Each query cell takes the label with the largest share of its neighbours’ inverse-distance weight. A cell abstains when it is uninformative, has no labelled neighbour, ties between labels, falls below threshold_fraction, or has its nearest reference neighbour beyond max_distance. Abstention is stored as the linked missing mask of the labels array, never as a placeholder string, so a reference class named "NA" stays a class. The artifact also stores the reference classes, each cell’s neighbour votes, and the evidence below, and a payload fingerprint that loading verifies.

A complete transfer with the same projection, frozen labels, and decision rule is reused. A read-only query datastore raises PermissionError before anything is computed or written when no match exists. mapping.load_label_transfer reads only the query datastore, so a saved transfer loads without the reference and never changes when the reference annotations change. Because label_transfer is a cell-label artifact, it can colour an embedding, group statistical tests and plots, and seed select_cells like a clustering; consumers that need a label for every cell reject it while it contains abstentions. DataStore.artifacts.lineage(transfer_ref, references=reference) follows the transfer into the reference datastore.

LabelTransferResult.evidence has one row per projected query cell, in the order of cell_selection, with these columns:

Column

Meaning

label

Transferred label, missing where the cell abstained

candidateLabel

Label the vote favoured before the threshold and distance rules

voteFraction

Share of neighbour weight that supports the winning label

topTwoMargin

Winning share minus the runner-up share

voteEntropy

Entropy of the vote among labelled neighbours

nearestDistance

Distance to the nearest reference neighbour

referenceDistancePercentile

Percentile of that distance among reference nearest-neighbour distances

abstained

Whether the cell received no label

abstentionReason

uninformative_cell, no_labeled_neighbors, tied_vote, below_threshold, or beyond_max_distance

Vote metrics are NaN for uninformative cells. Projection-level diagnostics such as featureCoverage and queryScaledDispersion stay in mapping.load_result(...).diagnostics.

label_vote_shares(labels) returns each cell’s vote share for given labels, and prediction_sets(calibration_nonconformity, alpha) forms split-conformal prediction sets from the saved votes, calibrated with one minus those shares on held-out cells. Both need the per-neighbour vote matrices, which hold one column per saved neighbour, so mapping.load_label_transfer loads them only with load_votes=True. Each array that a load reads is checked against the digest recorded when the transfer was written.

class cytearc.MappingReference(datastore, ref, assay_name, reduction, ann_index, neighbors, cell_selection, feature_selection, batch_correction, dataset_fingerprint, selected_cell_count, model, symphony_state, feature_ids, metadata, reference_distance_quantiles, reference_distance_values, payload_fingerprint, model_digest)#

An immutable scaled-PCA reference loaded from a CyteArc Zarr store.

payload_fingerprint is the stored payload fingerprint the handle was loaded against and model_digest the digest of the arrays it was given; validate_mapping_reference_binding compares both with the store and with the handle instead of re-reading the payload.

current_model_digest()#

Recompute the digest of the arrays this handle holds.

Return type:

str

fetch_cell_column(column)#

Fetch one reference cell column through the stored cell selection.

Return type:

ndarray

validate_dataset_fingerprint()#

Check the reference assay against the fingerprint the handle carries.

Return type:

None

validate_frozen_axes()#

Validate the exact stored cell and feature axes used by the reference.

Return type:

None

class cytearc.MappingResult(ref, n_cells, correction_method, diagnostics, reference, indices=None, distances=None, uninformative=None)#

One loaded query projection and its optional neighbor arrays.

uninformative marks query cells whose raw counts are zero in every reference feature that the query measured. Their neighbor rows are stored but carry no query evidence, so label transfer and mapping scores skip them.

property cell_selection: ArtifactRef#

Exact frozen query-row selection for this loaded projection.

property feature_selection: ArtifactRef#

Exact frozen query-feature selection for this loaded projection.

class cytearc.LabelTransferResult(ref, projection, reference_labels, reference_label_source, cell_selection, cell_idx, threshold_fraction, max_distance, categories, evidence, vote_class_codes=None, vote_class_fractions=None)#

One loaded label transfer: transferred query labels and their evidence.

evidence has one row per projected query cell, in the order of cell_selection; cell_idx gives the matching query cell rows. label is the transferred label and is missing where the cell abstained. abstentionReason says why a cell abstained: uninformative_cell (no counts in any measured reference feature), no_labeled_neighbors, tied_vote, below_threshold (voteFraction below threshold_fraction), or beyond_max_distance (nearestDistance above max_distance). candidateLabel is the label that the vote favored before the threshold and distance rules, so other thresholds can be compared without a new transfer.

reference_labels is the frozen copy of the reference labels in the query datastore, and reference_label_source names where they were read: a reference cell-metadata column, or a reference label artifact. vote_class_codes and vote_class_fractions hold, for each cell, the reference classes that its neighbors voted for, as positions in categories, padded with -1, and each class’s share of the neighbor weight. These matrices hold one column per saved neighbor, so they are loaded only when requested, with mapping.load_label_transfer(transfer, load_votes=True); label_vote_shares() and prediction_sets() need them.

label_vote_shares(labels)#

Return each cell’s share of neighbor vote weight for a given label.

labels holds one label per projected query cell, such as the known labels of held-out calibration cells. A label that is not a reference class has a share of zero. Missing labels and uninformative cells give NaN. One minus these shares is the nonconformity that prediction_sets() calibrates with.

Return type:

ndarray

property labels: Series#

Transferred labels, missing where a cell abstained.

property n_cells: int#

Number of projected query cells.

prediction_sets(calibration_nonconformity, alpha=0.1)#

Return split-conformal prediction sets from the stored votes.

calibration_nonconformity holds one minus the vote share of the true label for held-out calibration cells, which must be exchangeable with these query cells; label_vote_shares() computes those shares. A class joins a cell’s set when its nonconformity is not exceeded by more than a fraction alpha of the calibration cells. Cells without labeled votes get an empty set.

Return type:

Series

DataStore methods#

cytearc.datastore.namespaces.MappingAccessor.build_reference

Package a scaled-PCA neighbor chain as an immutable artifact.

cytearc.datastore.namespaces.MappingAccessor.load_reference

Load one mapping reference from an explicit artifact.

cytearc.datastore.namespaces.MappingAccessor.run

Map selected query cells into an immutable prepared reference.

cytearc.datastore.namespaces.MappingAccessor.load_result

Load one complete query-owned mapping projection.

cytearc.datastore.namespaces.MappingAccessor.compute_scores

Yield reference-sized mapping scores for each requested query group.

cytearc.datastore.namespaces.MappingAccessor.transfer_labels

Transfer reference labels to projected query cells and save the result.

cytearc.datastore.namespaces.MappingAccessor.load_label_transfer

Load one complete label transfer from this query datastore.

MappingAccessor.build_reference(neighbors, *, invalidate_cache=False)#

Package a scaled-PCA neighbor chain as an immutable artifact.

Return type:

ArtifactRef

MappingAccessor.load_reference(reference)#

Load one mapping reference from an explicit artifact.

Return type:

MappingReference

MappingAccessor.run(reference, cell_selection, *, query_assay=None, save_k=3, missing_feature_policy='reference_mean', query_batches=None, invalidate_cache=False)#

Map selected query cells into an immutable prepared reference.

A query cell whose raw counts are zero in every reference feature that the query measured is recorded as uninformative. It keeps a projection row but is excluded from label transfer, mapping scores, Symphony query-batch statistics, and queryScaledDispersion.

Raises:

UnmeasuredCellsError – If the query assay did not measure a selected cell.

Return type:

ArtifactRef

MappingAccessor.load_result(result, *, reference, load_arrays=False)#

Load one complete query-owned mapping projection.

Return type:

MappingResult

MappingAccessor.compute_scores(result, target_groups=None, *, reference, log_transform=True, multiplier=1000, weighted=True, fixed_weight=0.1)#

Yield reference-sized mapping scores for each requested query group.

Return type:

Generator[tuple[Any, ndarray], None, None]

MappingAccessor.transfer_labels(projection, *, reference, reference_labels, threshold_fraction=0.5, max_distance=None, invalidate_cache=False)#

Transfer reference labels to projected query cells and save the result.

The reference labels are first frozen into this query datastore as a reference_labels artifact, so a later change to the reference cannot change a saved transfer. Each query cell then takes the label with the largest share of its neighbors’ inverse-distance weight. A cell abstains, and its label is missing, when it is uninformative, no neighbor has a usable label, two labels tie, the winning share is below threshold_fraction, or its nearest reference neighbor is farther than max_distance. A high vote share means that the neighbors agree; it is not a calibrated probability.

A complete transfer with the same projection, reference labels, and decision rule is reused.

Parameters:
  • projection (ArtifactRef) – Query projection returned by run().

  • reference (MappingReference) – The mapping reference that the projection used.

  • reference_labels (str | ArtifactRef) – A cell-metadata column of the reference datastore, or a cell-label artifact in it, such as cluster_labels, cluster_cut, or smart_label.

  • threshold_fraction (float) – Smallest winning vote share that assigns a label.

  • max_distance (float | None) – Largest distance to the nearest reference neighbor that assigns a label. None sets no distance limit.

  • invalidate_cache (bool) – Compute a new transfer even when a matching one exists. Frozen reference labels with the same fingerprint are still reused, because they are an exact copy.

Return type:

ArtifactRef

Returns:

Reference to the immutable label_transfer artifact. Load it with load_label_transfer(), or use it wherever a cell-label artifact is accepted, such as color_by of an embedding plot.

Raises:

PermissionError – If no matching transfer exists and the query datastore is not opened with zarr_mode='r+'.

MappingAccessor.load_label_transfer(transfer, *, load_votes=False)#

Load one complete label transfer from this query datastore.

Loading reads only this datastore, so the reference datastore is not needed and later changes to it do not change the result.

Parameters:
  • transfer (ArtifactRef) – Label transfer returned by transfer_labels().

  • load_votes (bool) – Also load each cell’s neighbor votes, which label_vote_shares and prediction_sets need. The vote matrices hold one column per saved neighbor, so they are skipped by default.

Return type:

LabelTransferResult

Returns:

The transferred labels, their evidence, and the exact inputs.

Mapping diagnostics are documented in the Plotting API reference API reference.