spanorm

spanorm(
    data,
    sample_p=0.25,
    gene_model='nb',
    adj_method='auto',
    scale_factor=1.0,
    df_tps=6,
    lambda_a=0.0001,
    batch_key=None,
    batch=None,
    size_factors=None,
    tol=0.0001,
    step_factor=0.5,
    maxit_nb=50,
    maxit_psi=25,
    maxn_psi=500,
    overwrite=False,
    backend='auto',
    n_jobs=1,
    verbose=True,
    layer=None,
    spatial_key='spatial',
    table_key=None,
    random_state=0,
    copy=False,
    **kwargs,
)

Spatially-dependent normalisation of spatial transcriptomics counts (R SpaNorm).

Fits (or reuses) a spatial regression model for library size and biology on the raw counts, then writes the adjusted data to adata.layers["logcounts"]. The fit is stored with :func:spanormpy._fit.store_fit under the name "spanorm" and the adjustment method in adata.uns["spanorm"]["adj_method"].

Parameters

Name Type Description Default
data An AnnData (raw counts in X or layer, coordinates in obsm[spatial_key]) or a SpatialData object (its table, chosen with table_key). required
sample_p float Maximum proportion of cells/spots sampled for model fitting. 0.25
gene_model str Gene model; "nb" for counts. 'nb'
adj_method str "auto" (= "logpac"), "logpac", "pearson", "medbio" or "meanbio". 'auto'
scale_factor float Sample-specific scaling factor for the adjusted counts. 1.0
df_tps Degrees of freedom of the thin-plate spline, length 1 (biology; library size gets half) or 2 (biology, library size). Truncated to integers like R’s as.integer. 6
lambda_a Smoothing parameter for the regression coefficients, length 1 or 2 (biology, library size). The value used is lambda_a * n_cells. 0.0001
batch_key str | None Batch to regress out: an obs column name, or a vector / numeric design matrix (see :func:spanormpy._io.check_batch). Strings and categoricals are batches; a numeric vector is one covariate column (R model.matrix semantics). None
batch str | None Batch to regress out: an obs column name, or a vector / numeric design matrix (see :func:spanormpy._io.check_batch). Strings and categoricals are batches; a numeric vector is one covariate column (R model.matrix semantics). None
size_factors Precomputed size factors (array, or an obs column name). If None they are computed (scran-style pooled factors) when a fit is needed, and stored in obs["spanorm_size_factors"]. obs["size_factors"] is never read. None
tol float Fitting controls, as in R. 0.0001
step_factor float Fitting controls, as in R. 0.0001
maxit_nb float Fitting controls, as in R. 0.0001
maxit_psi float Fitting controls, as in R. 0.0001
maxn_psi float Fitting controls, as in R. 0.0001
overwrite bool Force a refit even if a matching fit is stored. A stored fit is also refitted if gene_model, df_tps, lambda_a or batch changed. False
backend str "auto", "cpu" or "gpu". 'auto'
n_jobs int Threads used to normalise gene blocks in parallel (R BPPARAM). 1
verbose bool Print progress messages (to stderr, like R’s message). True
random_state int Seed of the numpy generator behind the cell and dispersion subsampling. 0
copy bool Return a modified copy instead of modifying data in place. False
**kwargs R’s ...: gpu_mem_budget and winsor are passed to the NB fit; any other key is ignored with a UserWarning. {}

Returns

Name Type Description
None, or with copy=True a modified copy of the same container type (an
AnnData, or a new SpatialData whose table is the result; the input is untouched).

Examples

Note

The code below runs when the site is built, on a small pre-fitted subset of HumanDLPFC (301 genes x 4015 spots; spanorm(sample_p=0.05, df_tps=2), spanorm_svg() and spanorm_pca() already applied) that is fitted once per build and loaded as adata. The outputs are those of the code shown.

import spanormpy as sn
# adata: the HumanDLPFC AnnData (raw counts in X, coordinates in obsm["spatial"]),
# already fitted with sn.spanorm(adata, sample_p=0.05, df_tps=2)
# an existing, matching fit in adata is reused; only the adjustment is recomputed
sn.spanorm(adata, sample_p=0.05, df_tps=2, tol=1e-2, random_state=36)
adata
AnnData object with n_obs × n_vars = 4015 × 301
    obs: 'AnnotatedCluster', 'cell_count', 'spanorm_sampling', 'spanorm_size_factors', 'spanorm_null_sampling'
    var: 'spanorm_gmean', 'spanorm_psi', 'spanorm_null_gmean', 'spanorm_null_psi', 'svg_F', 'svg_p', 'svg_fdr', 'svg_F_raw'
    uns: 'X_name', 'X_spanorm_pca', 'spanorm'
    obsm: 'X_spanorm_pca', 'spanorm_W', 'spanorm_null_W', 'spatial'
    varm: 'X_spanorm_pca_loadings', 'spanorm_alpha', 'spanorm_null_alpha'
    layers: 'logcounts', None (.X)
# the normalised values are in the "logcounts" layer; the fit lives in var, varm, obsm and uns
adata.layers["logcounts"][:3, :3]
array([[1.5849625 , 2.32192809, 2.5849625 ],
       [2.        , 1.        , 0.        ],
       [3.        , 1.5849625 , 2.        ]])