Skip to content
theislabPublic

About

Cross-species scRNA-seq integration with learnable per-gene evolutionary gating

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Chimera

Cross-species Harmonization via Integrated Mixing of Evolutionary Residual Alphas

When a protein is conserved across species, is the gene also used the same way in cells? Chimera is a variational autoencoder, built on scvi-tools, that aligns single-cell RNA-seq data across species and returns, for every one-to-one ortholog, two gene-level readouts from the same fit:

  • the count evidence S_g: how much better one cell-state pattern shared by all species explains the gene's counts than a separate average per species. It rewards a shared pattern and is lowered by a gap in expression level between species.
  • Δα: where the gene's deployment sits relative to a protein-identity prior. Δα above zero: the gene is used more alike across species than its protein identity suggests; below zero: less alike.
You want Go to
to train Chimera on your own cohort Quick start
the per-gene tables of the paper REPRODUCE.md, section 3 (bundle gene_tables)
the code and data behind a figure, table or number of the paper REPRODUCE.md, section 4
the whole chain, from the raw data to the figures REPRODUCE.md, section 1 (the chain) and section 8 (raw data to objects)
to find your way in the repository CONTRIBUTING.md

What the model does

Cells of all species are encoded into one latent space. The decoder predicts each gene's expression through two heads that are always combined:

log rate = shared head (sees no species label) + (1 - α_g) × residual head (species-aware)
  • The shared head must explain a gene in every species with one cell-state pattern.
  • The residual head adds a species-specific correction, scaled per gene by 1 - α_g.
  • The gate α_g = sigmoid(logit(π_g) + c_g) starts at the protein prior π_g, the protein identity of the gene's orthologs, and moves only under count evidence: its target is S_g, the log-likelihood gain of the shared head over a per-species average. Δα_g = α_g - π_g.

The correction c_g is read in two ways:

Gate Option What sets c_g Use
protein-feature gate (default) --config A a small network, the Gene Integration Network (GIN), on 72 gene features: 64 principal components of ESM-2 protein embeddings, ESM-2 variance between species, protein identity and its spread, three expression statistics places every gene through its protein neighborhood, genes with too few counts included (their values are imputed from features)
per-gene gate (companion) --config M one free offset per gene follows each gene's own counts; no protein-feature network

The loss adds four structural terms to the usual reconstruction and KL terms, each closing one way in which a gated decoder fails silently: a sparsity penalty on the residual head (otherwise it fits everything and α falls to zero), a reconstruction loss of the shared head alone (otherwise the shared head receives no gradient), an anchor of α to the prior (otherwise α of divergent genes collapses), and a fit-quality reward driven by S_g (otherwise α can only move down). Species information is removed from the latent space by an adversarial classifier and a maximum-mean-discrepancy term. The paper's Methods and Supplement derive each term.

What to keep in mind when reading the outputs (the paper's Results and Discussion give the evidence):

  • Genes with too few counts have S_g = 0 ("masked"). With the protein-feature gate their Δα is imputed from protein and expression features; read it as such.
  • Δα is read within a cohort (centered on the cohort median, averaged over seeds). How well it repeats across seeds differs between cohorts; check the training state of every fit.
  • S_g and Δα reward shared pattern. Where cell-type labels are rich, direct comparisons of pseudobulk profiles match or beat them; S_g needs no labels.

Installation

Python 3.12 was used for all results.

git clone https://github.com/theislab/chimera.git && cd chimera
mamba create -n chimera_env python=3.12 pip
mamba activate chimera_env
pip install torch==2.11.0
pip install -e ".[dev,graph,attributions,protein,evolution,data,baselines]"
pytest -q

Two other routes build the same environment: the notebook notebooks/00_environment.ipynb (any platform; picks the PyTorch build for CPU, CUDA or Apple MPS and registers a Jupyter kernel), and, on Linux x86-64, bash analysis/envs/build_env_from_lock.sh chimera_env, which installs every package at the exact version of the lock file. Core dependencies are pinned in pyproject.toml to the versions the archived models were trained with.

Quick start: your own cohort

1. Build the cohort object. Chimera reads one AnnData file with all species:

Field Content
X raw integer counts, cells × one-to-one ortholog groups
obs['species'] species of each cell
obs['batch'] data set or chemistry within a species (see below)
var['conservation_prior'] protein prior π_g in (0, 1)
varm['gene_features'] the 72 standardized gene features
uns['p_null'] per-species average expression proportions

The functions that build it are in chimera/_data_utils.py (query_ortholog_table, compute_conservation_prior, pca_esm2, compute_esm2_interspecies_variance, compute_expression_stats, assemble_gin_features, construct_unified_adata, precompute_p_null). Two worked examples: notebooks/01_data_preparation.ipynb (liver and testis) and analysis/tasks/C1_cohorts/build.py (cohorts from CELLxGENE and GEO, one configuration per cohort). Then check the object:

python -m analysis.common.check_cohort my_cohort.h5ad --batch-key batch

Batch key. Use a batch column with few levels per species (the source data set or the chemistry). Sample- or donor-level batches made training fail in our cohorts.

2. Train. Start from the canonical recipe closest to your cohort (configs/canonical_recipes.tsv; two species at moderate divergence: the liver Human+Mouse row):

python training/run_experiment.py --run-name my-cohort-s42 --adata my_cohort.h5ad \
    --config A --max-epochs 150 --adv-weight 200 --free-bits 1.0 --seed 42 --accelerator cpu

--accelerator is cpu, gpu or mps (the default). --config M trains the per-gene gate with the same recipe. python training/run_experiment.py --help lists every option. The run is written to training/runs/my-cohort-s42/:

File Content
final_state.npz per gene: alpha, prior, correction, S_g_ema (the count evidence); per cell: z_mean (the latent)
summary.json, report.md training health: which expectations passed (failed_expectations), key metrics
model/ the saved model
config.json every setting of the run

3. Check the fit before reading it: failed_expectations in summary.json, the final adversary accuracy (near chance when species are mixed), and that Δα is not flat (near zero for almost every gene). Train at least three seeds; the paper reads the mean over seeds. --clamp-z-logvar bounds the log-variance of the sampled latent; it is off by default and in every canonical model. Use it only if a fit becomes non-finite. It keeps such fits finite but does not cure a flat gate.

4. Read the gene table.

import anndata as ad, numpy as np, pandas as pd

adata = ad.read_h5ad("my_cohort.h5ad", backed="r")
fs = np.load("training/runs/my-cohort-s42/final_state.npz", allow_pickle=False)
genes = pd.DataFrame(
    {"prior": fs["prior"], "alpha": fs["alpha"], "delta_alpha": fs["alpha"] - fs["prior"], "S_g": fs["S_g_ema"]},
    index=adata.var_names,
)
genes["count_evidence"] = np.abs(genes["S_g"]) >= 1e-6     # False: masked, Δα imputed from features
genes["D"] = genes["delta_alpha"] - genes["delta_alpha"].median()   # centered within the cohort

A saved model is reloaded with ChimeraModel.load("training/runs/my-cohort-s42/model", adata=adata, accelerator="cpu") (per-gene-gate runs: analysis.common.load_run.load_run(run_dir, adata)); get_alpha(), get_delta_alpha(), get_S_g() and get_latent_representation() return the readouts and the latent.

Where everything is

Path Holds
chimera/ the package: model (_model.py), module and loss (_module.py), gate network and other components (_components.py), training plan, data preparation (_data_utils.py), diagnostics, constants
configs/ canonical_recipes.tsv (the recipe of every canonical model), optuna_search_space.json
training/ run_experiment.py (train, evaluate, summarize), baselines, diagnostics; runs/ holds trained models (not in git)
notebooks/ the workflow on the liver and testis cohorts: environment, data preparation, baselines and the first analyses of the gate (notebooks 00 to 11), with their builders, stored outputs and caches; the guide says what each still produces
analysis/ the analyses of the paper, one folder per analysis, with an index; shared helpers; environments; job templates
figures/ every figure of the paper: panels, specs, the build, one PDF with one figure per page, an index
release/ how a release is staged for Zenodo and tested from a clean clone
scripts/ stand-alone scripts of the first version of the model, kept as starting points (no analysis of the paper uses them; none was run again for the release): ablations, hyperparameter search, robustness, demonstrations
tests/ the test suite (pytest -q)
data/, results/, training/runs/, notebooks/cache/ data, results, models and caches; not in git, filled from the deposit (REPRODUCE.md, section 3)

Data

All analyzed data are public; no new data were generated. The canonical cohorts:

Data Source
Liver: human, macaque, mouse Guilliams et al. 2022, Cell 185:379, GEO GSE192742
Liver: zebrafish Wang et al. 2023, Nucleic Acids Res., doi:10.1093/nar/gkac633, GEO GSE198832
Testis: human, macaque, mouse Murat et al. 2023, Nature, doi:10.1038/s41586-022-05547-7, E-MTAB-11063, E-MTAB-11068, E-MTAB-11071
Both, as processed counts CAMEX bundle, Guo, Huang and Zhang 2026, Nat. Commun. 17:3017, archived at figshare doi:10.6084/m9.figshare.31131808.v1; the data preparation downloads it from the CAMEX authors' Google Drive folder (REPRODUCE.md, section 8)
ESM-2 protein embeddings (esm2_t48_15B_UR50D) SATURN, Rosen et al. 2024, Nat. Methods (archive protein_embeddings.tar.gz at snap.stanford.edu)
Ortholog tables Ensembl BioMart, release 110

The sources of the other cohorts (bone marrow, kidney, pancreatic islet, eye, cerebral cortex, lung, skeletal muscle, tumor myeloid cells) and of every reference are listed in the paper and in the MANIFEST.tsv files of the deposit; how each object is built from them is in REPRODUCE.md, section 8. Processed objects, ortholog tables, trained models and per-gene tables are archived at Zenodo, one record per bundle: REPRODUCE.md, section 3, gives the DOI of each, and the code archive of release v0.1.0, 10.5281/zenodo.24137767, links them all. In file names, panc_* and pancreas_* mean the liver cohorts.

Reproducing the paper

REPRODUCE.md is the guide: what can be reproduced at which cost, the deposit, a map from every figure, table and section to the code behind it, the names used in files, and the tests of a release (bash analysis/reproduce_smoke.sh).

Citation

If you use Chimera, please cite the paper (reference added on publication) and the software; see CITATION.cff.

License

CC BY 4.0 (Creative Commons Attribution 4.0 International); see LICENSE. The records of the deposit are released under the same license; third-party sources keep their own terms (release/zenodo/LICENSES.md). Chimera follows the conventions of scvi-tools for model registration, AnnData handling and training plans.

About

Cross-species scRNA-seq integration with learnable per-gene evolutionary gating

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages