6. Spatial Analysis#
Pipeline phase: Phase 5 — Downstream Biology
What you will learn:
Compute co-localization scores (
truncated_similarity,pearson_correlation)Run Moran’s I spatial autocorrelation per library
Run neighborhood enrichment analysis
Generate a multipage spatial PDF with signature overlays
Prerequisites: adata.normalized.scored.p35.h5ad (Phase 3.5b checkpoint)
import numpy as np
import pandas as pd
import anndata as ad
import sc_tools.tl as tl
import sc_tools.pl as pl
from sc_tools.tl.colocalization import (
truncated_similarity,
pearson_correlation,
morans_i_batch,
neighborhood_enrichment_batch,
)
Synthetic spatial AnnData with signature scores#
np.random.seed(42)
n_spots, n_genes = 400, 100
# Spatial grid
row, col = np.divmod(np.arange(n_spots), 20)
spatial = np.column_stack([col * 100.0, row * 100.0])
gene_names = [f"GENE_{i}" for i in range(n_genes)]
X = np.random.rand(n_spots, n_genes).astype(np.float32)
adata = ad.AnnData(X=X, obsm={"spatial": spatial})
adata.var_names = gene_names
adata.obs["library_id"] = pd.Categorical([f"lib_{i % 2}" for i in range(n_spots)])
adata.obs["leiden"] = pd.Categorical([str(i % 5) for i in range(n_spots)])
# Simulate signature scores in obsm (as produced by score_signature)
sig_cols = ["Hallmark/HYPOXIA", "Hallmark/MYC_TARGETS_V1", "Myeloid/Macrophage_Core"]
score_data = np.random.randn(n_spots, len(sig_cols)).astype(np.float32)
# Make HYPOXIA and Macrophage positively correlated in one region
score_data[:100, 0] += 1.5
score_data[:100, 2] += 1.2
adata.obsm["signature_score"] = pd.DataFrame(score_data, index=adata.obs_names, columns=sig_cols)
adata.obsm["signature_score_z"] = adata.obsm["signature_score"].apply(lambda c: (c - c.mean()) / c.std())
print(adata)
Co-localization: truncated similarity#
truncated_similarity computes score_a * score_b where both are positive,
else 0. This highlights spots where two programs are jointly active.
hypoxia_scores = adata.obsm["signature_score"]["Hallmark/HYPOXIA"].values
macro_scores = adata.obsm["signature_score"]["Myeloid/Macrophage_Core"].values
coloc = truncated_similarity(hypoxia_scores, macro_scores)
print(f"Co-localization score: mean={coloc.mean():.3f}, max={coloc.max():.3f}")
print(f"Fraction of spots with joint signal: {(coloc > 0).mean():.2%}")
Co-localization: Pearson correlation#
from sc_tools.tl.colocalization import pearson_correlation
corr_df = pearson_correlation(
adata,
sig_a="Hallmark/HYPOXIA",
sig_b="Myeloid/Macrophage_Core",
groupby="library_id",
)
print(corr_df)
Moran’s I spatial autocorrelation (per library)#
morans_i_batch runs Moran’s I for each signature column separately per library.
Requires squidpy.
# In a real run (squidpy must be installed):
# morans_results = morans_i_batch(
# adata,
# keys=sig_cols,
# library_key="library_id",
# n_perms=100,
# )
# print(morans_results)
print("morans_i_batch returns a DataFrame with columns: key, library_id, I, pval, fdr")
Neighborhood enrichment#
neighborhood_enrichment_batch tests whether cell types co-occur in spatial
neighborhoods more than expected by chance (squidpy gr.nhood_enrichment wrapper).
# In a real run:
# nhood_df = neighborhood_enrichment_batch(
# adata,
# cluster_key="leiden",
# library_key="library_id",
# )
# print(nhood_df)
print("neighborhood_enrichment_batch returns a long-format DataFrame:")
print(" columns: library_id, celltype_A, celltype_B, zscore, pval, fdr")
Multipage spatial PDF#
multipage_spatial_pdf generates a PDF with one page per signature per library,
overlaid on the tissue slide.
import tempfile, os
with tempfile.TemporaryDirectory() as tmpdir:
pdf_path = os.path.join(tmpdir, "spatial_signatures.pdf")
pl.spatial.multipage_spatial_pdf(
adata,
keys=sig_cols,
library_key="library_id",
output_path=pdf_path,
spot_size=50,
)
print(f"PDF written: {os.path.getsize(pdf_path)} bytes")
Next steps#
For a real project, Phase 5 scripts live under projects/<platform>/<project>/scripts/.
Example:
# Run spatial multipage colocalization plot for ggo_visium
make -C projects/visium/ggo_visium spatial-multipage-colocalization
Publication figures are saved to projects/<platform>/<project>/figures/manuscript/.