spatial-smooth

Composable smoothing of gene-set signatures over space and cell state.

Danger

This package is for visualization only. It exists to make spatial regions easier to see. Its output is a picture, not data.

Smoothing deliberately makes neighbouring cells look like one another. That is exactly what you want when you are trying to see where a program is active, and exactly what you must not hand to a statistical test. A smoothed score is spatially autocorrelated by construction: the cells are no longer independent observations, so differential expression, differential abundance, clustering, correlations and p-values computed on smoothed values will find “significant” structure in pure noise.

Look at the smoothed values. Do the statistics on the raw ones (adata.obs[f"{name}_raw"], which every call writes for you), using a method that accounts for spatial dependence.

Every cell in a single-cell or spatial assay is measured independently, so a per-cell signature score is dominated by dropout and sampling noise – a speckle of dots in which a real anatomical region is genuinely hard to spot. Smoothing lets neighbouring cells borrow statistical strength, turning that speckle into a coherent field you can read at a glance. Which neighbours count is the scientific choice, and this package makes it explicit.

smoothing

neighbours are…

recovers

spatial

physically adjacent cells (obsm["spatial"])

tissue architecture: niches, layers, gradients

cell state

transcriptionally similar cells (a diffusion map)

biological structure, independent of position

both, composed

first the manifold, then the tissue

denoised expression laid out in space

The three are one argument apart:

import spatial_smooth as ss

ss.smooth(adata, genes, "sig")                     # spatial only  (the default)
ss.smooth(adata, genes, "sig", steps="dm")         # cell state only
ss.smooth(adata, genes, "sig", steps="dm+spatial") # both, in that order
ss.pl.signature(adata, "sig")                      # raw vs smoothed, on tissue

Results are written into the AnnData. Save it, ship it, reload it – plotting never recomputes.

Indices