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.
Files changed (134) hide show
  1. shanuz-0.1.1/.github/workflows/ci.yml +35 -0
  2. shanuz-0.1.1/.gitignore +39 -0
  3. shanuz-0.1.1/LICENSE +21 -0
  4. shanuz-0.1.1/PKG-INFO +396 -0
  5. shanuz-0.1.1/README.md +336 -0
  6. shanuz-0.1.1/ROADMAP.md +341 -0
  7. shanuz-0.1.1/pyproject.toml +69 -0
  8. shanuz-0.1.1/shanuz/__init__.py +143 -0
  9. shanuz-0.1.1/shanuz/_sparse.py +68 -0
  10. shanuz-0.1.1/shanuz/_types.py +15 -0
  11. shanuz-0.1.1/shanuz/_utils.py +65 -0
  12. shanuz-0.1.1/shanuz/assay.py +395 -0
  13. shanuz-0.1.1/shanuz/assay5.py +586 -0
  14. shanuz-0.1.1/shanuz/clustering.py +187 -0
  15. shanuz-0.1.1/shanuz/command.py +113 -0
  16. shanuz-0.1.1/shanuz/compat/__init__.py +3 -0
  17. shanuz-0.1.1/shanuz/compat/anndata.py +242 -0
  18. shanuz-0.1.1/shanuz/composition.py +98 -0
  19. shanuz-0.1.1/shanuz/datasets.py +297 -0
  20. shanuz-0.1.1/shanuz/dimreduc.py +192 -0
  21. shanuz-0.1.1/shanuz/generics.py +391 -0
  22. shanuz-0.1.1/shanuz/graph.py +172 -0
  23. shanuz-0.1.1/shanuz/io.py +138 -0
  24. shanuz-0.1.1/shanuz/jackstraw.py +174 -0
  25. shanuz-0.1.1/shanuz/logmap.py +96 -0
  26. shanuz-0.1.1/shanuz/markers.py +411 -0
  27. shanuz-0.1.1/shanuz/mixins/__init__.py +3 -0
  28. shanuz-0.1.1/shanuz/mixins/key_mixin.py +30 -0
  29. shanuz-0.1.1/shanuz/module_score.py +248 -0
  30. shanuz-0.1.1/shanuz/neighbor.py +124 -0
  31. shanuz-0.1.1/shanuz/neighbors.py +151 -0
  32. shanuz-0.1.1/shanuz/plotting.py +1156 -0
  33. shanuz-0.1.1/shanuz/preprocessing.py +619 -0
  34. shanuz-0.1.1/shanuz/py.typed +0 -0
  35. shanuz-0.1.1/shanuz/reduction.py +144 -0
  36. shanuz-0.1.1/shanuz/sctransform.py +264 -0
  37. shanuz-0.1.1/shanuz/shanuz.py +590 -0
  38. shanuz-0.1.1/shanuz/spatial/__init__.py +36 -0
  39. shanuz-0.1.1/shanuz/spatial/analysis.py +239 -0
  40. shanuz-0.1.1/shanuz/spatial/base.py +95 -0
  41. shanuz-0.1.1/shanuz/spatial/centroids.py +119 -0
  42. shanuz-0.1.1/shanuz/spatial/fov.py +275 -0
  43. shanuz-0.1.1/shanuz/spatial/loaders.py +248 -0
  44. shanuz-0.1.1/shanuz/spatial/molecules.py +95 -0
  45. shanuz-0.1.1/shanuz/spatial/segmentation.py +116 -0
  46. shanuz-0.1.1/shanuz/umap.py +79 -0
  47. shanuz-0.1.1/tests/conftest.py +57 -0
  48. shanuz-0.1.1/tests/test_advanced_tutorial.py +101 -0
  49. shanuz-0.1.1/tests/test_analysis.py +324 -0
  50. shanuz-0.1.1/tests/test_anndata_compat.py +41 -0
  51. shanuz-0.1.1/tests/test_assay.py +74 -0
  52. shanuz-0.1.1/tests/test_assay5.py +61 -0
  53. shanuz-0.1.1/tests/test_command.py +39 -0
  54. shanuz-0.1.1/tests/test_dimreduc.py +53 -0
  55. shanuz-0.1.1/tests/test_graph.py +44 -0
  56. shanuz-0.1.1/tests/test_logmap.py +63 -0
  57. shanuz-0.1.1/tests/test_multimodal_tutorial.py +93 -0
  58. shanuz-0.1.1/tests/test_neighbor.py +53 -0
  59. shanuz-0.1.1/tests/test_new_features.py +267 -0
  60. shanuz-0.1.1/tests/test_seurat.py +132 -0
  61. shanuz-0.1.1/tests/test_spatial.py +137 -0
  62. shanuz-0.1.1/tests/test_spatial_analysis.py +314 -0
  63. shanuz-0.1.1/tutorials/README.md +293 -0
  64. shanuz-0.1.1/tutorials/advanced_pbmc8k_subclustering.md +351 -0
  65. shanuz-0.1.1/tutorials/cbmc_citeseq_tutorial.py +246 -0
  66. shanuz-0.1.1/tutorials/compare_xenium_anchors.py +69 -0
  67. shanuz-0.1.1/tutorials/figures/01_qc_violin.png +0 -0
  68. shanuz-0.1.1/tutorials/figures/02_qc_scatter.png +0 -0
  69. shanuz-0.1.1/tutorials/figures/02a_qc_scatter_mt.png +0 -0
  70. shanuz-0.1.1/tutorials/figures/02b_qc_scatter_feat.png +0 -0
  71. shanuz-0.1.1/tutorials/figures/03_variable_features.png +0 -0
  72. shanuz-0.1.1/tutorials/figures/04_pca_loadings.png +0 -0
  73. shanuz-0.1.1/tutorials/figures/05_pca_dimplot.png +0 -0
  74. shanuz-0.1.1/tutorials/figures/06_elbow_plot.png +0 -0
  75. shanuz-0.1.1/tutorials/figures/07_umap_clusters.png +0 -0
  76. shanuz-0.1.1/tutorials/figures/08_feature_plots.png +0 -0
  77. shanuz-0.1.1/tutorials/figures/09_marker_violins.png +0 -0
  78. shanuz-0.1.1/tutorials/figures/09b_marker_violins_counts.png +0 -0
  79. shanuz-0.1.1/tutorials/figures/10_marker_heatmap.png +0 -0
  80. shanuz-0.1.1/tutorials/figures/11_umap_labeled.png +0 -0
  81. shanuz-0.1.1/tutorials/figures/12_ridge_plot.png +0 -0
  82. shanuz-0.1.1/tutorials/figures_advanced/01_qc_violin.png +0 -0
  83. shanuz-0.1.1/tutorials/figures_advanced/02_elbow_plot.png +0 -0
  84. shanuz-0.1.1/tutorials/figures_advanced/03_umap_global_clusters.png +0 -0
  85. shanuz-0.1.1/tutorials/figures_advanced/04_umap_global_celltypes.png +0 -0
  86. shanuz-0.1.1/tutorials/figures_advanced/05_lineage_featureplots.png +0 -0
  87. shanuz-0.1.1/tutorials/figures_advanced/06_global_markers_heatmap.png +0 -0
  88. shanuz-0.1.1/tutorials/figures_advanced/07_umap_tnk_subclusters.png +0 -0
  89. shanuz-0.1.1/tutorials/figures_advanced/08_umap_tnk_subsets.png +0 -0
  90. shanuz-0.1.1/tutorials/figures_advanced/09_tnk_subset_featureplots.png +0 -0
  91. shanuz-0.1.1/tutorials/figures_advanced/10_tnk_subset_violins.png +0 -0
  92. shanuz-0.1.1/tutorials/figures_advanced/11_tnk_markers_heatmap.png +0 -0
  93. shanuz-0.1.1/tutorials/figures_multimodal/01_rna_umap_clusters.png +0 -0
  94. shanuz-0.1.1/tutorials/figures_multimodal/02_rna_umap_celltypes.png +0 -0
  95. shanuz-0.1.1/tutorials/figures_multimodal/03_adt_featureplots.png +0 -0
  96. shanuz-0.1.1/tutorials/figures_multimodal/04_protein_vs_rna.png +0 -0
  97. shanuz-0.1.1/tutorials/figures_multimodal/05_adt_ridgeplots.png +0 -0
  98. shanuz-0.1.1/tutorials/figures_multimodal/06_adt_scatter_CD4_CD8.png +0 -0
  99. shanuz-0.1.1/tutorials/figures_multimodal/07_adt_scatter_CD19_CD3.png +0 -0
  100. shanuz-0.1.1/tutorials/figures_sctransform/01_sct_umap_clusters.png +0 -0
  101. shanuz-0.1.1/tutorials/figures_sctransform/02_sct_umap_celltypes.png +0 -0
  102. shanuz-0.1.1/tutorials/figures_sctransform/03_sct_featureplots_1.png +0 -0
  103. shanuz-0.1.1/tutorials/figures_sctransform/04_sct_featureplots_2.png +0 -0
  104. shanuz-0.1.1/tutorials/figures_sctransform/05_sct_violins.png +0 -0
  105. shanuz-0.1.1/tutorials/figures_sctransform/06_sct_vs_std_umap.png +0 -0
  106. shanuz-0.1.1/tutorials/figures_spatial/01_qc_violin.png +0 -0
  107. shanuz-0.1.1/tutorials/figures_spatial/02_umap_celltype.png +0 -0
  108. shanuz-0.1.1/tutorials/figures_spatial/03_image_celltype.png +0 -0
  109. shanuz-0.1.1/tutorials/figures_spatial/04_image_clusters.png +0 -0
  110. shanuz-0.1.1/tutorials/figures_spatial/05_image_feature_Slc17a7.png +0 -0
  111. shanuz-0.1.1/tutorials/figures_spatial/06_image_niches.png +0 -0
  112. shanuz-0.1.1/tutorials/figures_spatial/07_image_focal.png +0 -0
  113. shanuz-0.1.1/tutorials/figures_spatial/anchors.json +82 -0
  114. shanuz-0.1.1/tutorials/figures_spatial/r_01_qc_violin.png +0 -0
  115. shanuz-0.1.1/tutorials/figures_spatial/r_02_umap_celltype.png +0 -0
  116. shanuz-0.1.1/tutorials/figures_spatial/r_03_image_celltype.png +0 -0
  117. shanuz-0.1.1/tutorials/figures_spatial/r_04_image_clusters.png +0 -0
  118. shanuz-0.1.1/tutorials/figures_spatial/r_05_image_feature_Slc17a7.png +0 -0
  119. shanuz-0.1.1/tutorials/figures_spatial/r_06_image_niches.png +0 -0
  120. shanuz-0.1.1/tutorials/figures_spatial/r_07_image_focal.png +0 -0
  121. shanuz-0.1.1/tutorials/figures_spatial/r_reference.json +82 -0
  122. shanuz-0.1.1/tutorials/generate_advanced_plots.py +109 -0
  123. shanuz-0.1.1/tutorials/generate_multimodal_plots.py +110 -0
  124. shanuz-0.1.1/tutorials/generate_plots.py +192 -0
  125. shanuz-0.1.1/tutorials/generate_sctransform_plots.py +97 -0
  126. shanuz-0.1.1/tutorials/generate_spatial_plots.py +221 -0
  127. shanuz-0.1.1/tutorials/multimodal_citeseq.md +300 -0
  128. shanuz-0.1.1/tutorials/pbmc3k_sctransform_tutorial.py +240 -0
  129. shanuz-0.1.1/tutorials/pbmc3k_tutorial.md +1002 -0
  130. shanuz-0.1.1/tutorials/pbmc3k_tutorial.py +373 -0
  131. shanuz-0.1.1/tutorials/pbmc8k_subclustering_tutorial.py +309 -0
  132. shanuz-0.1.1/tutorials/sctransform_vignette.md +282 -0
  133. shanuz-0.1.1/tutorials/xenium_spatial_tutorial.md +586 -0
  134. 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
@@ -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
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
64
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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.