本文へ移動
cccskills
無料GitHub で公開

bio-machine-learning-atlas-mapping

Maps query single-cell data onto reference atlases and transfers cell-type labels using scArches surgery (scVI/scANVI), Symphony, Azimuth, CellTypist, scPoli, popV, and foundation models, with explicit out-of-distribution and label-transfer uncertainty. Use when annotating new single-cell datasets against a pre-trained reference, deciding which mapping method fits, or judging whether transferred labels are trustworthy. For de novo clustering and manual annotation see single-cell/cell-annotation; for batch integration without a reference see single-cell/batch-integration.

インストール方法を見る

含まれるファイル(4)

  • SKILL.md20.1 KB
  • examples/ood_gating_demo.py2.5 KB
  • examples/scarches_annotation.py2.2 KB
  • usage-guide.md4.1 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Version Compatibility

Reference examples tested with: anndata 0.10+, scanpy 1.10+, scvi-tools 1.1+, scikit-learn 1.3+, celltypist 1.6+.

Before using code patterns, verify installed versions match. If versions differ:

  • Python: pip show <package> then help(module.function) to check signatures

scvi-tools 1.x has had API churn around minified/registered models and the semi-supervised loader. Confirm scvi.__version__ and help(scvi.model.SCANVI.load_query_data) before relying on argument names. If code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.

Reference Mapping and Label Transfer for Single-Cell Data

"Annotate my scRNA-seq query against a reference atlas" -> Project query cells into a fixed reference latent space and transfer labels, then gate every label on an out-of-distribution signal.

  • scArches surgery: scvi.model.SCANVI.prepare_query_anndata() -> load_query_data() -> train(plan_kwargs={'weight_decay': 0.0}) -> predict(soft=True)
  • Linear/fixed reference: Symphony (R) or Azimuth/Seurat anchor transfer
  • Pure classifier (no embedding): CellTypist logistic regression

The Single Most Important Modern Insight -- Mapping Is a Projection, Not an Annotation Oracle

Reference mapping indicates where in a fixed reference manifold a query cell lands; it does not establish whether that location is biologically meaningful for the query. The projection always succeeds geometrically: every query cell is assigned its nearest reference label whether or not that label is true. A softmax over reference classes is normalized to sum to 1 and therefore cannot express "I have never seen this cell" -- a hepatocyte handed to an immune reference gets confidently called a T cell. Every failure mode below is a corollary of confusing projection with annotation.

The operational consequence: a transferred label is untrustworthy until paired with an out-of-distribution / label-transfer-uncertainty signal that measures whether the cell belongs to the reference at all, which is a different quantity from the prediction probability that measures which reference label. Conflating these two is the field's most common error.

Methods Taxonomy

MethodModel classNeeds reference model?Novel-cell-type signalBest whenFails when
scVI + scArches surgeryConditional VAE; surgery freezes reference weights, fits query-batch nodesYes (saved scVI model)None intrinsic; add kNN uncertainty / OOD distanceUnseen batch; want a de novo joint embedding then cluster query yourselfExpected to label (it only embeds); reference lacks query biology
scANVI + scArches surgerySemi-supervised VAE (scVI latent + label classifier head)Yes (scANVI, often from_scvi_model)Classifier softmax (overconfident); kNN-on-latent uncertaintyReference well-labeled, query is the same tissue/biologySemi-supervised leakage carves latent; novel states confidently mislabeled
SymphonyLinear Harmony soft-cluster mixture; query projected into fixed referenceYes (compressed reference object)Per-cell Mahalanobis distance to soft-cluster centroidsSeconds-scale, deterministic, CPU-only, reproducible/clinicalStrong nonlinear batch the reference never saw
Azimuth / Seurat anchor transferCCA/PCA anchors; supervised PCA projectionYes (precomputed ref)prediction.score.max, mapping.scoreMultimodal refs (CITE-seq/WNN), curated tissue atlases, R shopFiltered-anchor pathology when query is very divergent
scPoliConditional VAE + learnable sample embeddings + cell-type prototypesYes (built on scArches)Prototype distance + uncertaintyWant sample-level (patient) embeddings too, many small batchesFew samples (condition embedding underdetermined)
popVEnsemble of methods + ontology-aware votingMixed (wraps several)Cross-method disagreement = uncertaintyHigh-stakes atlas annotation; distrust any single methodCompute-heavy; consensus can be confidently wrong if all share reference bias
CellTypistLogistic regression (pre-trained models)No embedding (ships models)Low max-probability = ambiguous; no true OODFast immune annotation, no integration neededTreated as a mapper (no shared embedding, no batch handling)
treeArches / scHPLscArches + hierarchical classifier with rejectionYesExplicit rejection -> "unseen" nodeExpect novel subtypes, want hierarchy-aware fallbackMis-specified hierarchy propagates error down branches
Foundation models (scGPT, Geneformer)Transformer pretrained on 10s of millions of cellsCheckpoint; fine-tune needs labelsNone intrinsic; OOD poorly characterizedFine-tuned on the target task; cross-modality/species; data-scarceZero-shot: underperform scVI/Harmony/HVG-PCA (Kedzierska 2025)

Cross-cutting: linear methods (Symphony, Azimuth-sPCA) give a fixed, reproducible reference embedding (the query never perturbs the reference); VAE surgery fine-tunes and can drift. Reproducibility-critical or clinical pipelines lean linear; maximal batch-effect flexibility leans VAE.

Decision Tree by Scenario

ScenarioRecommended approachWhy
Same tissue as a published scVI/scANVI atlas; want one embedding + labelsscArches surgery onto the scANVI model; then gate labels on kNN uncertaintyBuilt for this; reuses the learned manifold; only query fine-tuned
Seconds-scale, deterministic, CPU-only, must re-run identically (clinical)Symphony (or Azimuth if curated)Fixed reference embedding, no fine-tuning drift, built-in Mahalanobis OOD
Query likely contains cell types/states NOT in the reference (disease, new niche)treeArches/scHPL rejection, or scArches + explicit OOD distanceDefault kNN/softmax confidently mislabels novel cells
High-stakes annotation; distrust any single methodpopV ensembleCross-method disagreement is a more honest uncertainty than any softmax
Want patient/sample-level structure tooscPoliOnly method learning sample (condition) embeddings jointly with cell prototypes
Just need fast immune labels, no integrationCellTypist (Immune_All_Low, majority_voting=True)Calibrated classifier, no embedding needed; QC the query first
Multimodal reference (CITE-seq/ATAC)Azimuth/Seurat WNN or totalVI+scArchesAnchor framework natively weights modalities
Considering scGPT/GeneformerOnly if fine-tuning with labels, or cross-modality/species, or data too scarceZero-shot foundation embeddings are not a justified default for same-tissue transfer
De novo clustering, no reference, or manual marker annotation-> single-cell/markers-annotation, single-cell/clusteringOut of scope here

scArches Surgery: Embedding (scVI)

Goal: Project query cells into a pre-trained reference latent space without retraining on combined data.

Approach: Align query genes to the reference exactly, load into the frozen reference model, and fine-tune only query-specific parameters with zero weight decay so the shared manifold does not drift.

import scvi
import scanpy as sc

ref_model = scvi.model.SCVI.load('reference_model/')          # saved with save_anndata=True (or minified)

adata_query = sc.read_h5ad('query.h5ad')
# Align genes to the reference EXACTLY: zero-pad missing, reorder. Mandatory and silent if skipped.
scvi.model.SCVI.prepare_query_anndata(adata_query, 'reference_model/')

query_model = scvi.model.SCVI.load_query_data(adata_query, 'reference_model/')
# weight_decay=0.0 + frozen reference weights make surgery a query-only fine-tune;
# non-zero decay drifts the shared latent and breaks cross-query comparability.
query_model.train(max_epochs=200, plan_kwargs={'weight_decay': 0.0}, check_val_every_n_epoch=10)
adata_query.obsm['X_scVI'] = query_model.get_latent_representation()

scANVI Label Transfer

Goal: Transfer reference cell-type labels to an unlabeled query.

Approach: Build a semi-supervised scANVI head on the reference, map the query by surgery, then read hard labels and per-class probabilities -- treating the probability as "which label," not "does it belong."

# Reference side (once): scANVI from a trained scVI model. unlabeled_category is REQUIRED.
ref_scanvi = scvi.model.SCANVI.from_scvi_model(ref_vae, unlabeled_category='Unknown', labels_key='cell_type')
ref_scanvi.train(max_epochs=20, n_samples_per_label=100)
ref_scanvi.save('ref_scanvi/', save_anndata=True)

# Query side (surgery):
scvi.model.SCANVI.prepare_query_anndata(adata_query, 'ref_scanvi/')
query_scanvi = scvi.model.SCANVI.load_query_data(adata_query, 'ref_scanvi/')
query_scanvi.train(max_epochs=100, plan_kwargs={'weight_decay': 0.0})

adata_query.obs['predicted_label'] = query_scanvi.predict()          # hard labels
adata_query.obsm['X_scANVI'] = query_scanvi.get_latent_representation()
proba = query_scanvi.predict(soft=True)                             # per-class probabilities (which label)

Out-of-Distribution Gating (the step that makes labels trustworthy)

Goal: Decide whether each query cell belongs to the reference, separately from which label it would get.

Approach: Compute a distance/entropy signal on the shared latent. The canonical scArches/HLCA approach is a weighted-kNN label-transfer uncertainty (neighbor disagreement in the reference latent), thresholded at 0.2 to set cells to "Unknown." A portable kNN-entropy version is shown; the softmax proba is NOT this signal.

import numpy as np
from sklearn.neighbors import KNeighborsClassifier

ref_latent = ref_scanvi.get_latent_representation()                  # reference cells in latent
knn = KNeighborsClassifier(n_neighbors=15, weights='distance').fit(ref_latent, adata_ref.obs['cell_type'])
query_latent = adata_query.obsm['X_scANVI']

neighbor_proba = knn.predict_proba(query_latent)                    # weighted neighbor label distribution
# Uncertainty = 1 - max neighbor agreement. HLCA sets cells above 0.2 to 'Unknown'.
uncertainty = 1.0 - neighbor_proba.max(axis=1)
adata_query.obs['transfer_uncertainty'] = uncertainty
adata_query.obs.loc[uncertainty > 0.2, 'predicted_label'] = 'Unknown'   # gate, do not trust ungated labels
print(f'Flagged Unknown: {(uncertainty > 0.2).mean():.1%}')

Per-Method Failure Modes

scANVI / kNN -- forcing the query onto reference labels

  • Trigger: Query contains a population absent from the reference (novel type, disease state, perturbed program).
  • Mechanism: The classifier/kNN assigns every query cell to its nearest reference label; there is no "none of the above" unless added.
  • Symptom: A coherent novel cluster split across 2-3 reference labels, each with high probability; the UMAP looks "well integrated."
  • Fix: Always gate on transfer uncertainty / OOD distance (above). Inspect query-only clusters for marker genes independent of transferred labels.

Softmax overconfidence vs label-transfer uncertainty conflated

  • Trigger: Reporting "confidence" as the predict(soft=True) max.
  • Mechanism: The softmax measures which reference label conditional on belonging; it is normalized away from distance and cannot say "far from everything." A cell can be 0.99 "T cell" and be a hepatocyte.
  • Symptom: Pipeline filters on softmax >= 0.5 and still passes OOD cells.
  • Fix: Threshold the weighted-kNN uncertainty (HLCA 0.2) or a Mahalanobis/ensemble OOD signal for the "Unknown" decision; use the softmax only to disambiguate among in-distribution labels.

scANVI -- semi-supervised label leakage / latent carving

  • Trigger: scANVI reference where labels strongly drive latent geometry; trajectory or novel-state query.
  • Mechanism: The classifier head back-propagates label structure into the latent, carving it to separate reference types; query cells are pulled toward that structure even when their biology lies between/outside it.
  • Symptom: A query continuum (differentiation trajectory) collapses onto discrete reference clusters; intermediate states vanish.
  • Fix: For trajectory/novel-state queries prefer unsupervised scVI surgery, annotate the query independently, and cross-check against the scVI latent.

Reference composition / missing-biology bias

  • Trigger: Reference from healthy/limited donors; query from disease, different age, ancestry, or tissue region.
  • Mechanism: The reference manifold is the entire hypothesis space; off-manifold cells are projected onto the nearest on-manifold point and rare reference populations act as attractors.
  • Symptom: Disease-specific states labeled as the closest healthy type; ancestry/age effects read as "batch."
  • Fix: Audit reference composition before mapping; prefer references covering the query's expected biology; treat mapping as hypothesis generation and validate query findings de novo; consider extending the reference (treeArches).

Query QC artifacts laundered into confident labels

  • Trigger: Query not QC'd to the reference's standard (empty droplets, ambient RNA, doublets, high-MT).
  • Mechanism: A doublet sits between two reference types and maps to a spurious "intermediate"; ambient RNA shifts profiles toward the dominant type.
  • Symptom: Artifactual "transitional" populations; doublet clusters labeled as rare real types.
  • Fix: Run full query QC before mapping (single-cell/doublet-detection, ambient correction, MT/count filters matched to the reference). Mapping does not clean data.

Feature-space / gene-set mismatch

  • Trigger: Query missing reference HVGs; different gene annotation/version; prepare_query_anndata skipped.
  • Mechanism: The encoder expects the exact reference gene order; missing genes are zero-padded and reordering silently corrupts the input.
  • Symptom: Garbage latent, everything maps to one blob, or a silent accuracy cliff (no error raised).
  • Fix: Always prepare_query_anndata(query, reference_model); verify the shared-gene fraction; too few shared HVGs is a hard stop.

Good integration metrics, wrong labels

  • Trigger: Judging mapping by scIB integration scores alone.
  • Mechanism: Integration metrics reward query/reference mixing; mixing OOD cells into the wrong neighborhood raises the batch-removal score, and bio-conservation uses reference labels (circular for the query).
  • Symptom: Top scIB total score with biologically wrong annotation.
  • Fix: Integration metrics validate the embedding, not labels. Evaluate transfer on held-out labeled query cells (per-type F1, especially rare types), OOD detection on spiked-in unseen types, and marker-gene sanity checks.

Zero-shot foundation-model embedding as a mapper

  • Trigger: Using scGPT/Geneformer zero-shot embeddings for clustering/transfer expecting SOTA.
  • Mechanism: The masked-gene pretraining objective does not guarantee a label- or batch-aware embedding; zero-shot embeddings are not batch-corrected.
  • Symptom: Worse AvgBio/integration than scVI or even HVG-PCA + Harmony.
  • Fix: Fine-tune with task labels, or use an established mapper; reserve foundation models for cross-modality/species/data-scarce cases (Kedzierska 2025).

Reconciliation: When Methods Disagree

PatternLikely causeAction
scANVI label confident but kNN uncertainty highOOD cell forced onto nearest labelTrust the uncertainty; set Unknown and inspect markers
Symphony Mahalanobis flags OOD but scANVI does notscANVI latent carved to absorb the cellPrefer the distance-based flag; novel biology likely
popV members disagreeGenuine ambiguity or granularity mismatchRoute to manual review; report the disagreement, do not force a leaf
High scIB score, poor per-type F1 on held-out labelsEmbedding mixes well but labels wrongBelieve the F1; integration score is not a label metric

Quantitative Thresholds

ThresholdSourceRationale
Transfer uncertainty > 0.2 -> "Unknown"Sikkema 2023 (HLCA)Weighted-kNN neighbor-disagreement cutoff bounding false labels; recalibrate per reference
Surgery weight_decay=0.0, ~100-200 epochsscvi-tools scArches tutorialFrozen reference weights + no decay keep the shared latent fixed
scIB total = 0.6bio + 0.4batchLuecken 2022Benchmark weighting; scores the embedding, NOT query labels
CellTypist input = log1p of CP10kCellTypist docsWrong normalization silently degrades accuracy

Common Errors

Error / symptomCauseSolution
Everything maps to one blobprepare_query_anndata skipped; gene mismatchRun it before load_query_data; check shared-gene fraction
OOD cells pass a 0.5 softmax filterThresholding the wrong quantityGate on weighted-kNN uncertainty / OOD distance, not softmax
Reference cells move between runsNon-zero weight_decay or over-training in surgerySet weight_decay=0.0, keep freeze_* defaults, modest epochs
load_query_data errors on labelsscANVI needs unlabeled_categoryPass it to from_scvi_model; query labels filled with that category
CellTypist labels look randomRaw or wrongly normalized countsFeed log1p CP10k input

References

  • Lopez R, Regier J, Cole MB, Jordan MI, Yosef N. 2018. Deep generative modeling for single-cell transcriptomics. Nat Methods 15:1053-1058.
  • Xu C, Lopez R, Mehlman E, Regier J, Jordan MI, Yosef N. 2021. Probabilistic harmonization and annotation of single-cell transcriptomics data with deep generative models. Mol Syst Biol 17:e9620.
  • Lotfollahi M, Naghipourfar M, Luecken MD, et al. 2022. Mapping single-cell data to reference atlases by transfer learning. Nat Biotechnol 40:121-130.
  • Kang JB, Nathan A, Weinand K, et al. 2021. Efficient and precise single-cell reference atlas mapping with Symphony. Nat Commun 12:5890.
  • Hao Y, Hao S, Andersen-Nissen E, et al. 2021. Integrated analysis of multimodal single-cell data. Cell 184:3573-3587.
  • De Donno C, Hediyeh-Zadeh S, Moinfar AA, et al. 2023. Population-level integration of single-cell datasets enables multi-scale analysis across samples. Nat Methods 20:1683-1692.
  • Ergen C, Xing G, Xin C, et al. 2024. Consensus prediction of cell type labels in single-cell data with popV. Nat Genet 56:2731-2738.
  • Dominguez Conde C, Xu C, Jarvis LB, et al. 2022. Cross-tissue immune cell analysis reveals tissue-specific features in humans. Science 376:eabl5197.
  • Michielsen L, Lotfollahi M, Strobl D, et al. 2023. Single-cell reference mapping to construct and extend cell-type hierarchies. NAR Genom Bioinform 5:lqad070.
  • Luecken MD, Buttner M, Chaichoompu K, et al. 2022. Benchmarking atlas-level data integration in single-cell genomics. Nat Methods 19:41-50.
  • Sikkema L, Ramirez-Suastegui C, Strobl DC, et al. 2023. An integrated cell atlas of the lung in health and disease. Nat Med 29:1563-1577.
  • Kedzierska KZ, Crawford L, Amini AP, Lu AX. 2025. Zero-shot evaluation reveals limitations of single-cell foundation models. Genome Biol 26:101.

Related Skills

  • single-cell/preprocessing - QC, normalization, and HVG selection the query needs before mapping
  • single-cell/markers-annotation - Manual marker-based cluster annotation when there is no reference
  • single-cell/batch-integration - Integrating datasets without a labeled reference
  • single-cell/doublet-detection - Removing doublets that map to spurious intermediates
  • differential-expression/de-results - Pseudobulk validation of mapping-derived populations

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Simplest distributed training API. 4 lines to add distributed support to any PyTorch script. Unified API for DeepSpeed/FSDP/Megatron/DDP. Automatic device placement, mixed precision (FP16/BF16/FP8). Interactive config, single launch command. HuggingFace ecosystem standard.

日本語の概要は準備中です。原文の説明を表示しています。

huang-sh/DeepScience42026年7月15日 更新

ADMET property prediction for drug candidates. Full pharmacokinetic panel (Caco-2, PPB, clearance, CYP), toxicity (hERG, AMES, DILI), drug-likeness (Lipinski, QED), using RDKit descriptors and TDC models.

日本語の概要は準備中です。原文の説明を表示しています。

huang-sh/DeepScience42026年7月15日 更新

Interpretable ADMET analysis with mechanistic reasoning. Maps liabilities to structural causes and biological pathways. Based on CoTox (Park 2025) and DrugR (Liu 2026).

日本語の概要は準備中です。原文の説明を表示しています。

huang-sh/DeepScience42026年7月15日 更新

aeon

無料

This skill should be used for time series machine learning tasks including classification, regression, clustering, forecasting, anomaly detection, segmentation, and similarity search. Use when working with temporal data, sequential patterns, or time-indexed observations requiring specialized algorithms beyond standard ML approaches. Particularly suited for univariate and multivariate time series analysis with scikit-learn compatible APIs.

日本語の概要は準備中です。原文の説明を表示しています。

huang-sh/DeepScience42026年7月15日 更新

arboreto

無料

Infer gene regulatory networks (GRNs) from gene expression data using scalable algorithms (GRNBoost2, GENIE3). Use when analyzing transcriptomics data (bulk RNA-seq, single-cell RNA-seq) to identify transcription factor-target gene relationships and regulatory interactions. Supports distributed computation for large-scale datasets.

日本語の概要は準備中です。原文の説明を表示しています。

huang-sh/DeepScience42026年7月15日 更新

astropy

無料

Comprehensive Python library for astronomy and astrophysics. This skill should be used when working with astronomical data including celestial coordinates, physical units, FITS files, cosmological calculations, time systems, tables, world coordinate systems (WCS), and astronomical data analysis. Use when tasks involve coordinate transformations, unit conversions, FITS file manipulation, cosmological distance calculations, time scale conversions, or astronomical data processing.

日本語の概要は準備中です。原文の説明を表示しています。

huang-sh/DeepScience42026年7月15日 更新

huang-sh のスキルをすべて見る

このスキルの問題を報告する