Skip to content

spatialCooccurrence

spatialCooccurrence

spatialCooccurrence(
    data,
    xCoordinate="X_centroid",
    yCoordinate="Y_centroid",
    zCoordinate=None,
    phenotype="phenotype",
    method="radius",
    radius=30,
    knn=10,
    permutation=1000,
    imageId="imageid",
    subset=None,
    verbose=True,
    label="spatialCooccurrence",
    maxWorkers=-1,
    streamData=False,
    outputDir=None,
    sdataTable=None,
)

Test cell-type adjacency against a permutation null.

Neighbourhoods are found once per image with a BallTree, and every (cell, neighbour) pair is reduced to an integer key so the counts are a single np.bincount. The phenotype labels are then shuffled permutation times — the shuffle and the recount run in a Numba-compiled kernel — and each observed count is turned into a z-score against that null, then into a two-sided p-value.

The reported score is not the raw count: counts are divided by the number of cells of the source type and rescaled so each row's largest value is 1, then signed by whether the pair was observed more or less often than expected. So a score near +1 means strong attraction, near -1 strong avoidance.

The result written to uns[label] is a long table with columns phenotype, neighbour_phenotype, one score column per image, and one pvalue_<image> column per image. Plot it with sp.pl.spatialCooccurrence or sp.pl.spatialInteractionNetwork.

Parameters:

Name Type Description Default
data (AnnData | SpatialData | str, required)

The cell table. An AnnData, a path to an .h5ad file, a SpatialData object, or a path to a .zarr SpatialData store.

required
xCoordinate str

Column in obs holding x positions.

'X_centroid'
yCoordinate str

Column in obs holding y positions.

'Y_centroid'
zCoordinate str

Column in obs holding z positions. Leave as None for 2D data; set it and the neighbourhood search becomes three-dimensional.

None
phenotype str

Column in obs holding the cell type labels.

'phenotype'
method str

How neighbourhoods are defined. 'radius' takes every cell within radius pixels; 'knn' takes the knn nearest cells regardless of distance.

'radius'
radius float

Neighbourhood radius in the units of the coordinate columns, normally pixels. Used when method='radius'.

30
knn int

Number of nearest neighbours. Used when method='knn'.

10
permutation int

Number of label shuffles behind each p-value. 1000 is a reasonable default; drop it to 100 while exploring, since runtime is linear in it.

1000
imageId str

Column in obs holding image identifiers. Each image is tested separately.

'imageid'
subset str

Process only this image.

None
label str

Key in uns the result table is written to.

'spatialCooccurrence'
maxWorkers int

Workers for the permutation loop, passed to joblib.Parallel. The default -1 uses every core.

-1
verbose bool

Print progress messages.

True
outputDir str

Directory to write the updated object to. With None the object is returned instead.

None
streamData bool

Run out of core against an .h5ad path with CAP-AnnData, reading only the sections this function needs and writing back only what it changes. Requires data to be a path; the file is updated in place and None is returned.

False
sdataTable str

Which SpatialData table to work on. Ignored for AnnData input, and optional when the store has exactly one table.

None

Returns:

Name Type Description
adata AnnData | SpatialData | None

The updated object when outputDir is None. None in streaming mode and when outputDir is given, where the result is written to disk.

Example
adata = sp.tl.spatialCooccurrence(
    adata, phenotype="phenotype", method="radius", radius=30, permutation=1000
)
sp.pl.spatialCooccurrence(adata)

# Nearest-neighbour definition instead of a fixed radius.
adata = sp.tl.spatialCooccurrence(adata, method="knn", knn=10)

# Only significant pairs, as a network.
sp.pl.spatialInteractionNetwork(adata, pVal=0.01)