Changes since 1.0.0rc1:
Breaking changes
-
Python 3.11 or newer is required. Current AnnData and Scanpy releases require
Python 3.12 or newer, while installing this project's test extra on Python
3.10 selects a Pillow version with known security vulnerabilities through
Scanpy's Matplotlib dependency. Python 3.11 supports the patched Pillow
release while retaining compatibility with earlier AnnData and Scanpy
releases. -
Residual clipping is enabled by default, using
clip="seurat"
(sqrt(n_obs / 30)). Passclip=Noneto recover the previous unclipped
behavior. Because the default clips symmetrically, it raisesRuntimeError
when clipping would grow sparse support toclip_max_nnz_ratio(default
2.0) times the input's stored entries; for example, pass
clip_mode="upper", which never grows support. Theclip_modeand
clip_max_nnz_ratiodefaults are unchanged. -
TransformedMatrix.pcaraisesValueErrorwhen it must read amask_var
key or the default"highly_variable"column after the AnnData object it was
fitted from no longer exists. This includes a transform fitted from an
AnnData that was never assigned to a variable, as in
scp.transform(sc.read_h5ad(path), ...). Pass a boolean-arraymask_varor
mask_var=None. The transform does not keep the AnnData in memory. -
Stricter validation: composition-scale shifted CLR now raises
ValueError
when multiplying the shift by a cell's total count overflows float64, instead
of silently collapsing transformed nonzero counts to zero.
New features
- Add
TransformedMatrix.variable_statisticsto compute each gene's mean and
variance under a fitted transform without materializing it, for example to
select highly variable genes by Pearson-residual variance. Statistics include
any residual clipping and default to then_obs - 1denominator used by PCA
total variance. WithResidual(model="poisson", clip="scanpy")andddof=0,
the variances agree with Scanpy's Pearson-residualresidual_variancesfor
theta=np.infin a small synthetic regression test. - Add size-factor-normalized
log1pPCA withlog1p_norm_pca,
log1p_norm_pca_matrix, and theLog1pNormalizedtransform, using a
median-depth default, explicit target totals, or supplied size factors,
including factors stored in AnnData observation columns. - Add named clipping thresholds:
"seurat"(sqrt(n_obs / 30)) and"scanpy"
(sqrt(n_obs)), resolved against the fitted matrix's observation count.
Names select only the threshold; positive floats andNoneremain supported. - Add
transform(..., share_structure=True)to let two-step workflows reuse
the count matrix's sparsity structure and save memory, as one-step analyses
do automatically. Inputs that need canonicalization or conversion to CSR,
int32 indices that must widen to int64, and residual clipping that adds
entries still produce a copy, with aUserWarning. Sharing is
opt-in; do not modify the count matrix's sparsity structure in place, for
example withsort_indices(), while the fitted transform is in use.pca
andmaterializeraiseRuntimeErrorif it changed. - Record the resolved numeric clipping threshold as
clip_thresholdin
transform and PCA metadata, alongside the request inclip. - Identify PCA and correspondence-analysis results with
package_name="sparse-count-pca"alongsidepackage_versionin metadata.
Performance
- Faster PCA setup for large sparse inputs, with lower peak memory.
Centering statistics are computed from sparse row blocks instead of a full
column-major copy of the transform. In a synthetic benchmark of unclipped
float64 Poisson Pearson residuals on 100,000 × 30,000 counts with 71.8
million stored entries, building the centered operator took 1.9 s instead of
12.5 s with 1.0.0rc1, and the process's peak memory fell from 2.6 to 1.6 GiB
(single runs at revision3bf8c2e, one thread). - Lower peak memory for residual PCA, especially with clipping. Residuals
are built in bounded row blocks directly in the requested dtype. On real
data, 22,111 PBMCs × 29,157 genes with 71.8 million stored counts, clipped
Poisson Pearson residual PCA peaked at 2.1 GiB in float32 and 3.2 GiB in
float64, compared with about 5.2 and 4.8 GiB for 1.0.0rc1 (single runs at
revision425238con an M2 MacBook Air). - Count validation and log, CLR, and Dirichlet fitting process arithmetic in
blocks, reducing temporary memory, especially withdtype="float32"
storage. - One-step analyses use less memory by reusing the count matrix's sparsity
structure whenreturn_operator=False. Symmetric clipping that changes
residuals at zero counts, as the defaultclip="seurat"can on real data,
builds new structure instead.
Fixes
- Locked test and documentation environments use patched certifi, Pillow,
nbconvert, Tornado, and urllib3 dependencies. - More accurate gene totals for float32 counts correct the normalization used
by residual PCA and correspondence analysis. Synthetic regression tests
recover100000000 + 1as100000001, where float32 accumulation lost the
small contribution, and verify that fitting agrees with an exact float64
copy of the input. Count totals accumulate in float64 for every input dtype.
These corrections can change float32-input results beyond the last few
digits compared with 1.0.0rc1. - Squared norms behind total variance, explained-variance ratios, and
correspondence-analysis inertia are recomputed directly when cancellation
would leave them accurate to only about eight digits. TransformedMatrix.pcareadsmask_varkeys and the default
"highly_variable"mask from the AnnData object's currentadata.var, so
highly variable genes selected after fitting a transform are used. It
previously read a copy taken at fitting, silently selecting every gene when
that copy had no"highly_variable"column. If the AnnData's genes change
after fitting, keys raiseValueError; boolean-array masks and
mask_var=Nonestill work.TransformedMatrix.materializeraisesIndexErrorfor a boolean mask whose
length does not match its axis, including an empty mask, which previously
selected nothing, and for scalar-boolean or two-dimensional selectors.
Other changes
- Changed summation order introduces last-digit differences in PCA results,
means, and variance statistics compared with 1.0.0rc1.
Documentation
- Add a Performance section to the README comparing time and memory with
Scanpy on real PBMC and mouse brain data. - Add a log1p normalization guide and worked example, and expand
materialize()
examples for its supported selectors. - Clarify transform formulas, shift scales, and overdispersion parameters across
the public API, including how PFlog's dataset-widealphadiffers from
per-genescaled_nboverdispersion and how PFlog relates tocleartools. - Add citation metadata in
CITATION.cffand citation instructions to the
README and documentation home page; releases are archived on Zenodo with a
DOI.