peach.tl.spatial#

Spatial archetype analysis functions.

Analyze spatial co-localization and neighborhood enrichment of archetypal patterns using squidpy. Requires spatial transcriptomics data with tissue coordinates in adata.obsm['spatial'] and archetype assignments in adata.obs['archetypes'].

Main Functions: - spatial_neighbors(): Build spatial connectivity graph - archetype_nhood_enrichment(): Test archetype co-localization via permutation - archetype_co_occurrence(): Distance-dependent archetype co-occurrence - archetype_spatial_autocorr(): Moran’s I / Geary’s C per archetype weight - archetype_interaction_boundaries(): Detect cross-cell-type gradient fronts

Requires: pip install peach[spatial] (squidpy >= 1.3.0)

Functions

archetype_co_occurrence(adata, *[, ...])

Compute distance-dependent co-occurrence of archetype groups.

archetype_interaction_boundaries(adata, *[, ...])

Detect spatial fronts where archetype weight mixtures diverge between cell types.

archetype_nhood_enrichment(adata, *[, ...])

Test spatial neighborhood enrichment between archetype groups.

archetype_spatial_autocorr(adata, *[, ...])

Compute spatial autocorrelation (Moran's I or Geary's C) per archetype weight.

spatial_neighbors(adata, *[, spatial_key, ...])

Build spatial neighbor graph from tissue coordinates.

peach.tl.spatial.spatial_neighbors(adata, *, spatial_key='spatial', n_neighs=30, coord_type='generic', **kwargs)[source]#

Build spatial neighbor graph from tissue coordinates.

Wrapper around squidpy.gr.spatial_neighbors() with PEACH-appropriate defaults for bead-based and imaging-based spatial transcriptomics.

Parameters:
  • adata (AnnData) – Annotated data with spatial coordinates in adata.obsm[spatial_key].

  • spatial_key (str, default: "spatial") – Key in adata.obsm containing 2D spatial coordinates.

  • n_neighs (int, default: 30) – Number of nearest neighbors for the spatial graph.

  • coord_type (str, default: "generic") – Coordinate type. Use “generic” for Slide-seq/MERFISH (continuous coords) or “grid” for Visium (hexagonal grid). See squidpy docs for details.

  • **kwargs (Any) – Additional arguments passed to squidpy.gr.spatial_neighbors().

Returns:

Modifies adata in place:

  • adata.obsp['spatial_connectivities']: sparse connectivity matrix

  • adata.obsp['spatial_distances']: sparse distance matrix

Return type:

None

peach.tl.spatial.archetype_nhood_enrichment(adata, *, cluster_key='archetypes', n_perms=1000, seed=42, **kwargs)[source]#

Test spatial neighborhood enrichment between archetype groups.

For each pair of archetypes, tests whether cells of one archetype are found more or less frequently in the spatial neighborhood of the other archetype than expected by chance (permutation test).

Parameters:
  • adata (AnnData) – Annotated data with spatial graph (run spatial_neighbors first) and archetype assignments in adata.obs[cluster_key].

  • cluster_key (str, default: "archetypes") – Column in adata.obs with archetype labels.

  • n_perms (int, default: 1000) – Number of permutations for significance testing.

  • seed (int, default: 42) – Random seed for permutation reproducibility.

  • **kwargs (Any) – Additional arguments passed to squidpy.gr.nhood_enrichment().

Returns:

Dictionary with ‘zscore’ and ‘count’ arrays [n_archetypes x n_archetypes]. Also stored in adata.uns['archetype_nhood_enrichment'].

Return type:

dict

Examples

>>> pc.tl.spatial_neighbors(adata)
>>> result = pc.tl.archetype_nhood_enrichment(adata)
>>> print(result['zscore'])  # positive = enriched, negative = depleted
peach.tl.spatial.archetype_co_occurrence(adata, *, cluster_key='archetypes', spatial_key='spatial', interval=50, **kwargs)[source]#

Compute distance-dependent co-occurrence of archetype groups.

Measures how the co-occurrence ratio between archetype pairs varies with spatial distance. Useful for identifying distance-dependent spatial relationships (e.g., archetypes that co-occur at short but not long distances).

Parameters:
  • adata (AnnData) – Annotated data with spatial coordinates and archetype assignments.

  • cluster_key (str, default: "archetypes") – Column in adata.obs with archetype labels.

  • spatial_key (str, default: "spatial") – Key in adata.obsm with spatial coordinates.

  • interval (int, default: 50) – Number of distance intervals to evaluate.

  • **kwargs (Any) – Additional arguments passed to squidpy.gr.co_occurrence().

Returns:

Dictionary with ‘occ’ (co-occurrence ratios) and ‘interval’ (distance bins). Also stored in adata.uns['archetype_co_occurrence'].

Return type:

dict

Examples

>>> pc.tl.spatial_neighbors(adata)
>>> result = pc.tl.archetype_co_occurrence(adata)
>>> print(result['occ'].shape)  # [n_archetypes, n_archetypes, n_intervals]
peach.tl.spatial.archetype_spatial_autocorr(adata, *, weights_key='cell_archetype_weights', mode='moran', n_perms=100, n_jobs=1, **kwargs)[source]#

Compute spatial autocorrelation (Moran’s I or Geary’s C) per archetype weight.

Tests whether each archetype weight is spatially smooth (positive autocorrelation), spatially random, or spatially checkered (negative autocorrelation). Moran’s I > 0 indicates spatial clustering of that archetype; I ~ 0 indicates random distribution; I < 0 indicates dispersal.

Parameters:
  • adata (AnnData) – Annotated data with spatial graph (run spatial_neighbors first) and archetype weights in adata.obsm[weights_key].

  • weights_key (str, default: "archetype_weights") – Key in adata.obsm with archetype weight matrix [n_cells, n_archetypes].

  • mode (str, default: "moran") – Autocorrelation statistic: “moran” (Moran’s I) or “geary” (Geary’s C).

  • n_perms (int, default: 100) – Number of permutations for p-value estimation. Set to None for analytical p-values only.

  • n_jobs (int, default: 1) – Number of parallel jobs. Default 1 for macOS compatibility.

  • **kwargs (Any) – Additional arguments passed to squidpy.gr.spatial_autocorr().

Returns:

DataFrame with autocorrelation statistics per archetype weight. Also stored in adata.uns['archetype_spatial_autocorr'].

Return type:

pandas.DataFrame

Examples

>>> pc.tl.spatial_neighbors(adata)
>>> autocorr = pc.tl.archetype_spatial_autocorr(adata)
>>> print(autocorr)  # Moran's I per archetype
peach.tl.spatial.archetype_interaction_boundaries(adata, *, cell_type_col='Cell_Type', weights_key='cell_archetype_weights', cell_type_a=None, cell_type_b=None)[source]#

Detect spatial fronts where archetype weight mixtures diverge between cell types.

Uses the existing spatial neighbor graph (from pc.tl.spatial_neighbors()) and continuous archetype weights (from pc.tl.extract_archetype_weights()) to identify tissue regions where two cell types run different archetype programs in the same neighborhood.

For each cell, computes the mean archetype weight vector of its spatial neighbors that belong to cell type A and cell type B separately, then measures divergence (Jensen-Shannon) between these two distributions.

High-scoring cells sit at spatial fronts where the local archetype program of one cell type is shifting in a different direction from the other — e.g., macrophages trending toward inflammatory archetypes while neighboring fibroblasts trend toward fibrotic archetypes.

Parameters:
  • adata (AnnData) –

    Annotated data with:

    • Spatial neighbor graph in adata.obsp['spatial_connectivities'] (from pc.tl.spatial_neighbors())

    • Archetype weights in adata.obsm[weights_key] (from pc.tl.extract_archetype_weights())

    • Cell type labels in adata.obs[cell_type_col]

  • cell_type_col (str, default: "Cell_Type") – Column in adata.obs with cell type labels.

  • weights_key (str, default: "archetype_weights") – Key in adata.obsm with archetype weight matrix [n_cells, n_archetypes]. Each row sums to 1.

  • cell_type_a (str | None, default: None) – First cell type for pairwise comparison. If None, uses the two most abundant cell types.

  • cell_type_b (str | None, default: None) – Second cell type.

Returns:

Dictionary with:

  • 'boundary_scores': np.ndarray [n_cells] — per-cell JSD boundary score

  • 'mean_weights_a': np.ndarray [n_cells, n_archetypes] — mean weight vector of type-A neighbors per cell

  • 'mean_weights_b': np.ndarray [n_cells, n_archetypes] — mean weight vector of type-B neighbors per cell

  • 'cross_correlations': pd.DataFrame — per-archetype Spearman r between cell types across space

  • 'cell_type_a', 'cell_type_b': str — cell type names

  • 'n_archetypes': int — number of archetype dimensions

Also stored in adata.uns['archetype_interaction_boundaries'] and boundary scores in adata.obs['boundary_score'].

Return type:

dict

Examples

>>> pc.tl.spatial_neighbors(adata, n_neighs=30)
>>> weights = pc.tl.extract_archetype_weights(adata)
>>> result = pc.tl.archetype_interaction_boundaries(
...     adata, cell_type_col="Cell_Type",
...     cell_type_a="Myeloid", cell_type_b="Treg",
... )
>>> pc.pl.interaction_boundaries(adata)