CellMapper is a Python package for k-NN-based mapping of cells across representations to transfer labels, embeddings, and expression values. It works for millions of cells, on CPU and GPU, across molecular modalities, and between spatial and non-spatial data. The core idea is to separate the method (k-NN graph + kernel → mapping matrix) from the application (transfer across arbitrary representations). Key frameworks: AnnData/Scanpy, numpy/scipy, scikit-learn, pynndescent, faiss, RAPIDS cuML.
When sources disagree:
- PR description and changed code
- This file (
AGENTS.md) REVIEW_GUIDE.md- Tests and fixtures
- Public docs in
docs/andREADME.md
Every fact should have one owner. This file owns invariants and the reference table below — everything else is delegated.
| Topic | Source of truth |
|---|---|
| User-facing overview, use cases, quickstart | README.md |
| Public API reference | docs/api.md and autosummary under docs/generated/ |
| Tutorials (query→reference, spatial mapping, spatial smoothing, data denoising) | docs/notebooks/tutorials/ |
| Contributor setup, environments, docs build | docs/contributing.md |
| Release notes | docs/changelog.md |
| PR review workflow and risk areas | REVIEW_GUIDE.md |
| Test fixtures | tests/conftest.py, tests/data/ |
| Kernel taxonomy and tunable thresholds (sklearn warning cutoff, spectral threshold) | src/cellmapper/constants.py |
| Optional-dependency gating | src/cellmapper/check.py |
| Method-level behavior (parameters, return shapes) | docstrings in src/cellmapper/model/ |
For GitHub PR reviews, use REVIEW_GUIDE.md as the canonical review workflow and
source of review-specific risk areas, testing checks, and documentation-impact checks.
This file only owns the project invariants and source-of-truth map below.
- Self-mapping mode activates when
reference is Noneorreference is query(object identity). SeeCellMapper.__init__insrc/cellmapper/model/cellmapper.py. - Reference is read-only.
.map()never mutates the reference AnnData.queryis mutated in place formap_obs/map_obsm. Expression transfer produces a separatequery_imputedAnnData object, not a view. - Output key naming follows
{key}{prediction_postfix}and{key}{confidence_postfix}inquery.obs/query.obsm. Postfixes are user-controllable on the per-method entrypoints (map_obs,map_obsm);.map()also exposesprediction_postfix. .map()auto-chainscompute_neighbors→compute_mapping_matrix→map_obs/obsm/layersbased on missing state. Callers that use these methods directly must respect that ordering.- Mapping matrix is row-stochastic and float32. Sparse inputs are stored as
scipy.sparse.csr_matrix; dense inputs stay dense. Zero-neighbor rows are left as-is. SeeMappingOperator._validate_and_normalize_mapping_matrix. - Matrix powers
t > 1are self-mapping-only (MappingOperator._validate_powerraises otherwise). - Optional k-NN backends fail fast.
check.check_deps()is called at backend construction with clear install hints — no silent fallback. Supported backends:sklearn,pynndescent,faiss-cpu,faiss-gpu,rapids. - Kernel taxonomy lives in
constants.py(JACCARD_BASED_KERNELS,CONNECTIVITY_BASED_KERNELS,SELF_MAPPING_ONLY_KERNELS). Kernels inSELF_MAPPING_ONLY_KERNELSrequire a square neighbor matrix. Neighborsstrips self-edges from storage for square matrices;n_neighborscounts non-self neighbors.query_imputedis always assembled viautils.create_imputed_anndata. Setter acceptsAnnData | ndarray | csr_matrix | DataFrame | None; result hasobs/obsmfrom query andvar/varmfrom reference.- Public API surface =
__init__.py__all__:CellMapper,Kernel,Neighbors,logger.EvaluationMixinandEmbeddingMixinare internal. Do not re-export helpers from the top-level package. - Tests mirror source layout.
src/cellmapper/X.py→tests/test_X.py;src/cellmapper/model/X.py→tests/model/test_X.py.
Python 3.12 and 3.14 (see the hatch-test matrix in pyproject.toml).
hatch test # run tests (highest Python)
hatch test --all # full matrix
hatch run docs:build # build Sphinx docs
pre-commit run --all-files # lint and formatFocused runs (with uv):
uv run pytest tests/model
uv run pytest tests/model/test_mapping_operator.py
uv run pytest tests/test_utils.py