02 · Analytic Pearson residuals#

Mirrors the rapids-singlecell Pearson-residuals tutorial. Pearson residuals (Lause et al. 2021) are an alternative to log-normalization that models counts with a regularized negative binomial; the residuals feed directly into PCA. All on the Metal GPU via metal-SingleCell.

import warnings; warnings.filterwarnings('ignore')
import numpy as np, scanpy as sc
import metalsinglecell as msc

Load and QC#

adata = sc.datasets.pbmc3k(); adata.var_names_make_unique()
adata.var['mt'] = adata.var_names.str.startswith('MT-')
sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], inplace=True)
msc.pp.filter_cells(adata, min_genes=200)
msc.pp.filter_genes(adata, min_cells=3)
adata = adata[adata.obs.pct_counts_mt < 20].copy()
adata.layers['counts'] = adata.X.copy()
adata.shape
(2698, 13714)

Highly variable genes from raw counts#

The rapids tutorial uses flavor='pearson_residuals'; metal-SingleCell currently offers seurat_v3 (the closest count-based selector), which also operates directly on the counts layer.

msc.pp.highly_variable_genes(adata, n_top_genes=2000, flavor='seurat_v3', layer='counts')
adata = adata[:, adata.var.highly_variable].copy()
adata.X = adata.layers['counts'].copy()   # residuals are computed from raw counts
adata.shape
(2698, 2000)

Pearson residuals → PCA#

normalize_pearson_residuals writes the residuals into adata.X; PCA then runs on them.

msc.pp.normalize_pearson_residuals(adata, theta=100.0)
msc.pp.pca(adata, n_comps=50, use_highly_variable=False)
sc.pl.pca_variance_ratio(adata, log=True, n_pcs=50)
../_images/5bb4f5c5bccbc8535d464d44539944d53ac8b991dc6dd93a984585315b0f8f5b.png

Neighbors, UMAP, Leiden on the residual PCA#

msc.pp.neighbors(adata, n_neighbors=15)
msc.tl.umap(adata)
msc.tl.leiden(adata, resolution=1.0, backend='gpu')
sc.pl.umap(adata, color=['leiden'], legend_loc='on data')
../_images/a8211312778dc9d363949d28429cd3a2193a5870a0197fb1c1717a3e7e269665.png

Pearson-residual normalization (no log1p, no scaling) produces a clustered embedding directly from counts — useful when sequencing depth varies strongly across cells.