Chapter 10: Spatial Statistics (Moran’s I, nnSVG), Niche Analysis & Quarto Reproducible Capstone
Chapter 10: Spatial Statistics (Moran’s I, nnSVG), Niche Analysis & Quarto Reproducible Capstone
Identifying Spatially Variable Genes (SVGs) via Moran’s I and nnSVG; spatial domain discovery; cellular microenvironment niche analysis (tumor core, invasive border, TLS); publication figures (300 DPI) and Quarto reproducible capstone.
Key Learning Deliverables & Competencies
- Identify Spatially Variable Genes (SVGs) utilizing Moran's I autocorrelation and
nnSVG. - Differentiate Highly Variable Genes (HVGs) from SVGs exhibiting spatial spatial dependency.
- Quantify microenvironmental cellular niches (tumor core, invasive stroma, tertiary lymphoid structures).
- Design publication-grade figures (300 DPI, viridis color scales, accessible palettes, physical scale bars).
- Assemble an end-to-end, reproducible computational analysis report in Quarto / R Markdown.
1. Spatial Statistics: Spatially Variable Genes (SVGs)
Standard transcriptomic workflows identify Highly Variable Genes (HVGs) based strictly on expression variance across cells, completely ignoring spatial coordinates. In contrast, Spatially Variable Genes (SVGs) explicitly model spatial covariance:
Moran's I Autocorrelation Statistic
$$I = rac{N}{W} rac{\sum_{i=1}^N \sum_{j=1}^N w_{ij}(x_i - ar{x})(x_j - ar{x})}{\sum_{i=1}^N (x_i - ar{x})^2}$$ Where $N$ is the number of spatial bins, $w_{ij}$ is the spatial weight matrix (e.g., inverse Euclidean distance), and $x_i$ is gene expression. An $I$ value near $+1$ indicates strong spatial clustering (focal expression gradients), while $I pprox 0$ indicates random spatial distribution.
# Calculate Spatial Variable Genes via Seurat / Moran's I
seurat_obj <- FindSpatiallyVariableFeatures(
seurat_obj,
assay = "SCT",
selection.method = "moransi",
features = VariableFeatures(seurat_obj)[1:1000],
r.metric = 5
)
# Top Spatially Variable Features
top_svgs <- head(SpatiallyVariableFeatures(seurat_obj, selection.method = "moransi"), 6)
print(top_svgs)
# Visualize Key Spatial Gradients
SpatialFeaturePlot(seurat_obj, features = top_svgs[1:4], ncol = 2)2. Cellular Niche & Neighborhood Analysis
By constructing a $k$-nearest-neighbor graph ($k = 20-30$) around each spatial bin based on cell type proportions, we define discrete microenvironmental niches:
- Tumor Core Niche: Dominated by proliferating epithelial cells, marked by hypoxic markers (HIF1A, VEGFA) and glycolytic enzymes.
- Invasive Tumor-Stroma Interface: Co-enrichment of EMT-high tumor cells and activated myofibroblastic CAFs (ACTA2, FAP, POSTN).
- Immune-Excluded Niche: Dense peritumoral collagenous barrier with cytotoxic T-cells sequestered outside the malignant parenchyma.
3. Capstone Deliverable: Reproducible Quarto Pipeline
The final capstone synthesizes all 4 workshop days into a single, automated, reproducible computational report. The workflow captures session environment metadata, exact seed numbers, and software dependencies:
---
title: "Visium HD Spatial Transcriptomics Clinical Capstone"
author: "Bioinformatics Research Fellow"
date: "November 26, 2026"
format:
html:
toc: true
toc-depth: 3
theme: cosmo
code-fold: show
code-tools: true
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)
set.seed(42)
library(renv)
library(Seurat)
library(ggplot2)
```
## Session Environment Capture
```{r session_info}
sessionInfo()
```⚠️ Common Pitfalls & Troubleshooting in Spatial Genomics
- Out-Of-Memory (OOM) Crashes on 2 µm/8 µm Grids: Never run default
FindVariableFeatures()or dense Euclidean distance matrices across raw unsketched 2 µm arrays. Always leverage Seurat v5'sSketchData()with on-disk BPCells streaming. - Tissue Detachment & Optical Misalignment: Inspect fiducial edge coordinates in Loupe Browser before downstream R processing. If tissue folds or lifts during CytAssist transfer, manually flag and filter affected spatial barcodes.
- Over-Filtering Low-Cellularity Stromal Bins: Dense desmoplastic collagen or mucinous lakes naturally possess low transcript abundance. Setting an overly aggressive $nFeature$ threshold risks completely discarding critical acellular microenvironments.
Common Pitfalls & Troubleshooting Checklist
- Java Heap Exhaustion (GATK / Picard): If processes terminate with
java.lang.OutOfMemoryError, set your environment variable explicitly:export _JAVA_OPTIONS="-Xmx16g -Djava.io.tmpdir=/tmp". - Index Timestamp Mismatch: If tools complain that a BAM index is missing or out of date, regenerate with
samtools index -@ 4 sample.bam. - Conda Channel Conflicts: Avoid ABI incompatibilities between bioconda and conda-forge by setting strict priority:
conda config --set channel_priority strict. - Chromosome Naming Contamination: Always verify whether reference FASTA headers use
chr1or1; divergent naming causes silent alignment drops.