Skip to main content

truecell

Truecell — Python Single-Cell Genomics Toolkit

PyPI Python 3.12+ License: MIT Docs

📖 Documentation — API reference, all eighteen tutorials, and how the port is checked against R Seurat.

Truecell is a Python port of the Seurat single-cell RNA-seq analysis framework, implementing Seurat's core data structures, preprocessing pipeline, dimensionality reduction, clustering, and marker detection — entirely in Python.

The package is spiritually and algorithmically faithful to Seurat v5 while providing a pure-Python, pip-installable alternative that integrates naturally with NumPy, SciPy, and AnnData ecosystems.


Features

  • Truecell object — mirrors the R Seurat S4 class with __slots__-based Python classes
  • Assay5 — sparse-matrix-backed multi-layer assay (counts, data, scale.data)
  • Object slimming — diet_truecell (Seurat's DietSeurat) strips an object to chosen assays, layers, features, reductions and graphs for saving or sharing. Returns a new object and leaves the input alone, sharing the surviving layers rather than copying them. Note that dimreducs and graphs are keep-lists — calling it with no arguments removes every reduction and graph, which is Seurat's behaviour too; name what you want kept
  • Preprocessing — normalize_data, find_variable_features (VST), scale_data, percentage_feature_set
  • SCTransform — sctransform (regularized negative-binomial Pearson residuals; vst_flavor="v2" by default, as Seurat 5, or "v1" for the 2019 model)
  • Multi-sample SCT — prep_sct_find_markers (Seurat's PrepSCTFindMarkers). SCTransform corrects each object's counts to its own median sequencing depth, so merging two SCTransformed objects leaves the halves on different scales and a fold change across the merge partly measures how deeply each batch was sequenced. Run it once after the merge, before any find_markers on the SCT assay; it re-corrects every cell to the minimum median UMI across the models and is a no-op on a single-model object. Verified against Seurat 5.5.1: given R's own fitted models, 0 of 13,953,800 entries differ
  • Signature scoring — add_module_score, cell_cycle_scoring (S/G2M + Phase)
  • Dimensionality reduction — run_pca, run_spca (supervised, off a cell graph), run_ica, run_tsne, glm_pca (Poisson or negative binomial, straight on counts)
  • Batch correction / integration — run_harmony (via harmonypy), CCA/RPCA anchors (find_integration_anchors + integrate_data), and the integrate_layers dispatcher (method="harmony"|"cca"|"rpca")
  • Reference mapping — find_transfer_anchors (project a query into a reference; pcaproject or cca) + transfer_data (annotate the query with reference labels, or impute reference expression onto it); project_umap / map_query place the query in the reference's own UMAP in one call
  • Scale (sketching) — sketch_data draws a leverage-weighted subset of a huge dataset (rare states kept, not lost), leverage_score computes the per-cell scores via a CountSketch (no full SVD), and project_data extends the sketch's PCA/UMAP/labels back to every cell
  • Scale (lazy on-disk matrices) — LazyMatrix keeps a matrix out-of-core as memory-mapped compressed-sparse-column arrays (BPCells-style); write_lazy_matrix / open_lazy_matrix persist and map it, a slice reads only the touched cells off disk, col_blocks streams a million cells at bounded RAM, and it drops straight into an Assay5 layer — no new dependency
  • Cell hashing (demultiplexing) — hto_demux (Seurat's HTODemux) demultiplexes pooled samples from hashtag counts: CLR normalize → cluster into k = n_hashtags + 1 groups (kfunc="clara", Seurat's k-medoids, or "kmeans") → per-hashtag negative-binomial background threshold → singlet / doublet / negative calls, written to meta_data (HTO_maxID, HTO_classification, …) plus a hash.ID identity. multiseq_demux (Seurat's MULTIseqDemux) is the MULTI-seq alternative — a Gaussian-KDE quantile threshold per barcode, with an autothresh sweep — writing MULTI_ID / MULTI_classification
  • Pooled CRISPR screens (Mixscape) — calc_perturb_sig (Seurat's CalcPerturbSig) subtracts each cell's nearest non-targeting controls to isolate its perturbation signature, then run_mixscape (Seurat's RunMixscape) separates true knockouts from non-perturbed escapers per guide — gene-vs-NT DE, then an iterative 2-component Gaussian mixture over the perturbation score — writing mixscape_class ("<gene> KO" / NP / NT, also the identity), mixscape_class.global, and mixscape_class_p_ko. mixscape_lda (Seurat's MixscapeLDA) adds the supervised map on which each guide population forms its own cloud — per-guide DE-gene PCA subspaces, every cell projected onto each, then one linear discriminant analysis over the concatenation → an lda reduction plus lda_assignments / LDAP_<class>. Two diagnostics complete the workflow: plot_perturb_score (Seurat's PlotPerturbScore) overlays the NT control density against one guide's own along the perturbation score — the axis mixscape actually splits on, bimodal when the guide has a real effect — and mixscape_heatmap (Seurat's MixscapeHeatmap) shows the DE genes underneath it with every cell ordered by its knockout probability
  • Nearest-neighbour graph — find_neighbors (KNN + SNN). return_neighbor=True (Seurat's return.neighbor) stores the raw KNN — indices and distances — as a Neighbor under <assay>.nn instead of building graphs, and compute_snn controls the SNN independently. Verified against Seurat 5.5.1 on pbmc3k: all 54,000 neighbour indices match, distances to 1.1e-13
  • Multimodal WNN — find_multi_modal_neighbors (full two-stage port: per-cell RNA/protein weights via exponential kernel + softmax, then a joint neighbour search building the wknn/wsnn graphs)
  • Clustering — find_clusters runs Seurat's own modularity optimiser (Louvain, Louvain with multilevel refinement, smart local moving), translated from its C++ with the same restarts and random stream, so the same graph gives Seurat's partition label for label; Leiden via leidenalg
  • UMAP — run_umap (via umap-learn; embeds a reduction or a precomputed graph)
  • PC significance — jack_straw, score_jackstraw (JackStraw permutation test)
  • Differential expression — find_markers, find_all_markers and find_conserved_markers (cross-condition, Fisher-combined), with all nine of Seurat's tests: wilcox (tie-corrected, the default), t, bimod, LR, negbinom, poisson, mast hurdle, deseq2, and roc. Eight of them — every p-value test — reproduce Seurat's top 50 genes exactly on PBMC 3k, and roc agrees within Seurat's own 3-dp AUC rounding. deseq2 is Seurat's DESeq2DETest, every cell a replicate, and sample_col makes it a pseudobulk test. poisson and negbinom are Seurat's two GLMDETest families and both run on the counts layer — prefer negbinom, since fixing the dispersion at 1 makes poisson anti-conservative on overdispersed UMI counts
  • Pseudobulk — aggregate_expression (sum counts per group → matrix or one-cell-per-group object), pseudobulk DESeq2 via find_markers(test_use="deseq2", sample_col=...)
  • Plotting — dim_plot, feature_plot, vln_plot, dot_plot, elbow_plot, do_heatmap, dim_heatmap, feature_scatter, variable_feature_plot, ridge_plot, plot_perturb_score, mixscape_heatmap (matplotlib/seaborn)
  • AnnData interoperability — truecell.compat.anndata.as_anndata and from_anndata, with spatial coordinates, FOVs and Visium images in the layout Scanpy and Squidpy read, plus recipes for SpatialData (AnnData, Scanpy and SpatialData)
  • Spatial (Xenium / Visium / CosMx / MERSCOPE) — load_xenium/load_visium/load_cosmx/load_merscope, get_tissue_coordinates, nearest_neighbor_distance, local_neighborhood, build_niche_assay, find_spatially_variable_features (Moran's I + mark variogram), composition_test, image_dim_plot, image_feature_plot
  • Visium tissue images — load_visium reads the H&E PNG + scalefactors_json.json into a VisiumV2 image (Seurat v5's class): get_image(), scale_factors, radius(), scale_coordinates(); spatial_dim_plot / spatial_feature_plot draw spots over that image at their true diameter
  • PBMC 3k tutorial — end-to-end validated against the official Seurat tutorial
  • PBMC 8k advanced tutorial — larger dataset + T/NK subclustering workflow
  • CITE-seq multimodal tutorial — RNA + surface protein (ADT) with CLR normalization and WNN joint clustering
  • Cell-hashing tutorial — hto_demux + multiseq_demux demultiplexing, 99.81% call-concordant with R Seurat's HTODemux
  • Mixscape tutorial — pooled-CRISPR calc_perturb_sig + run_mixscape + mixscape_lda, 97.68% per-cell call-concordant with R Seurat on the THP-1 ECCITE-seq screen
  • Integration tutorial — run_harmony / integrate_layers on the ifnb IFN-β benchmark; batch mixing lands within 0.001 of Seurat's for all three methods (Harmony 0.991, CCA 0.992, RPCA 0.917). The first tutorial to catch real defects: four RPCA-path bugs, all fixed — a crash on unequal batch sizes, a 4× under-integration, integrate_layers silently running v4's IntegrateData algorithm behind the v5 IntegrateEmbeddings API, and sklearn's randomized SVD drifting run_pca's trailing components (RPCA's batch mixing rose from 0.222 to 0.867 as the first two were fixed)
  • Reference mapping tutorial — find_transfer_anchors / transfer_data / map_query on the panc8 cross-technology benchmark; label transfer is 98.87% per-cell concordant with R Seurat, both ~98.7% accurate against the held-out cell types
  • Cell-cycle & module-score tutorial — cell_cycle_scoring / add_module_score on the proliferating THP-1 line; per-cell phase is 95.9% concordant with R Seurat, as often as two NumPy seeds agree with each other, and the S/G2M/module scores correlate at Pearson ≥ 0.997 (residual is the control-gene RNG)
  • Xenium spatial tutorial — spatial neighbourhood/niche analysis, verified to 8 s.f. against R Seurat

Installation

Truecell is published on PyPI — pip install truecell just works.

Requires Python 3.12 or newer, and CI tests 3.12 and 3.13. The floor follows SPEC 0, the support window numpy, scipy, pandas and scikit-learn themselves keep — three years past each Python release — rather than CPython's longer EOL calendar. On 3.10 or 3.11, pip resolves to 0.2.0, the last release that declared >=3.10.

Python 3.14 is not yet tested: harmonypy ships manylinux wheels only through cp313, and the alternatives are a source build needing BLAS or a resolver backtrack that pulls in torch. Everything else in the dependency set already has 3.14 wheels, so this is one package away.

If truecell crashes (a segmentation fault, or a Jupyter kernel that dies), the Troubleshooting page covers the known causes, and truecell.show_versions() prints what a bug report needs.

Releases and main. PyPI has the latest release, and this README follows main. CHANGELOG.md says what shipped in each release, and lists what is on main only under Unreleased.

From PyPI — the released core

pip install truecell                 # core: object model, preprocessing, PCA, markers
pip install "truecell[analysis]"     # + clustering, UMAP, plotting (matplotlib/seaborn)
pip install "truecell[anndata]"      # + AnnData interoperability
pip install "truecell[integration]"  # + Harmony batch correction (harmonypy)
pip install "truecell[deseq2]"       # + find_markers(test_use="deseq2") (pydeseq2)
pip install "truecell[all]"          # everything (all of the above + dev/test and docs tooling)

Or with uv:

uv pip install "truecell[analysis]"

From source — everything above

git clone https://github.com/GenomicAI/truecell.git
cd truecell
uv sync --all-extras --locked   # editable install + tests/linting, at uv.lock's versions
source .venv/bin/activate       # Windows: .venv\Scripts\activate

--locked installs the versions CI tests and the tutorial figures were drawn with; resolving fresh can give a different scientific stack.

With pip instead of uv:

git clone https://github.com/GenomicAI/truecell.git
cd truecell
pip install -e ".[analysis]"

Quick Start

import scipy.sparse as sp
import numpy as np
from truecell import create_truecell_object

# Create a Truecell object from a counts matrix
counts = sp.random(2000, 500, density=0.2, format="csc")
sobj = create_truecell_object(counts, project="my_project", min_cells=3, min_features=200)
print(sobj)
# Truecell object — my_project
#   500 cells × 2000 features
#   Active assay: 'RNA'
#   Reductions: []
#   Version: 5.4.0

# Access metadata
print(sobj.meta_data.head())

Tutorials

Eighteen end-to-end tutorials — from basic guided clustering through multimodal CITE-seq, cell-hashing demultiplexing, pooled-CRISPR Mixscape, batch integration, reference mapping, cell-cycle scoring, PC-significance testing, leverage-score sketching and the object model itself to Xenium spatial — each pairing R Seurat code side-by-side with the Python Truecell equivalent. See tutorials/README.md for the full index.

# Tutorial Dataset Complexity
1 PBMC 3k — Guided Clustering 3k PBMCs · 10x Genomics Beginner
2 PBMC 8k — Advanced Subclustering 8k PBMCs · GRCh38 Intermediate
3 CBMC CITE-seq — Multimodal 8,600 CBMCs · RNA + 13 proteins Advanced
4 PBMC 3k — SCTransform 3k PBMCs · 10x Genomics Advanced
5 Xenium — Spatial (R vs Python) 36k cells · 10x Xenium mouse brain Spatial
6 Cell Hashing — Demultiplexing 39,842 cells · 8 HTOs · GSE108313 Advanced
7 Mixscape — Pooled CRISPR Screen 20,729 cells · 25 guides · GSE153056 Advanced
8 Batch Integration — Harmony/CCA/RPCA 13,999 cells · CTRL/STIM · ifnb Advanced
9 Reference Mapping — Label Transfer 4,679 cells · celseq2→smartseq2 · panc8 Advanced
10 Cell-cycle & Module Scoring 20,729 cells · THP-1 · GSE153056 Advanced
11 Dimensional-Reduction Extras 2,700 PBMCs · 10x Genomics Advanced
12 Leverage-Score Sketching 13,999 cells · CTRL/STIM · ifnb Advanced
13 The Object Model Itself 2,700 PBMCs · 10x Genomics Advanced
14 Spatial Statistics & the Spatial Container 36,602 cells · 10x Xenium mouse brain Advanced
15 The Differential-Expression Test Suite 2,700 PBMCs · 10x Genomics Advanced
16 Out of Core — LazyMatrix vs BPCells 2,700 PBMCs · 10x Genomics Advanced
17 Visium — the Spatial Container 2,695 spots · 10x mouse brain Spatial
18 Anchor Internals — CCA & RPCA 2,400 cells · ifnb Advanced
# Tutorial 1 — PBMC 3k
python tutorials/pbmc3k_tutorial.py && python tutorials/generate_plots.py

# Tutorial 2 — PBMC 8k subclustering
python tutorials/pbmc8k_subclustering_tutorial.py && python tutorials/generate_advanced_plots.py

# Tutorial 3 — CITE-seq multimodal
python tutorials/cbmc_citeseq_tutorial.py && python tutorials/generate_multimodal_plots.py

# Tutorial 4 — SCTransform
python tutorials/pbmc3k_sctransform_tutorial.py && python tutorials/generate_sctransform_plots.py

# Tutorial 5 — Xenium spatial (auto-downloads ~20 MB)
python tutorials/generate_spatial_plots.py

# Tutorial 6 — Cell hashing demultiplexing (auto-downloads ~34 MB)
python tutorials/pbmc_hashing_tutorial.py && python tutorials/generate_hashing_plots.py

# Tutorial 7 — Mixscape pooled-CRISPR screen (auto-downloads ~66 MB)
python tutorials/thp1_mixscape_tutorial.py && python tutorials/generate_mixscape_plots.py

# Tutorial 8 — Batch integration (needs a one-time `Rscript tutorials/export_seuratdata.R ifnb`)
python tutorials/ifnb_integration_tutorial.py && python tutorials/generate_integration_plots.py

# Tutorial 9 — Reference mapping (needs a one-time `Rscript tutorials/export_seuratdata.R panc8`)
python tutorials/panc8_reference_mapping_tutorial.py && python tutorials/generate_refmap_plots.py

# Tutorial 10 — Cell-cycle & module scoring (downloads ~66 MB, shared with Mixscape)
python tutorials/thp1_cellcycle_tutorial.py && python tutorials/generate_cellcycle_plots.py

# Tutorial 13 — The object model (downloads ~24 MB, shared with Tutorial 1)
python tutorials/pbmc3k_objects_tutorial.py && python tutorials/generate_objects_plots.py

# Tutorial 14 — Spatial statistics & the container (downloads ~14 MB, shared with Tutorial 5)
python tutorials/xenium_svf_tutorial.py && python tutorials/generate_svf_plots.py

# Tutorial 15 — The DE test suite (downloads ~24 MB, shared with Tutorial 1)
python tutorials/pbmc3k_de_tutorial.py && python tutorials/generate_de_plots.py

API Reference

Object creation

from truecell import create_truecell_object

pbmc = create_truecell_object(
    counts,             # scipy.sparse CSC/CSR or numpy ndarray (genes × cells)
    project="pbmc3k",
    min_cells=3,        # filter genes present in fewer than N cells
    min_features=200,   # filter cells with fewer than N detected genes
)

Preprocessing

from truecell.preprocessing import (
    normalize_data,
    find_variable_features,
    scale_data,
    percentage_feature_set,
)

percentage_feature_set(pbmc, pattern=r"^MT-", col_name="percent.mt")
normalize_data(pbmc, normalization_method="LogNormalize", scale_factor=10000)
find_variable_features(pbmc, selection_method="vst", nfeatures=2000)
scale_data(pbmc)

Dimensionality reduction & clustering

from truecell.reduction import run_pca
from truecell.neighbors import find_neighbors
from truecell.clustering import find_clusters
from truecell.umap import run_umap

run_pca(pbmc, n_pcs=50)
find_neighbors(pbmc, dims=range(10), k_param=20)
find_clusters(pbmc, resolution=0.5)
run_umap(pbmc, dims=range(10))

# Seurat's `return.neighbor`: keep the raw KNN — indices and distances — instead
# of building graphs. Stored as a `Neighbor` under "RNA.nn" (a dot; the graphs
# use an underscore). Indices are 0-based, where R's `Indices()` are 1-based.
find_neighbors(pbmc, dims=range(10), return_neighbor=True)
nn = pbmc.neighbors["RNA.nn"]
nn.indices()      # (cells × k), the cell itself first
nn.distances()    # (cells × k), 0.0 in column 0

Differential expression

from truecell import (
    find_markers, find_all_markers, find_conserved_markers, aggregate_expression,
)

markers = find_markers(pbmc, ident_1=1)
all_markers = find_all_markers(pbmc, only_pos=True, logfc_threshold=0.25)

# Any of Seurat's nine tests. `negbinom` and `poisson` are its two GLM families
# and read the counts layer; prefer `negbinom` — holding the dispersion at 1
# makes `poisson` anti-conservative on overdispersed UMI counts.
markers = find_markers(pbmc, ident_1=1, test_use="poisson")
markers = find_markers(pbmc, ident_1=1, test_use="LR", latent_vars=["percent.mt"])

# Markers up in cluster 1 across every condition (Fisher-combined p per gene).
conserved = find_conserved_markers(pbmc, ident_1=1, grouping_var="condition")

# Pseudobulk counts summed per (cell type × donor) — input for sample-level DE.
pseudobulk = aggregate_expression(pbmc, group_by=["cell_type", "donor"])

# Pseudobulk DESeq2 between two conditions, one summed profile per donor (needs
# `pip install truecell[deseq2]`). pbmc.idents must hold the two conditions.
# Without sample_col every cell is a replicate, as in Seurat's FindMarkers.
de = find_markers(pbmc, ident_1="stim", ident_2="ctrl",
                  test_use="deseq2", sample_col="donor")

Multi-sample SCT, and slimming an object

import truecell

# Two samples SCTransformed separately, then merged. Each was corrected to its
# OWN median sequencing depth, so the two halves of the SCT counts layer are on
# different scales — a fold change across the merge would partly measure how
# deeply each batch was sequenced.
merged = ctrl.merge(stim, add_cell_ids=["ctrl", "stim"])
truecell.prep_sct_find_markers(merged)          # once, before any find_markers
de = truecell.find_markers(merged, "0", "1", assay="SCT")

# Slim an object before saving or sharing it. `pbmc` here is the object from the
# blocks above, which already has a `pca` and its two graphs.
#
# NOTE: `dimreducs` and `graphs` are keep-LISTS — with neither named, every
# reduction and graph is dropped (this is Seurat's behaviour too). Name what you
# want to keep, or you will lose your embedding.
slim = truecell.diet_truecell(pbmc, layers="counts", dimreducs="pca")
# -> keeps the counts layer and `pca`; drops data, scale.data and both graphs

Plotting

All plotting functions return a matplotlib.figure.Figure — save or display as needed.

from truecell.plotting import (
    dim_plot,            # DimPlot   — cells on UMAP/PCA coloured by ident
    feature_plot,        # FeaturePlot — gene expression on embedding
    vln_plot,            # VlnPlot   — violin plots per cluster
    elbow_plot,          # ElbowPlot — stdev per PC
    feature_scatter,     # FeatureScatter — two features vs each other
    variable_feature_plot, # VariableFeaturePlot — mean-variance HVG plot
    dim_heatmap,         # DimHeatmap — top loading genes per PC
    do_heatmap,          # DoHeatmap  — expression heatmap sorted by cluster
    ridge_plot,          # RidgePlot  — ridgeline plots per cluster
)

# Quick examples
fig = dim_plot(pbmc, reduction="umap", label=True)
fig = feature_plot(pbmc, ["LYZ", "MS4A1", "NKG7"], reduction="umap", ncol=3)
fig = vln_plot(pbmc, ["LYZ", "CD3D", "PPBP"], group_by=None)
fig = elbow_plot(pbmc, ndims=20)
fig = do_heatmap(pbmc, top_marker_genes)
fig.savefig("output.png", dpi=150, bbox_inches="tight")
Truecell function R Seurat equivalent
dim_plot DimPlot
feature_plot FeaturePlot
vln_plot VlnPlot
dot_plot DotPlot
elbow_plot ElbowPlot
feature_scatter FeatureScatter
variable_feature_plot VariableFeaturePlot
dim_heatmap DimHeatmap
do_heatmap DoHeatmap
ridge_plot RidgePlot

Data Structures

Truecell
├── assays: dict[str, Assay5]
│   └── "RNA"
│       ├── layers["counts"]    # raw integer counts (genes × cells)
│       ├── layers["data"]      # log-normalized (genes × cells)
│       └── layers["scale.data"] # z-scored (genes × cells)
├── meta_data: pd.DataFrame     # per-cell metadata
├── reductions: dict
│   ├── "pca": DimReduc         # PCA embeddings + loadings
│   └── "umap": DimReduc        # UMAP embeddings
├── graphs: dict
│   ├── "RNA_nn": Graph         # KNN graph
│   └── "RNA_snn": Graph        # SNN graph
└── commands: list[TruecellCommand]  # audit log

Roadmap

See ROADMAP.md for the full development plan, and CHANGELOG.md for what has actually shipped. The two are not the same thing — these milestones are planning labels rather than release versions — but as of 0.9.0 every row below through v0.9.0 is released, not just landed on main. Milestones:

Milestone Focus
v0.2.0 Batch correction — Harmony, CCA/RPCA anchors, IntegrateLayers dispatcher ✅ (released in 0.2.0)
v0.3.0 Reference mapping — FindTransferAnchors, TransferData, MapQuery/ProjectUMAP ✅ (released in 0.9.0)
v0.4.0 Multimodal WNN — FindMultiModalNeighbors, joint UMAP/clustering ✅ (released in 0.9.0 — see Tutorial 3)
v0.5.0 Additional reductions — t-SNE, ICA, run_spca, glm_pca (Poisson + negative binomial) ✅ (released in 0.9.0)
v0.6.0 Pseudobulk & advanced DE — AggregateExpression, FindConservedMarkers, DESeq2 (test_use="deseq2"), MAST (test_use="mast"), bimod (test_use="bimod") ✅ (released in 0.9.0)
v0.7.0 Spatial — Xenium/Visium/CosMx/MERSCOPE loaders, niche/neighbourhood analysis, find_spatially_variable_features (Moran's I + markvariogram), image_* plots, VisiumV2 tissue images, spatial_* H&E plots ✅ (released in 0.9.0 — see Tutorial 5)
v0.8.0 Scale — SketchData/ProjectData (leverage-score sketching) ✅; BPCells-style lazy on-disk matrices (LazyMatrix) ✅ (released in 0.9.0)
v0.9.0 Specialized — HTODemux ✅ + MULTIseqDemux ✅ (cell hashing); Mixscape ✅ (CalcPerturbSig + RunMixscape + MixscapeLDA + PlotPerturbScore + MixscapeHeatmap, CRISPR screens) — released in 0.9.0
v0.10.0 Infrastructure — PyPI ✅, GitHub Actions CI ✅ (3.12–3.13 matrix, wheel build + clean-install verification, coverage), CHANGELOG.md ✅, mypy in CI ✅, the documentation site ✅

Running Tests

uv sync --all-extras --locked
uv run pytest tests/ -q

About 1,700 tests; CI runs them on Python 3.12 and 3.13.

A further smoke suite runs the tutorials end to end against real data. It is opt-in: it needs the cached datasets and takes minutes. CI runs the part that needs only PBMC 3k; the rest runs on a developer's machine before each release:

TRUECELL_TUTORIAL_SMOKE=1 pytest tests/test_tutorial_smoke.py -v

A green unit suite says nothing about the tutorials on its own.


Dependencies

Package Purpose
numpy, scipy, pandas Core numerics and data frames
statsmodels The LR, poisson and mast DE tests
scikit-learn PCA
umap-learn UMAP embedding
numba Seurat's modularity optimiser (find_clusters)
python-igraph Leiden clustering; find_clusters(optimizer="igraph")
leidenalg Leiden clustering
packaging Version handling

Credits

Development assistance: This package was developed with the help of Claude (Anthropic's AI assistant) — initially claude-sonnet-4-6, and subsequently claude-opus-4-8 — which assisted in porting the R Seurat codebase to Python, implementing the VST algorithm, degree-2 LOESS, Louvain clustering, the anchor-based integration and transfer machinery, and validating results against real R Seurat runs.

Human in the loop. All development was carried out under strong human-in-the-loop (HITL) supervision. Every change was directed, reviewed and accepted by the maintainer; nothing was merged unattended. That review is the reason the fidelity claims in this repository are worth reading — each one is pinned to a side-by-side run against R Seurat with the numbers recorded, and several were sent back and re-derived when the first answer did not hold up. Where a difference from Seurat remains, it was examined and is documented as either a deliberate choice or an open question, rather than quietly absorbed.

Original R Seurat package:
The algorithms and data structures in Truecell are direct Python translations of the R Seurat package by the Satija Lab. Please cite the original Seurat papers if you use Truecell in published work:

Hao Y, Stuart T, Kowalski MH, et al. (2024). Dictionary learning for integrative, multimodal and scalable single-cell analysis. Nature Biotechnology, 42, 293–304. https://doi.org/10.1038/s41587-023-01767-y

Hao Y, Hao S, Andersen-Nissen E, et al. (2021). Integrated analysis of multimodal single-cell data. Cell, 184(13), 3573–3587. https://doi.org/10.1016/j.cell.2021.04.048

Stuart T, Butler A, Hoffman P, et al. (2019). Comprehensive Integration of Single-Cell Data. Cell, 177(7), 1888–1902. https://doi.org/10.1016/j.cell.2019.05.031

Butler A, Hoffman P, Smibert P, Papalexi E, Satija R. (2018). Integrating single-cell transcriptomic data across different conditions, technologies, and species. Nature Biotechnology, 36, 411–420. https://doi.org/10.1038/nbt.4096

PBMC 3k dataset:
10x Genomics. (2016). 3k PBMCs from a Healthy Donor. https://www.10xgenomics.com/resources/datasets/3-k-pb-mcs-from-a-healthy-donor-1-standard-1-1-0


License

MIT License — see LICENSE for details.

This software is an independent reimplementation for educational and research purposes. It is not affiliated with, endorsed by, or maintained by the Satija Lab or 10x Genomics.

Metadata

Release files for truecell 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for truecell 2.0.0
File Size Uploaded
truecell-2.0.0.tar.gz 1.0 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for truecell 2.0.0
File Interpreter ABI Platform
truecell-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.3 MB

Release files / truecell-2.0.0.tar.gz

Download URL truecell-2.0.0.tar.gz
Size 1.0 MB
Tags Source
SHA-256 checksum
How to use checksums
588316d3258854a726878ce8fc82078aa941c3db7d72e5eed93863ae6274f9b4
BLAKE2b-256 checksum
How to use checksums
52eee949ddcb536f3c5421763d563b61958213a062bb7ac487311b5ed44f299d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / truecell-2.0.0-py3-none-any.whl

Download URL truecell-2.0.0-py3-none-any.whl
Size 317.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
35a8e5ef0ca362886c896cca14e832d26a27f6c326b1c21179b881959e2e0870
BLAKE2b-256 checksum
How to use checksums
49d903c4c907b68ff117bcf6315e53fef872628a4cd08a1f29d8e133485c47b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.9.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page