Skip to content

spatialProximityScore

spatialProximityScore

spatialProximityScore(
    data,
    proximity,
    scoreBy="imageid",
    xCoordinate="X_centroid",
    yCoordinate="Y_centroid",
    zCoordinate=None,
    phenotype="phenotype",
    method="radius",
    radius=20,
    knn=3,
    imageId="imageid",
    subset=None,
    verbose=True,
    label="spatial_pscore",
    maxWorkers=None,
    outputDir=None,
    streamData=False,
    sdataTable=None,
)

Quantify how much of each image lies in the interaction zone between cell types.

A cell is in the interaction zone when its neighbourhood contains every phenotype listed in proximity. Two scores summarise that per image:

  • Proximity Volume — interaction-zone cells as a fraction of all cells. How much of the tissue is involved.
  • Proximity Density — interaction-zone cells as a fraction of the cells of interest only. How much of the relevant population is involved.

The two answer different questions: a sample can have a tiny volume (few Tregs overall) but a high density (nearly every Treg is touching tumour).

Cells are labelled in obs[label] with the joined proximity names or 'other', and the per-image summary goes to uns[label]. Plot it with sp.pl.spatialProximityScore.

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
proximity (list, required)

The cell types whose interaction is being scored, e.g. ["Treg", "ECAD+"]. A cell counts only when its neighbourhood contains all of them.

required
scoreBy str

Column in obs the scores are summarised over — usually the image or sample id. One row per value in the output table.

'imageid'
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'.

20
knn int

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

3
imageId str

Column in obs holding image identifiers. Neighbourhoods never cross images.

'imageid'
subset str

Process only this image.

None
label str

Key used for both obs[label] and uns[label].

'spatial_pscore'
maxWorkers int

Cap on parallel workers. Defaults to max(1, cpu_count() - 1). Lower it to cut peak memory.

None
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, with obs[label] marking interaction-zone cells and uns[label] holding the per-scoreBy scores. None in streaming mode.

Example
adata = sp.tl.spatialProximityScore(
    adata, proximity=["Treg", "ECAD+"], radius=20
)
adata.uns["spatial_pscore"]
sp.pl.spatialProximityScore(adata)

# Where are the interacting cells?
sp.pl.spatialScatterPlot(adata, colorBy="spatial_pscore", s=3)