spatial-domains
Identify tissue regions and spatial niches from preprocessed spatial transcriptomics data using Leiden, Louvain, SpaGCN, STAGATE, GraphST, BANKSY, or CellCharter.
SKILL.mdSkills/spatial/spatial-domains/SKILL.md
GitHubπΊοΈ Spatial Domains
You are Spatial Domains, a specialised OmicsClaw agent for tissue region and spatial niche identification. Your role is to partition spatial transcriptomics tissue sections into biologically meaningful domains using graph-based clustering methods that incorporate both gene expression and spatial coordinates.
Why This Exists
- Without it: Users manually configure spatial-aware clustering with inconsistent parameters across methods
- With it: One command identifies tissue domains, generates annotated maps, and produces a reproducible report
- Why OmicsClaw: Unified interface across graph clustering, deep spatial models, and neighborhood-aggregation methods with consistent reports, structured results, and reproducibility notebooks
Core Capabilities
- Leiden spatial domains: Fast graph-based clustering with spatial-weighted neighbors (default)
- Louvain clustering: Classic graph-based clustering (requires louvain package)
- SpaGCN: Spatial Graph Convolutional Network using coordinate-derived adjacency in the current OmicsClaw workflow
- STAGATE: Graph attention auto-encoder (requires PyTorch Geometric)
- GraphST: Self-supervised contrastive learning (requires PyTorch)
- BANKSY: Explicit spatial feature augmentation (interpretable)
- CellCharter: Neighborhood-aggregated GMM clustering with auto-K selection
- Standard Python gallery: recipe-driven overview, diagnostic, supporting, and uncertainty figures under
figures/ - Figure-ready data export:
figure_data/contains domain-level plotting contracts for downstream customization - Domain summary statistics: Cell counts, proportions, assignments, and neighbor-mixing summaries
- Spatial refinement: Optional KNN-based spatial smoothing of domain labels
- Optional R visualization layer: bundled
r_visualization/templates consumefigure_data/without recomputing domains - Notebook export: Auto-generated reproducibility notebook for code walkthrough and reruns
Input Formats
| Format | Extension | Required Fields | Example |
|---|---|---|---|
| AnnData (preprocessed) | .h5ad |
X (log-norm), obsm["spatial"], obsm["X_pca"], raw (counts), layers["counts"] |
preprocessed.h5ad |
| AnnData (raw, demo mode) | .h5ad |
X, obsm["spatial"] |
demo_visium.h5ad |
Unified Data Convention
After the standard spatial-preprocess pipeline, the AnnData object holds
multiple representations of the expression data. Each domain identification
method selects the appropriate layer automatically:
adata.layers["counts"] # raw integer counts (preserved before normalization)
adata.raw.X # raw counts (scanpy convention)
adata.X # log-normalized expression (normalize_total + log1p)
adata.obsm["X_pca"] # PCA embeddings (from scaled HVGs)
adata.obsp["connectivities"] # k-NN neighbor graph (from PCA)
adata.obsm["spatial"] # spatial coordinates (x, y)
adata.var["highly_variable"] # HVG annotation
Input Preprocessing Notes
Different methods consume the preprocessed.h5ad data differently. The skill
automatically selects the correct data layer for each method:
| Method | Primary input consumed | What the method actually operates on | Extra requirements |
|---|---|---|---|
| Leiden | obsp["connectivities"] (neighbor graph) |
Pre-built k-NN graph from log-normalized + PCA | Spatial coords for spatial-weighted graph |
| Louvain | obsp["connectivities"] (neighbor graph) |
Pre-built k-NN graph from log-normalized + PCA | Spatial coords optional |
| SpaGCN | X (log-normalized expression) |
Full gene matrix; internal PCA by SpaGCN | Spatial coords required; current wrapper uses coordinates only (histology=False) |
| STAGATE | X (log-normalized, HVG subset) |
Auto-filters to var["highly_variable"] before training |
Spatial coords for radius-based adjacency |
| GraphST | raw.X or layers["counts"] (raw counts) |
Internal log1p -> normalize -> scale -> HVG(3000) |
Spatial coords required |
| BANKSY | layers["counts"] or raw.X -> normalize_total |
Non-negative library-size normalized expression | Spatial coords required |
| CellCharter | obsm["X_pca"] or X (log-normalized) |
Fast neighbor aggregation over embeddings | Spatial coords for Delaunay graph |
Why raw counts for GraphST? GraphST's
preprocess()internally doeslog1p+normalize_total+scale+ HVG selection. Passing already log-normalized data would cause a double log-transform (log(log(x+1)+1)), which distorts the expression distribution. The skill automatically restoresadata.rawwhen available.
Why non-negative expression for BANKSY? BANKSY constructs neighborhood- averaged features by summing neighboring expression values. The official tutorial uses library-size normalization without log or z-score scaling. Z-score scaling (
sc.pp.scale) introduces negative values which distort the neighborhood aggregation. The skill restores raw counts and appliesnormalize_total(withoutlog1p) to produce a non-negative matrix.
Workflow
- Load: Read preprocessed h5ad; verify spatial coordinates and embeddings exist
- Preprocess (demo mode only): Normalize, log1p, PCA, neighbors if not already done
- Domain identification: Run the selected method (Leiden, Louvain, SpaGCN, STAGATE, GraphST, BANKSY, or CellCharter)
- Embed: Compute UMAP if not present for visualization
- Render the standard gallery: build the OmicsClaw narrative gallery with overview, diagnostic, supporting, and uncertainty panels
- Export figure-ready data: write
figure_data/*.csvandfigure_data/manifest.jsonfor downstream customization - Report and export: write
report.md,result.json,processed.h5ad, figures, tables, output guide, and reproducibility bundle including a notebook and optional R helper
Visualization Contract
OmicsClaw treats spatial-domains visualization as a two-layer system:
- Python standard gallery: the canonical result layer. This is the default output users should inspect first.
- R customization layer: an optional styling and publication layer that reads
figure_data/and does not recompute domain labels.
The standard gallery is declared as a recipe instead of hard-coded plotting branches. Current gallery roles include:
overview: spatial and UMAP domain mapsdiagnostic: PCA domain view and domain neighbor-mixing heatmapsupporting: domain size summaryuncertainty: local-purity spatial map and histogram
This keeps the default OmicsClaw story stable while leaving room for later method-specific visualization extensions.
CLI Reference
# Standard usage (Leiden, default)
oc run spatial-domains --input <preprocessed.h5ad> --output <report_dir>
# Specify method and parameters
oc run spatial-domains \
--input <preprocessed.h5ad> --method leiden --resolution 0.8 --spatial-weight 0.3 --output <dir>
oc run spatial-domains \
--input <preprocessed.h5ad> --method louvain --resolution 1.0 --output <dir>
oc run spatial-domains \
--input <preprocessed.h5ad> --method spagcn --n-domains 7 --output <dir>
oc run spatial-domains \
--input <preprocessed.h5ad> --method stagate --n-domains 7 --k-nn 6 --output <dir>
oc run spatial-domains \
--input <preprocessed.h5ad> --method graphst --n-domains 7 --output <dir>
oc run spatial-domains \
--input <preprocessed.h5ad> --method banksy --lambda-param 0.8 --resolution 1.0 --output <dir>
oc run spatial-domains \
--input <preprocessed.h5ad> --method cellcharter --n-domains 7 --n-layers 3 --output <dir>
oc run spatial-domains \
--input <preprocessed.h5ad> --method cellcharter --auto-k --auto-k-min 4 --auto-k-max 12 --output <dir>
# Apply spatial refinement
oc run spatial-domains \
--input <preprocessed.h5ad> --method leiden --refine --output <dir>
# Demo mode
oc run spatial-domains --demo --output /tmp/domains_demo
# Note: 'oc run' is an alias for 'python omicsclaw.py run'
python omicsclaw.py run spatial-domains --demo
Every successful standard run also writes reproducibility/analysis_notebook.ipynb
and a top-level README.md to make the output directory easier to inspect.
Algorithm / Methodology
Leiden (default)
- Input: Preprocessed AnnData with spatial coordinates (
adata.obsm["spatial"]) - Spatial weighting: Dynamically computes a localized spatial adjacency matrix and merges it with the gene expression neighbor graph without destructively overwriting
adata.obsp["connectivities"](preserves downstream UMAPs). - Clustering:
sc.tl.leiden(adjacency=adjacency, resolution=resolution) - Labels: Stored in
adata.obs["spatial_domain"]
Key parameters:
resolution: Controls granularity (default 1.0; higher = more domains)spatial_weight: Weight of spatial graph (0.0-1.0, default 0.3)
Louvain
- Input: Preprocessed AnnData with spatial coordinates (
adata.obsm["spatial"]) - Spatial weighting: Dynamically computes localized spatial adjacency (restoring feature parity with Leiden) and safely passes it via
adjacency=adjacency. - Clustering:
sc.tl.louvain(adjacency=adjacency, resolution=resolution) - Labels: Stored in
adata.obs["spatial_domain"] - Requires:
pip install louvain
Key parameters:
resolution: Controls granularity (default 1.0)spatial_weight: Weight of spatial graph (0.0-1.0, default 0.3)
SpaGCN
- Input: AnnData with spatial coordinates and log-normalized expression (following the official preprocessing logic:
normalize_per_cell+log1pbefore training) - Data layer used:
adata.X(log-normalized full gene matrix) β SpaGCN performs internal PCA - Spatial graph: Build adjacency from spatial coordinates
- GCN clustering:
SpaGCN.train()withn_domainstarget clusters - Refinement: Built-in spatial-aware label refinement
- Labels: Stored in
adata.obs["spatial_domain"]
Key parameters:
n_domains: Target number of spatial domainsspagcn_p: Spatial neighborhood contribution (default 0.5)epochs: Training epochs (default 100 in OmicsClaw CLI wrapper)- Source: Hu et al., Nature Methods 2021
Current OmicsClaw behavior: the wrapper uses
histology=False, so this execution path is coordinate-aware but not image-aware.
STAGATE
- Input: AnnData with spatial coordinates and log-normalized expression (auto-subsets to HVGs)
- HVG filtering: If
adata.var["highly_variable"]exists, only HVGs are used for the autoencoder (reduces VRAM explosion, improves convergence). - Spatial network: Builds graph preferably using scale-invariant KNN (
k_nn=6) to prevent graph fragmentation across vastly different coordinate scales (e.g. Visium vs Stereo-seq). - Graph attention: Train attention auto-encoder on PyTorch with aggressive explicit GPU garbage collection to prevent cross-run OOM leaks.
- Clustering: Gaussian Mixture Model on learned embeddings
- Labels: Stored in
adata.obs["spatial_domain"]
Key parameters:
n_domains: Target number of domainsk_nn: Nearest neighbors for spatial topology graph (default 6)rad_cutoff: Optional fixed-radius graph alternative when coordinate scale is knownstagate_alpha: Cell type-aware module weight (default 0.0)pre_resolution: Pre-clustering resolution for the cell type-aware extension- Source: Dong & Zhang, Nature Communications 2022
GraphST
- Input: AnnData with spatial coordinates (raw counts natively sourced from
adata.layers["counts"]oradata.raw) - Raw count restoration: Automatically restores safe raw counts to avoid double log-transform. (GraphST internally assumes pure counts and runs its own
log1p -> scale -> HVG). - Preprocessing:
GraphST.preprocess()+GraphST.construct_interaction() - Contrastive learning: Self-supervised GNN (with explicit
torch.cuda.empty_cache()sweeping to prevent VRAM memory locking). - Embedding: PCA on learned representations.
- Clustering: GMM (with heavily conditioned
reg_covar=1e-3to prevent ill-conditioned singular matrices) with graceful KMeans fallback. - Labels: Stored in
adata.obs["spatial_domain"]
Key parameters:
n_domains: Target number of domainsepochs: Training epochs (default 100 in OmicsClaw CLI wrapper)dim_output: Embedding dimension (default 64)refine: Optional GraphST / KNN-style post hoc smoothing- Source: Long et al., Nature Communications 2023
BANKSY
- Input: AnnData with spatial coordinates
- Non-negative normalization: Restores raw counts from
layers["counts"], strictly enforcingnormalize_totalWITHOUTlog1pto adhere to exact non-negative BANKSY augmentation rules. - HVG Subsetting: Extremely fast subsetting to HVGs before tensor calculations, yielding orders-of-magnitude reduction in RAM consumption and PCA computation time.
- Feature augmentation: Neighborhood-averaged expression + azimuthal Gabor filters.
- Smart Routing Clustering:
- If exact
n_domainsis requested: Leverages advanced tied-GMM fallback to guarantee exact cluster slicing. - If
n_domainsis NOT requested: Heuristicsc.tl.leidendiscovery mode via graph density.
- If exact
- Labels: Stored in
adata.obs["spatial_domain"]
Key parameters:
lambda_param: Spatial regularization (default 0.2)n_domains: Exact cluster quantity target (optional)resolution: Leiden resolution (default 1.0 in the OmicsClaw CLI wrapper, used ifn_domainsis omitted)num_neighbours: Neighbors for feature construction (default 15)
Note: Z-score scaling (
sc.pp.scale) is intentionally not applied, as it introduces negative values that distort BANKSY's neighborhood feature aggregation. See prabhakarlab/Banksy.
CellCharter
- Input: AnnData with spatial coordinates and pre-computed embeddings (preferably
adata.obsm["X_pca"]). - Spatial Graph: Constructs a cell-proximity network using Delaunay triangulation. Spurious long-range links are proactively removed (via 99th-percentile edge length thresholding).
- Neighborhood Aggregation: Concatenates each cell's intrinsic features with the mean-aggregated features from its 1-hop, 2-hop, ..., up to
n_layers(default 3) spatial neighbors. - Clustering:
- Fixed mode: Standard Gaussian Mixture Model (GMM) initialization.
- Auto-K mode (
--auto-k): Performs stability analysis across multiple cluster counts to identify the optimaln_domains.
- Labels: Stored in
adata.obs["spatial_domain"]
Key parameters:
n_domains: Target number of domains (default 7 in the current CLI wrapper when--auto-kis false)auto_k: Enable stability analysis for optimal cluster countauto_k_min/auto_k_max: Search range for stability-based K selectionn_layers: Number of spatial neighborhood hops to aggregate (default 3)use_rep: Feature representation to use (defaults toX_pca)- Source: Marco et al., Nature Genetics 2024
Spatial Refinement (optional)
- KNN smoothing: For each spot, find k nearest spatial neighbors
- Majority vote: Relabel if >threshold fraction of neighbors disagree
- Conservative: Only changes labels with strong spatial disagreement
Key parameters:
threshold: Disagreement threshold (default 0.5)k: Number of spatial neighbors (default 10)
Example Queries
- "Identify spatial domains in my Visium data"
- "Find tissue regions using SpaGCN"
- "Cluster my spatial transcriptomics data into niches"
- "Run spatial domain detection with 7 clusters"
Output Structure
output_dir/
βββ README.md
βββ report.md
βββ result.json
βββ processed.h5ad
βββ figures/
β βββ spatial_domains.png
β βββ umap_domains.png
β βββ pca_domains.png
β βββ domain_sizes.png
β βββ domain_neighbor_mixing.png
β βββ domain_local_purity_spatial.png
β βββ domain_local_purity_histogram.png
β βββ manifest.json
βββ figure_data/
β βββ domain_counts.csv
β βββ domain_spatial_points.csv
β βββ domain_umap_points.csv
β βββ domain_method_embedding_points.csv # if method-specific latent space exists
β βββ domain_neighbor_mixing.csv
β βββ manifest.json
βββ tables/
β βββ domain_summary.csv
β βββ domain_assignments.csv
β βββ domain_neighbor_mixing.csv
βββ reproducibility/
βββ analysis_notebook.ipynb
βββ commands.sh
βββ r_visualization.sh
Output Files Explained
README.md: Human-friendly output guide summarising the method, parameters, and where to look first.report.md: Narrative analysis report with domain counts, parameter summary, and next-step guidance.result.json: Machine-readable summary and parameter record for downstream automation.processed.h5ad: AnnData withobs["spatial_domain"]and method-specific embeddings when available.figures/: Standard Python gallery with overview, diagnostics, supporting summaries, uncertainty panels, andfigures/manifest.json.figure_data/: Figure-ready CSV exports for custom plotting in Python or R.tables/domain_summary.csv: Per-domain counts and proportions for downstream summaries.tables/domain_assignments.csv: Per-observation labels plus local purity when available.reproducibility/analysis_notebook.ipynb: Auto-generated notebook for code inspection, result loading, and reruns inside Jupyter.reproducibility/commands.sh: Minimal shell rerun command with the same core parameters.reproducibility/r_visualization.sh: Entry point for the optional R visualization layer.
Additional files such as reproducibility/requirements.txt may appear when
environment capture is enabled, but they are not guaranteed for every run.
The bundled repo-side R helpers live under:
skills/spatial/spatial-domains/r_visualization/
βββ README.md
βββ domains_publication_template.R
Dependencies
Required:
scanpy>= 1.9 β single-cell/spatial analysissquidpy>= 1.2 β spatial extensionsmatplotlibβ plottingnumpy,pandasβ numerics
Optional:
SpaGCNβ spatially-aware graph convolutional clusteringSTAGATE_pyGβ graph attention auto-encoder domains (requires PyTorch)GraphSTβ graph self-supervised contrastive learning (requires PyTorch)banksyβ spatial feature augmentationcellcharterβ neighborhood-aggregated clustering and Auto-K selectionlouvainβ Louvain clustering algorithm
Safety
- Local-first: Strict offline processing without external upload.
- Disclaimer: Reports follow the standard OmicsClaw reporting and disclaimer convention.
- Audit trail: Hyperparameters and operational flow states are logged fully.
- Non-destructive: Domain labels added as new
adata.obscolumn, original data preserved - Reproducible outputs: Standard runs now emit both shell and notebook-based rerun artifacts
Integration with Orchestrator
Trigger conditions:
- Automatically invoked dynamically based on tool metadata and user intent matching.
- Keywords β spatial domain, tissue region, niche, SpaGCN, STAGATE
Chaining partners:
spatial-preprocess: Provides the preprocessed h5ad inputspatial-de: Downstream differential expression between domainsspatial-enrichment: Gene set enrichment per domainspatial-communication: Cell-cell communication across domain boundaries
Citations
- Scanpy β analysis framework
- Leiden algorithm β community detection
- SpaGCN β Hu et al., Nature Methods 2021
- STAGATE β Dong & Zhang, Nature Communications 2022
- GraphST β Long et al., Nature Communications 2023
- BANKSY β Singhal et al., scalable spatial domain detection
- CellCharter β Marco et al., Nature Genetics 2024