Python single-cell genomics toolkit — a port of Seurat's core data structures and analysis pipeline
Project description
Shanuz — Python Single-Cell Genomics Toolkit
Shanuz 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
- Shanuz object — mirrors the R
SeuratS4 class with__slots__-based Python classes - Assay5 — sparse-matrix-backed multi-layer assay (counts, data, scale.data)
- Preprocessing —
normalize_data,find_variable_features(VST),scale_data,percentage_feature_set - SCTransform —
sctransform(regularized negative-binomial Pearson residuals) - Signature scoring —
add_module_score,cell_cycle_scoring(S/G2M + Phase) - Dimensionality reduction —
run_pca,run_ica,run_tsne(via scikit-learn) - Batch correction / integration —
run_harmony,integrate_layers(via harmonypy) - Nearest-neighbour graph —
find_neighbors(KNN + SNN) - Multimodal WNN —
find_multi_modal_neighbors(per-cell RNA/protein weights, jointwknn/wsnngraphs) - Clustering —
find_clusters(Louvain via python-igraph, 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(wilcoxtie-corrected,t,LR,negbinom,roc) - Plotting —
dim_plot,feature_plot,vln_plot,dot_plot,elbow_plot,do_heatmap,dim_heatmap,feature_scatter,variable_feature_plot,ridge_plot(matplotlib/seaborn) - AnnData interoperability —
as_anndata,from_anndata - Spatial (Xenium / Visium / CosMx) —
load_xenium/load_visium/load_cosmx,get_tissue_coordinates,nearest_neighbor_distance,local_neighborhood,build_niche_assay,composition_test,image_dim_plot,image_feature_plot - 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
- Xenium spatial tutorial — spatial neighbourhood/niche analysis, verified to 8 s.f. against R Seurat
Installation
Shanuz is published on PyPI — pip install shanuz just works.
Installing from source (editable install) is only needed if you want to modify shanuz itself.
From PyPI (recommended)
pip install shanuz # core: object model, preprocessing, PCA, markers
pip install "shanuz[analysis]" # + clustering, UMAP, plotting (matplotlib/seaborn)
pip install "shanuz[anndata]" # + AnnData interoperability
pip install "shanuz[integration]" # + Harmony batch correction (harmonypy)
pip install "shanuz[all]" # everything (analysis + anndata + integration + dev/test tooling)
Or with uv:
uv pip install "shanuz[analysis]"
From source (for development)
git clone https://github.com/GenomicAI/shanuz.git
cd shanuz
uv venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv pip install -e ".[all]" # editable install + tests/linting
With pip instead of uv:
git clone https://github.com/GenomicAI/shanuz.git
cd shanuz
pip install -e ".[analysis]"
Troubleshooting
ModuleNotFoundError: No module named 'numpy._core._multiarray_umath' (or a
similar broken NumPy/SciPy import) means the virtual environment has a corrupt or
partially-installed NumPy — usually left over from an interrupted install or from
mixing installers. It is not a shanuz issue. Fix it by reinstalling NumPy, or by
recreating the environment:
uv pip install --reinstall --no-cache numpy # quick fix
# or start clean:
rm -rf .venv && uv venv && uv pip install "shanuz[all]"
Quick Start
import scipy.sparse as sp
import numpy as np
from shanuz import create_shanuz_object
# Create a Shanuz object from a counts matrix
counts = sp.random(2000, 500, density=0.2, format="csc")
sobj = create_shanuz_object(counts, project="my_project", min_cells=3, min_features=200)
print(sobj)
# Shanuz object — my_project
# 500 cells × 2000 features
# Active assay: 'RNA'
# Reductions: []
# Version: 5.4.0
# Access metadata
print(sobj.meta_data.head())
Tutorials
Five end-to-end tutorials — from basic guided clustering through multimodal
CITE-seq to Xenium spatial — each pairing R Seurat code side-by-side with the
Python Shanuz 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 |
# 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
API Reference
Object creation
from shanuz import create_shanuz_object
pbmc = create_shanuz_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 shanuz.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 shanuz.reduction import run_pca
from shanuz.neighbors import find_neighbors
from shanuz.clustering import find_clusters
from shanuz.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))
Differential expression
from shanuz.markers import find_markers, find_all_markers
markers = find_markers(pbmc, ident_1=1)
all_markers = find_all_markers(pbmc, only_pos=True, logfc_threshold=0.25)
Plotting
All plotting functions return a matplotlib.figure.Figure — save or display as needed.
from shanuz.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")
| Shanuz 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
Shanuz
├── 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[ShanuzCommand] # audit log
Roadmap
See ROADMAP.md for the full development plan. Milestones:
| Milestone | Focus |
|---|---|
| v0.2.0 | Batch correction — Harmony + IntegrateLayers ✅ (delivered); remaining: CCA/RPCA anchors |
| v0.3.0 | Reference mapping — FindTransferAnchors, TransferData, MapQuery |
| v0.4.0 | Multimodal WNN — FindMultiModalNeighbors, joint UMAP/clustering ✅ (delivered — see Tutorial 3) |
| v0.5.0 | Additional reductions — t-SNE, ICA ✅ (delivered); remaining: SPCA, GLM-PCA |
| v0.6.0 | Pseudobulk DE — AggregateExpression, DESeq2, MAST, FindConservedMarkers |
| v0.7.0 | Spatial — Xenium/Visium/CosMx loaders, niche/neighbourhood analysis, image_* plots ✅ (largely delivered — see Tutorial 5); remaining: MERSCOPE loader, FindSpatiallyVariableFeatures (Moran's I), Visium tissue-image plots |
| v0.8.0 | Scale — BPCells-style lazy matrices, SketchData, ProjectData |
| v0.9.0 | Specialized — HTODemux, Mixscape (CRISPR screens) |
| v0.10.0 | Infrastructure — PyPI, GitHub Actions CI, type annotations, MkDocs site |
Running Tests
uv pip install -e ".[dev]"
pytest tests/ -v
All 156 unit tests pass.
Dependencies
| Package | Purpose |
|---|---|
| numpy, scipy, pandas | Core numerics and data frames |
| statsmodels | LOESS smoothing for VST |
| scikit-learn | PCA |
| umap-learn | UMAP embedding |
| python-igraph | Louvain clustering |
| leidenalg | Leiden clustering |
| packaging | Version handling |
Credits
Development assistance: This package was developed with the help of Claude (Anthropic's AI assistant, claude-sonnet-4-6), which assisted in porting the R Seurat codebase to Python, implementing the VST algorithm, degree-2 LOESS, Louvain clustering, and validating results against the official PBMC 3k tutorial.
Original R Seurat package:
The algorithms and data structures in Shanuz are direct Python translations of the
R Seurat package by the Satija Lab.
Please cite the original Seurat papers if you use Shanuz 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shanuz-0.2.0.tar.gz.
File metadata
- Download URL: shanuz-0.2.0.tar.gz
- Upload date:
- Size: 10.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3820273b716642ed0b1ff4792531101c4df2ef5995ee03d3f183b7f3b9cee09d
|
|
| MD5 |
ebadfb01db1c6c7af995435f79f2b024
|
|
| BLAKE2b-256 |
8886a3c6790bc1087e22793ff72152e3186684f0b0f585c8facbb20f521fbd1a
|
File details
Details for the file shanuz-0.2.0-py3-none-any.whl.
File metadata
- Download URL: shanuz-0.2.0-py3-none-any.whl
- Upload date:
- Size: 104.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e5876bc81cb2b95270de146917202de13cadf74baa3cbb6996992dbea49b82e
|
|
| MD5 |
0249eca28aca8f7ca8ff0f8aa73fd9bd
|
|
| BLAKE2b-256 |
580a328f8a2a146bd63a3ef5f522fda4d0fe25f367925d2413b6fa6cfec0906c
|