shanuz 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- shanuz-0.1.1/.github/workflows/ci.yml +35 -0
- shanuz-0.1.1/.gitignore +39 -0
- shanuz-0.1.1/LICENSE +21 -0
- shanuz-0.1.1/PKG-INFO +396 -0
- shanuz-0.1.1/README.md +336 -0
- shanuz-0.1.1/ROADMAP.md +341 -0
- shanuz-0.1.1/pyproject.toml +69 -0
- shanuz-0.1.1/shanuz/__init__.py +143 -0
- shanuz-0.1.1/shanuz/_sparse.py +68 -0
- shanuz-0.1.1/shanuz/_types.py +15 -0
- shanuz-0.1.1/shanuz/_utils.py +65 -0
- shanuz-0.1.1/shanuz/assay.py +395 -0
- shanuz-0.1.1/shanuz/assay5.py +586 -0
- shanuz-0.1.1/shanuz/clustering.py +187 -0
- shanuz-0.1.1/shanuz/command.py +113 -0
- shanuz-0.1.1/shanuz/compat/__init__.py +3 -0
- shanuz-0.1.1/shanuz/compat/anndata.py +242 -0
- shanuz-0.1.1/shanuz/composition.py +98 -0
- shanuz-0.1.1/shanuz/datasets.py +297 -0
- shanuz-0.1.1/shanuz/dimreduc.py +192 -0
- shanuz-0.1.1/shanuz/generics.py +391 -0
- shanuz-0.1.1/shanuz/graph.py +172 -0
- shanuz-0.1.1/shanuz/io.py +138 -0
- shanuz-0.1.1/shanuz/jackstraw.py +174 -0
- shanuz-0.1.1/shanuz/logmap.py +96 -0
- shanuz-0.1.1/shanuz/markers.py +411 -0
- shanuz-0.1.1/shanuz/mixins/__init__.py +3 -0
- shanuz-0.1.1/shanuz/mixins/key_mixin.py +30 -0
- shanuz-0.1.1/shanuz/module_score.py +248 -0
- shanuz-0.1.1/shanuz/neighbor.py +124 -0
- shanuz-0.1.1/shanuz/neighbors.py +151 -0
- shanuz-0.1.1/shanuz/plotting.py +1156 -0
- shanuz-0.1.1/shanuz/preprocessing.py +619 -0
- shanuz-0.1.1/shanuz/py.typed +0 -0
- shanuz-0.1.1/shanuz/reduction.py +144 -0
- shanuz-0.1.1/shanuz/sctransform.py +264 -0
- shanuz-0.1.1/shanuz/shanuz.py +590 -0
- shanuz-0.1.1/shanuz/spatial/__init__.py +36 -0
- shanuz-0.1.1/shanuz/spatial/analysis.py +239 -0
- shanuz-0.1.1/shanuz/spatial/base.py +95 -0
- shanuz-0.1.1/shanuz/spatial/centroids.py +119 -0
- shanuz-0.1.1/shanuz/spatial/fov.py +275 -0
- shanuz-0.1.1/shanuz/spatial/loaders.py +248 -0
- shanuz-0.1.1/shanuz/spatial/molecules.py +95 -0
- shanuz-0.1.1/shanuz/spatial/segmentation.py +116 -0
- shanuz-0.1.1/shanuz/umap.py +79 -0
- shanuz-0.1.1/tests/conftest.py +57 -0
- shanuz-0.1.1/tests/test_advanced_tutorial.py +101 -0
- shanuz-0.1.1/tests/test_analysis.py +324 -0
- shanuz-0.1.1/tests/test_anndata_compat.py +41 -0
- shanuz-0.1.1/tests/test_assay.py +74 -0
- shanuz-0.1.1/tests/test_assay5.py +61 -0
- shanuz-0.1.1/tests/test_command.py +39 -0
- shanuz-0.1.1/tests/test_dimreduc.py +53 -0
- shanuz-0.1.1/tests/test_graph.py +44 -0
- shanuz-0.1.1/tests/test_logmap.py +63 -0
- shanuz-0.1.1/tests/test_multimodal_tutorial.py +93 -0
- shanuz-0.1.1/tests/test_neighbor.py +53 -0
- shanuz-0.1.1/tests/test_new_features.py +267 -0
- shanuz-0.1.1/tests/test_seurat.py +132 -0
- shanuz-0.1.1/tests/test_spatial.py +137 -0
- shanuz-0.1.1/tests/test_spatial_analysis.py +314 -0
- shanuz-0.1.1/tutorials/README.md +293 -0
- shanuz-0.1.1/tutorials/advanced_pbmc8k_subclustering.md +351 -0
- shanuz-0.1.1/tutorials/cbmc_citeseq_tutorial.py +246 -0
- shanuz-0.1.1/tutorials/compare_xenium_anchors.py +69 -0
- shanuz-0.1.1/tutorials/figures/01_qc_violin.png +0 -0
- shanuz-0.1.1/tutorials/figures/02_qc_scatter.png +0 -0
- shanuz-0.1.1/tutorials/figures/02a_qc_scatter_mt.png +0 -0
- shanuz-0.1.1/tutorials/figures/02b_qc_scatter_feat.png +0 -0
- shanuz-0.1.1/tutorials/figures/03_variable_features.png +0 -0
- shanuz-0.1.1/tutorials/figures/04_pca_loadings.png +0 -0
- shanuz-0.1.1/tutorials/figures/05_pca_dimplot.png +0 -0
- shanuz-0.1.1/tutorials/figures/06_elbow_plot.png +0 -0
- shanuz-0.1.1/tutorials/figures/07_umap_clusters.png +0 -0
- shanuz-0.1.1/tutorials/figures/08_feature_plots.png +0 -0
- shanuz-0.1.1/tutorials/figures/09_marker_violins.png +0 -0
- shanuz-0.1.1/tutorials/figures/09b_marker_violins_counts.png +0 -0
- shanuz-0.1.1/tutorials/figures/10_marker_heatmap.png +0 -0
- shanuz-0.1.1/tutorials/figures/11_umap_labeled.png +0 -0
- shanuz-0.1.1/tutorials/figures/12_ridge_plot.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/01_qc_violin.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/02_elbow_plot.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/03_umap_global_clusters.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/04_umap_global_celltypes.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/05_lineage_featureplots.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/06_global_markers_heatmap.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/07_umap_tnk_subclusters.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/08_umap_tnk_subsets.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/09_tnk_subset_featureplots.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/10_tnk_subset_violins.png +0 -0
- shanuz-0.1.1/tutorials/figures_advanced/11_tnk_markers_heatmap.png +0 -0
- shanuz-0.1.1/tutorials/figures_multimodal/01_rna_umap_clusters.png +0 -0
- shanuz-0.1.1/tutorials/figures_multimodal/02_rna_umap_celltypes.png +0 -0
- shanuz-0.1.1/tutorials/figures_multimodal/03_adt_featureplots.png +0 -0
- shanuz-0.1.1/tutorials/figures_multimodal/04_protein_vs_rna.png +0 -0
- shanuz-0.1.1/tutorials/figures_multimodal/05_adt_ridgeplots.png +0 -0
- shanuz-0.1.1/tutorials/figures_multimodal/06_adt_scatter_CD4_CD8.png +0 -0
- shanuz-0.1.1/tutorials/figures_multimodal/07_adt_scatter_CD19_CD3.png +0 -0
- shanuz-0.1.1/tutorials/figures_sctransform/01_sct_umap_clusters.png +0 -0
- shanuz-0.1.1/tutorials/figures_sctransform/02_sct_umap_celltypes.png +0 -0
- shanuz-0.1.1/tutorials/figures_sctransform/03_sct_featureplots_1.png +0 -0
- shanuz-0.1.1/tutorials/figures_sctransform/04_sct_featureplots_2.png +0 -0
- shanuz-0.1.1/tutorials/figures_sctransform/05_sct_violins.png +0 -0
- shanuz-0.1.1/tutorials/figures_sctransform/06_sct_vs_std_umap.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/01_qc_violin.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/02_umap_celltype.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/03_image_celltype.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/04_image_clusters.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/05_image_feature_Slc17a7.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/06_image_niches.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/07_image_focal.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/anchors.json +82 -0
- shanuz-0.1.1/tutorials/figures_spatial/r_01_qc_violin.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/r_02_umap_celltype.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/r_03_image_celltype.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/r_04_image_clusters.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/r_05_image_feature_Slc17a7.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/r_06_image_niches.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/r_07_image_focal.png +0 -0
- shanuz-0.1.1/tutorials/figures_spatial/r_reference.json +82 -0
- shanuz-0.1.1/tutorials/generate_advanced_plots.py +109 -0
- shanuz-0.1.1/tutorials/generate_multimodal_plots.py +110 -0
- shanuz-0.1.1/tutorials/generate_plots.py +192 -0
- shanuz-0.1.1/tutorials/generate_sctransform_plots.py +97 -0
- shanuz-0.1.1/tutorials/generate_spatial_plots.py +221 -0
- shanuz-0.1.1/tutorials/multimodal_citeseq.md +300 -0
- shanuz-0.1.1/tutorials/pbmc3k_sctransform_tutorial.py +240 -0
- shanuz-0.1.1/tutorials/pbmc3k_tutorial.md +1002 -0
- shanuz-0.1.1/tutorials/pbmc3k_tutorial.py +373 -0
- shanuz-0.1.1/tutorials/pbmc8k_subclustering_tutorial.py +309 -0
- shanuz-0.1.1/tutorials/sctransform_vignette.md +282 -0
- shanuz-0.1.1/tutorials/xenium_spatial_tutorial.md +586 -0
- shanuz-0.1.1/tutorials/xenium_spatial_verify.R +186 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v5
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
run: uv python install ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Create venv and install
|
|
25
|
+
run: |
|
|
26
|
+
uv venv --python ${{ matrix.python-version }}
|
|
27
|
+
uv pip install -e ".[all]"
|
|
28
|
+
|
|
29
|
+
- name: Lint (ruff, advisory)
|
|
30
|
+
# Pre-existing lint debt in older modules is not yet cleared, so the
|
|
31
|
+
# full check is informational; it must not gate the build.
|
|
32
|
+
run: uv run ruff check shanuz || true
|
|
33
|
+
|
|
34
|
+
- name: Run tests
|
|
35
|
+
run: uv run pytest tests/ -q
|
shanuz-0.1.1/.gitignore
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
*.egg
|
|
7
|
+
*.egg-info/
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
.eggs/
|
|
11
|
+
|
|
12
|
+
# Virtual environments (uv)
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# uv
|
|
18
|
+
.uv/
|
|
19
|
+
uv.lock
|
|
20
|
+
|
|
21
|
+
# Testing
|
|
22
|
+
.pytest_cache/
|
|
23
|
+
.coverage
|
|
24
|
+
htmlcov/
|
|
25
|
+
.tox/
|
|
26
|
+
|
|
27
|
+
# IDE
|
|
28
|
+
.vscode/
|
|
29
|
+
.idea/
|
|
30
|
+
*.swp
|
|
31
|
+
*.swo
|
|
32
|
+
|
|
33
|
+
# Data cache
|
|
34
|
+
shanuz_data/
|
|
35
|
+
~/.shanuz_data/
|
|
36
|
+
|
|
37
|
+
# OS
|
|
38
|
+
.DS_Store
|
|
39
|
+
Thumbs.db
|
shanuz-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shanika Amarasoma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
shanuz-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: shanuz
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Python single-cell genomics toolkit — a port of Seurat's core data structures and analysis pipeline
|
|
5
|
+
Project-URL: Homepage, https://github.com/GenomicAI/shanuz
|
|
6
|
+
Project-URL: Repository, https://github.com/GenomicAI/shanuz
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/GenomicAI/shanuz/issues
|
|
8
|
+
Author-email: Shanika Amarasoma <shanika.amarasoma@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: RNA-seq,bioinformatics,genomics,scRNA-seq,single-cell
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: numpy>=1.24
|
|
22
|
+
Requires-Dist: packaging>=23.0
|
|
23
|
+
Requires-Dist: pandas>=2.0
|
|
24
|
+
Requires-Dist: scipy>=1.10
|
|
25
|
+
Provides-Extra: all
|
|
26
|
+
Requires-Dist: anndata>=0.10; extra == 'all'
|
|
27
|
+
Requires-Dist: build; extra == 'all'
|
|
28
|
+
Requires-Dist: leidenalg>=0.10; extra == 'all'
|
|
29
|
+
Requires-Dist: matplotlib>=3.7; extra == 'all'
|
|
30
|
+
Requires-Dist: numba>=0.59; extra == 'all'
|
|
31
|
+
Requires-Dist: pytest-cov; extra == 'all'
|
|
32
|
+
Requires-Dist: pytest>=7; extra == 'all'
|
|
33
|
+
Requires-Dist: python-igraph>=0.11; extra == 'all'
|
|
34
|
+
Requires-Dist: ruff; extra == 'all'
|
|
35
|
+
Requires-Dist: scikit-learn>=1.3; extra == 'all'
|
|
36
|
+
Requires-Dist: scikit-misc>=0.3; extra == 'all'
|
|
37
|
+
Requires-Dist: seaborn>=0.12; extra == 'all'
|
|
38
|
+
Requires-Dist: statsmodels>=0.14; extra == 'all'
|
|
39
|
+
Requires-Dist: twine; extra == 'all'
|
|
40
|
+
Requires-Dist: umap-learn>=0.5; extra == 'all'
|
|
41
|
+
Provides-Extra: analysis
|
|
42
|
+
Requires-Dist: leidenalg>=0.10; extra == 'analysis'
|
|
43
|
+
Requires-Dist: matplotlib>=3.7; extra == 'analysis'
|
|
44
|
+
Requires-Dist: numba>=0.59; extra == 'analysis'
|
|
45
|
+
Requires-Dist: python-igraph>=0.11; extra == 'analysis'
|
|
46
|
+
Requires-Dist: scikit-learn>=1.3; extra == 'analysis'
|
|
47
|
+
Requires-Dist: scikit-misc>=0.3; extra == 'analysis'
|
|
48
|
+
Requires-Dist: seaborn>=0.12; extra == 'analysis'
|
|
49
|
+
Requires-Dist: statsmodels>=0.14; extra == 'analysis'
|
|
50
|
+
Requires-Dist: umap-learn>=0.5; extra == 'analysis'
|
|
51
|
+
Provides-Extra: anndata
|
|
52
|
+
Requires-Dist: anndata>=0.10; extra == 'anndata'
|
|
53
|
+
Provides-Extra: dev
|
|
54
|
+
Requires-Dist: build; extra == 'dev'
|
|
55
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
56
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
57
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
58
|
+
Requires-Dist: twine; extra == 'dev'
|
|
59
|
+
Description-Content-Type: text/markdown
|
|
60
|
+
|
|
61
|
+
# Shanuz — Python Single-Cell Genomics Toolkit
|
|
62
|
+
|
|
63
|
+
[](https://www.python.org/downloads/)
|
|
64
|
+
[](https://opensource.org/licenses/MIT)
|
|
65
|
+
|
|
66
|
+
**Shanuz** is a Python port of the [Seurat](https://satijalab.org/seurat/) single-cell RNA-seq
|
|
67
|
+
analysis framework, implementing Seurat's core data structures, preprocessing pipeline,
|
|
68
|
+
dimensionality reduction, clustering, and marker detection — entirely in Python.
|
|
69
|
+
|
|
70
|
+
> The package is spiritually and algorithmically faithful to Seurat v5 while providing a
|
|
71
|
+
> pure-Python, pip-installable alternative that integrates naturally with NumPy, SciPy,
|
|
72
|
+
> and AnnData ecosystems.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Features
|
|
77
|
+
|
|
78
|
+
- **Shanuz object** — mirrors the R `Seurat` S4 class with `__slots__`-based Python classes
|
|
79
|
+
- **Assay5** — sparse-matrix-backed multi-layer assay (counts, data, scale.data)
|
|
80
|
+
- **Preprocessing** — `normalize_data`, `find_variable_features` (VST), `scale_data`, `percentage_feature_set`
|
|
81
|
+
- **SCTransform** — `sctransform` (regularized negative-binomial Pearson residuals)
|
|
82
|
+
- **Signature scoring** — `add_module_score`, `cell_cycle_scoring` (S/G2M + Phase)
|
|
83
|
+
- **Dimensionality reduction** — `run_pca` (via scikit-learn)
|
|
84
|
+
- **Nearest-neighbour graph** — `find_neighbors` (KNN + SNN)
|
|
85
|
+
- **Clustering** — `find_clusters` (Louvain via python-igraph, Leiden via leidenalg)
|
|
86
|
+
- **UMAP** — `run_umap` (via umap-learn)
|
|
87
|
+
- **PC significance** — `jack_straw`, `score_jackstraw` (JackStraw permutation test)
|
|
88
|
+
- **Differential expression** — `find_markers`, `find_all_markers` (`wilcox` tie-corrected, `t`, `LR`, `negbinom`, `roc`)
|
|
89
|
+
- **Plotting** — `dim_plot`, `feature_plot`, `vln_plot`, `dot_plot`, `elbow_plot`, `do_heatmap`, `dim_heatmap`, `feature_scatter`, `variable_feature_plot`, `ridge_plot` (matplotlib/seaborn)
|
|
90
|
+
- **AnnData interoperability** — `as_anndata`, `from_anndata`
|
|
91
|
+
- **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`
|
|
92
|
+
- **PBMC 3k tutorial** — end-to-end validated against the official Seurat tutorial
|
|
93
|
+
- **PBMC 8k advanced tutorial** — larger dataset + T/NK subclustering workflow
|
|
94
|
+
- **CITE-seq multimodal tutorial** — RNA + surface protein (ADT) with CLR normalization
|
|
95
|
+
- **Xenium spatial tutorial** — spatial neighbourhood/niche analysis, verified to 8 s.f. against R Seurat
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Installation
|
|
100
|
+
|
|
101
|
+
Shanuz is not yet published to PyPI. Install directly from the GitHub repository.
|
|
102
|
+
|
|
103
|
+
### With uv (recommended)
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Install uv if you haven't already
|
|
107
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS/Linux
|
|
108
|
+
# or: powershell -c "irm https://astral.sh/uv/install.ps1 | iex" # Windows
|
|
109
|
+
|
|
110
|
+
git clone https://github.com/GenomicAI/shanuz.git
|
|
111
|
+
cd shanuz
|
|
112
|
+
uv venv
|
|
113
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
114
|
+
uv pip install -e ".[analysis]"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### With pip
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
git clone https://github.com/GenomicAI/shanuz.git
|
|
121
|
+
cd shanuz
|
|
122
|
+
pip install -e ".[analysis]"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Full development installation (includes tests and linting)
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
git clone https://github.com/GenomicAI/shanuz.git
|
|
129
|
+
cd shanuz
|
|
130
|
+
uv venv
|
|
131
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
132
|
+
uv pip install -e ".[all]"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Quick Start
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
import scipy.sparse as sp
|
|
141
|
+
import numpy as np
|
|
142
|
+
from shanuz import create_shanuz_object
|
|
143
|
+
|
|
144
|
+
# Create a Shanuz object from a counts matrix
|
|
145
|
+
counts = sp.random(2000, 500, density=0.2, format="csc")
|
|
146
|
+
sobj = create_shanuz_object(counts, project="my_project", min_cells=3, min_features=200)
|
|
147
|
+
print(sobj)
|
|
148
|
+
# Shanuz object — my_project
|
|
149
|
+
# 500 cells × 2000 features
|
|
150
|
+
# Active assay: 'RNA'
|
|
151
|
+
# Reductions: []
|
|
152
|
+
# Version: 5.4.0
|
|
153
|
+
|
|
154
|
+
# Access metadata
|
|
155
|
+
print(sobj.meta_data.head())
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Tutorials
|
|
161
|
+
|
|
162
|
+
Three end-to-end tutorials — from basic guided clustering to multimodal CITE-seq —
|
|
163
|
+
each pairing R Seurat code side-by-side with the Python Shanuz equivalent.
|
|
164
|
+
See **[`tutorials/README.md`](tutorials/README.md)** for the full index.
|
|
165
|
+
|
|
166
|
+
| # | Tutorial | Dataset | Complexity |
|
|
167
|
+
|---|----------|---------|-----------|
|
|
168
|
+
| 1 | [PBMC 3k — Guided Clustering](tutorials/pbmc3k_tutorial.md) | 3k PBMCs · 10x Genomics | Beginner |
|
|
169
|
+
| 2 | [PBMC 8k — Advanced Subclustering](tutorials/advanced_pbmc8k_subclustering.md) | 8k PBMCs · GRCh38 | Intermediate |
|
|
170
|
+
| 3 | [CBMC CITE-seq — Multimodal](tutorials/multimodal_citeseq.md) | 8,600 CBMCs · RNA + 13 proteins | Advanced |
|
|
171
|
+
| 4 | [PBMC 3k — SCTransform](tutorials/sctransform_vignette.md) | 3k PBMCs · 10x Genomics | Advanced |
|
|
172
|
+
| 5 | [Xenium — Spatial (R vs Python)](tutorials/xenium_spatial_tutorial.md) | 36k cells · 10x Xenium mouse brain | Spatial |
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Tutorial 1 — PBMC 3k
|
|
176
|
+
python tutorials/pbmc3k_tutorial.py && python tutorials/generate_plots.py
|
|
177
|
+
|
|
178
|
+
# Tutorial 2 — PBMC 8k subclustering
|
|
179
|
+
python tutorials/pbmc8k_subclustering_tutorial.py && python tutorials/generate_advanced_plots.py
|
|
180
|
+
|
|
181
|
+
# Tutorial 3 — CITE-seq multimodal
|
|
182
|
+
python tutorials/cbmc_citeseq_tutorial.py && python tutorials/generate_multimodal_plots.py
|
|
183
|
+
|
|
184
|
+
# Tutorial 4 — SCTransform
|
|
185
|
+
python tutorials/pbmc3k_sctransform_tutorial.py && python tutorials/generate_sctransform_plots.py
|
|
186
|
+
|
|
187
|
+
# Tutorial 5 — Xenium spatial (auto-downloads ~20 MB)
|
|
188
|
+
python tutorials/generate_spatial_plots.py
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## API Reference
|
|
194
|
+
|
|
195
|
+
### Object creation
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from shanuz import create_shanuz_object
|
|
199
|
+
|
|
200
|
+
pbmc = create_shanuz_object(
|
|
201
|
+
counts, # scipy.sparse CSC/CSR or numpy ndarray (genes × cells)
|
|
202
|
+
project="pbmc3k",
|
|
203
|
+
min_cells=3, # filter genes present in fewer than N cells
|
|
204
|
+
min_features=200, # filter cells with fewer than N detected genes
|
|
205
|
+
)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Preprocessing
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
from shanuz.preprocessing import (
|
|
212
|
+
normalize_data,
|
|
213
|
+
find_variable_features,
|
|
214
|
+
scale_data,
|
|
215
|
+
percentage_feature_set,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
percentage_feature_set(pbmc, pattern=r"^MT-", col_name="percent.mt")
|
|
219
|
+
normalize_data(pbmc, normalization_method="LogNormalize", scale_factor=10000)
|
|
220
|
+
find_variable_features(pbmc, selection_method="vst", nfeatures=2000)
|
|
221
|
+
scale_data(pbmc)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Dimensionality reduction & clustering
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
from shanuz.reduction import run_pca
|
|
228
|
+
from shanuz.neighbors import find_neighbors
|
|
229
|
+
from shanuz.clustering import find_clusters
|
|
230
|
+
from shanuz.umap import run_umap
|
|
231
|
+
|
|
232
|
+
run_pca(pbmc, n_pcs=50)
|
|
233
|
+
find_neighbors(pbmc, dims=range(10), k_param=20)
|
|
234
|
+
find_clusters(pbmc, resolution=0.5)
|
|
235
|
+
run_umap(pbmc, dims=range(10))
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Differential expression
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
from shanuz.markers import find_markers, find_all_markers
|
|
242
|
+
|
|
243
|
+
markers = find_markers(pbmc, ident_1=1)
|
|
244
|
+
all_markers = find_all_markers(pbmc, only_pos=True, logfc_threshold=0.25)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Plotting
|
|
248
|
+
|
|
249
|
+
All plotting functions return a `matplotlib.figure.Figure` — save or display as needed.
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
from shanuz.plotting import (
|
|
253
|
+
dim_plot, # DimPlot — cells on UMAP/PCA coloured by ident
|
|
254
|
+
feature_plot, # FeaturePlot — gene expression on embedding
|
|
255
|
+
vln_plot, # VlnPlot — violin plots per cluster
|
|
256
|
+
elbow_plot, # ElbowPlot — stdev per PC
|
|
257
|
+
feature_scatter, # FeatureScatter — two features vs each other
|
|
258
|
+
variable_feature_plot, # VariableFeaturePlot — mean-variance HVG plot
|
|
259
|
+
dim_heatmap, # DimHeatmap — top loading genes per PC
|
|
260
|
+
do_heatmap, # DoHeatmap — expression heatmap sorted by cluster
|
|
261
|
+
ridge_plot, # RidgePlot — ridgeline plots per cluster
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
# Quick examples
|
|
265
|
+
fig = dim_plot(pbmc, reduction="umap", label=True)
|
|
266
|
+
fig = feature_plot(pbmc, ["LYZ", "MS4A1", "NKG7"], reduction="umap", ncol=3)
|
|
267
|
+
fig = vln_plot(pbmc, ["LYZ", "CD3D", "PPBP"], group_by=None)
|
|
268
|
+
fig = elbow_plot(pbmc, ndims=20)
|
|
269
|
+
fig = do_heatmap(pbmc, top_marker_genes)
|
|
270
|
+
fig.savefig("output.png", dpi=150, bbox_inches="tight")
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
| Shanuz function | R Seurat equivalent |
|
|
274
|
+
|-----------------|---------------------|
|
|
275
|
+
| `dim_plot` | `DimPlot` |
|
|
276
|
+
| `feature_plot` | `FeaturePlot` |
|
|
277
|
+
| `vln_plot` | `VlnPlot` |
|
|
278
|
+
| `dot_plot` | `DotPlot` |
|
|
279
|
+
| `elbow_plot` | `ElbowPlot` |
|
|
280
|
+
| `feature_scatter` | `FeatureScatter` |
|
|
281
|
+
| `variable_feature_plot` | `VariableFeaturePlot` |
|
|
282
|
+
| `dim_heatmap` | `DimHeatmap` |
|
|
283
|
+
| `do_heatmap` | `DoHeatmap` |
|
|
284
|
+
| `ridge_plot` | `RidgePlot` |
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Data Structures
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
Shanuz
|
|
292
|
+
├── assays: dict[str, Assay5]
|
|
293
|
+
│ └── "RNA"
|
|
294
|
+
│ ├── layers["counts"] # raw integer counts (genes × cells)
|
|
295
|
+
│ ├── layers["data"] # log-normalized (genes × cells)
|
|
296
|
+
│ └── layers["scale.data"] # z-scored (genes × cells)
|
|
297
|
+
├── meta_data: pd.DataFrame # per-cell metadata
|
|
298
|
+
├── reductions: dict
|
|
299
|
+
│ ├── "pca": DimReduc # PCA embeddings + loadings
|
|
300
|
+
│ └── "umap": DimReduc # UMAP embeddings
|
|
301
|
+
├── graphs: dict
|
|
302
|
+
│ ├── "RNA_nn": Graph # KNN graph
|
|
303
|
+
│ └── "RNA_snn": Graph # SNN graph
|
|
304
|
+
└── commands: list[ShanuzCommand] # audit log
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Roadmap
|
|
310
|
+
|
|
311
|
+
See **[`ROADMAP.md`](ROADMAP.md)** for the full development plan. Upcoming milestones:
|
|
312
|
+
|
|
313
|
+
| Milestone | Focus |
|
|
314
|
+
|-----------|-------|
|
|
315
|
+
| v0.2.0 | Batch correction — Harmony, CCA/RPCA, `IntegrateLayers` |
|
|
316
|
+
| v0.3.0 | Reference mapping — `FindTransferAnchors`, `TransferData`, `MapQuery` |
|
|
317
|
+
| v0.4.0 | Multimodal WNN — `FindMultiModalNeighbors`, joint UMAP/clustering |
|
|
318
|
+
| v0.5.0 | Additional reductions — t-SNE, ICA, SPCA, GLM-PCA |
|
|
319
|
+
| v0.6.0 | Pseudobulk DE — `AggregateExpression`, DESeq2, MAST, `FindConservedMarkers` |
|
|
320
|
+
| 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 |
|
|
321
|
+
| v0.8.0 | Scale — BPCells-style lazy matrices, `SketchData`, `ProjectData` |
|
|
322
|
+
| v0.9.0 | Specialized — `HTODemux`, Mixscape (CRISPR screens) |
|
|
323
|
+
| v0.10.0 | Infrastructure — PyPI, GitHub Actions CI, type annotations, MkDocs site |
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Running Tests
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
uv pip install -e ".[dev]"
|
|
331
|
+
pytest tests/ -v
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
All 144 unit tests pass.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Dependencies
|
|
339
|
+
|
|
340
|
+
| Package | Purpose |
|
|
341
|
+
|---------|---------|
|
|
342
|
+
| numpy, scipy, pandas | Core numerics and data frames |
|
|
343
|
+
| statsmodels | LOESS smoothing for VST |
|
|
344
|
+
| scikit-learn | PCA |
|
|
345
|
+
| umap-learn | UMAP embedding |
|
|
346
|
+
| python-igraph | Louvain clustering |
|
|
347
|
+
| leidenalg | Leiden clustering |
|
|
348
|
+
| packaging | Version handling |
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Credits
|
|
353
|
+
|
|
354
|
+
**Development assistance:** This package was developed with the help of
|
|
355
|
+
[Claude](https://claude.ai) (Anthropic's AI assistant, claude-sonnet-4-6),
|
|
356
|
+
which assisted in porting the R Seurat codebase to Python, implementing
|
|
357
|
+
the VST algorithm, degree-2 LOESS, Louvain clustering, and validating
|
|
358
|
+
results against the official PBMC 3k tutorial.
|
|
359
|
+
|
|
360
|
+
**Original R Seurat package:**
|
|
361
|
+
The algorithms and data structures in Shanuz are direct Python translations of the
|
|
362
|
+
R [Seurat](https://satijalab.org/seurat/) package by the Satija Lab.
|
|
363
|
+
Please cite the original Seurat papers if you use Shanuz in published work:
|
|
364
|
+
|
|
365
|
+
> Hao Y, Stuart T, Kowalski MH, et al. (2024).
|
|
366
|
+
> **Dictionary learning for integrative, multimodal and scalable single-cell analysis.**
|
|
367
|
+
> *Nature Biotechnology*, 42, 293–304.
|
|
368
|
+
> https://doi.org/10.1038/s41587-023-01767-y
|
|
369
|
+
|
|
370
|
+
> Hao Y, Hao S, Andersen-Nissen E, et al. (2021).
|
|
371
|
+
> **Integrated analysis of multimodal single-cell data.**
|
|
372
|
+
> *Cell*, 184(13), 3573–3587.
|
|
373
|
+
> https://doi.org/10.1016/j.cell.2021.04.048
|
|
374
|
+
|
|
375
|
+
> Stuart T, Butler A, Hoffman P, et al. (2019).
|
|
376
|
+
> **Comprehensive Integration of Single-Cell Data.**
|
|
377
|
+
> *Cell*, 177(7), 1888–1902.
|
|
378
|
+
> https://doi.org/10.1016/j.cell.2019.05.031
|
|
379
|
+
|
|
380
|
+
> Butler A, Hoffman P, Smibert P, Papalexi E, Satija R. (2018).
|
|
381
|
+
> **Integrating single-cell transcriptomic data across different conditions, technologies, and species.**
|
|
382
|
+
> *Nature Biotechnology*, 36, 411–420.
|
|
383
|
+
> https://doi.org/10.1038/nbt.4096
|
|
384
|
+
|
|
385
|
+
**PBMC 3k dataset:**
|
|
386
|
+
10x Genomics. (2016). *3k PBMCs from a Healthy Donor*.
|
|
387
|
+
https://www.10xgenomics.com/resources/datasets/3-k-pb-mcs-from-a-healthy-donor-1-standard-1-1-0
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## License
|
|
392
|
+
|
|
393
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
394
|
+
|
|
395
|
+
This software is an independent reimplementation for educational and research purposes.
|
|
396
|
+
It is not affiliated with, endorsed by, or maintained by the Satija Lab or 10x Genomics.
|