Metadata-Version: 2.5
Name: sctransform
Version: 0.2.0
Summary: Pure-python implementation of R sctransform: variance-stabilizing transformation for single-cell UMI data (no R/rpy2 required)
Project-URL: Homepage, https://github.com/Zikun-Yang/SCTransform
Project-URL: Repository, https://github.com/Zikun-Yang/SCTransform
Project-URL: Issues, https://github.com/Zikun-Yang/SCTransform/issues
Author: Zikun Yang
License-Expression: GPL-3.0-only
License-File: LICENSE
Keywords: normalization,scRNA-seq,scanpy,sctransform,seurat,single-cell
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.10
Requires-Dist: numpy>=1.21
Requires-Dist: pandas>=1.3
Requires-Dist: scipy>=1.7
Provides-Extra: scanpy
Requires-Dist: anndata>=0.8; extra == 'scanpy'
Requires-Dist: scanpy>=1.9; extra == 'scanpy'
Provides-Extra: test
Requires-Dist: anndata>=0.8; extra == 'test'
Requires-Dist: matplotlib>=3.5; extra == 'test'
Requires-Dist: pytest; extra == 'test'
Description-Content-Type: text/markdown

# sctransform

**Pure-python implementation of R [sctransform](https://github.com/satijalab/sctransform)** — variance-stabilizing transformation for single-cell UMI count data. No R, no rpy2 required.

Implements both model flavors of R sctransform:

* **v2 model** (`vst.flavor="v2"` in R): negative-binomial GLM with library-size offset (slope fixed at `log(10)`), per-gene intercept + overdispersion estimation, Poisson-gene exclusion.
* **v1 model** (original sctransform): per-gene Poisson GLM with free slope on `log10_umi`, theta via a port of `MASS::theta.ml`.

Both use kernel-smoothed regularization of parameters — all validated end-to-end against the R reference implementation (with `glmGamPoi`).

## Why

Existing python ports either wrap R via rpy2 (defeats the purpose) or delegate the v2 model to R's `glmGamPoi`. This package re-implements everything natively and numerically matches R:

| Component | Validation vs R |
|---|---|
| Step-1 NB offset GLM (theta, intercept) | log10 θ corr **0.994**, intercept corr **0.9994** |
| `bw.SJ` bandwidth selector | exact to 7 significant digits |
| `ksmooth` (Nadaraya-Watson, normal kernel) | max diff 2e-4 |
| `is_outlier` | identical flags on real data |
| v2 end-to-end Pearson residuals (pbmc3k) | corr **0.99999** |
| v2 UMAP workflow vs Seurat | HVG Jaccard **0.993**, KNN label transfer **0.97** |
| v1 end-to-end Pearson residuals (pbmc3k) | corr **1.000000** (regularized log10 θ corr **1.0000**) |

See `benchmark/` for the full executed notebook and reproduction scripts.

## Installation

```bash
pip install sctransform
# or with the scanpy interface:
pip install sctransform[scanpy]
```

## Quickstart

```python
import scanpy as sc
from sctransform import SCTransform

# adata with raw counts in adata.layers["counts"]
residuals = SCTransform(adata, layer="counts", vst_flavor="v2", var_features_n=3000)

# downstream, Seurat-style: PCA on Pearson residuals of variable features
adata.obsm["X_pca"] = sc.pp.pca(residuals.values, n_comps=30)
sc.pp.neighbors(adata, use_rep="X_pca")
sc.tl.umap(adata)
```

Low-level API (R-like, genes x cells matrix in, full vst output out):

```python
from sctransform import vst
vst_out = vst(umi_matrix, gene_names=genes, vst_flavor="v2")
vst_out["y"]                    # residuals (genes x cells DataFrame)
vst_out["model_parameters_fit"] # regularized per-gene theta / intercept / slope
vst_out["gene_attr"]            # residual_variance etc. (for HVG ranking)
```

## Scope

- [x] v2 model (`glmGamPoi_offset`): fixed slope, intercept + theta learned, `exclude_poisson`
- [x] v1 model (`poisson`/`theta_ml`, free slope) — exact port of `qpois_reg` IRLS + `MASS::theta.ml`
- [x] Pearson & deviance residuals, `min_variance` ("umi_median"), residual clipping
- [x] Cell/gene subsampling (density-based gene sampling, as in R)
- [ ] `batch_var` support — roadmap
- [ ] corrected counts (`return_corrected_umi`) — roadmap

## Relationship to Seurat

`SCTransform(adata, vst_flavor="v2")` replaces `NormalizeData + FindVariableFeatures + ScaleData`:
use the returned residuals as `scale.data` for PCA (as shown above). HVG flags and
regularized model parameters are stored in `adata.var` / `adata.uns["sct"]`.

## Tutorials

- [`tutorials/pbmc3k_sctransform_vs_lognormalize.ipynb`](tutorials/pbmc3k_sctransform_vs_lognormalize.ipynb) -
  end-to-end pbmc3k analysis, side-by-side vs the traditional log-normalize workflow
  (variance-stabilization QC, UMAP, cluster agreement, markers, depth effects).

## License & attribution

GPL-3.0. Contains code ported from R (GPL-2+, R Core Team) and algorithms
re-implemented from R sctransform (GPL-3, Christoph Hafemeister / Rahul Satija lab).

If you use this package, please cite the original publications:

- Hafemeister & Satija, *Normalization and variance stabilization of single-cell RNA-seq data using regularized negative binomial regression*, Genome Biology 2019
- Choudhary & Satija, *Comparison and evaluation of statistical error models for scRNA-seq*, Genome Biology 2022
- Ahlmann-Eltze & Huber, *glmGamPoi: Fitting Gamma-Poisson Generalized Linear Models on Single Cell Count Data*, Bioinformatics 2021
