omics.co.in logo omics.co.in

Chapter 9: Cell Type Annotation (SingleR/CellDex), Differential Expression & RCTD Deconvolution

Tested Stacks: GATK 4.6.1 Samtools 1.21 Nextflow 24.10 Seurat v5.1 Python 3.12
Prerequisites: Basic Linux CLI & Sequencing Formats
Day 4 • Annotation & Deconvolution Track 21 • 10 Modular Chapters Visium HD • Seurat v5 • Space Ranger

Chapter 9: Cell Type Annotation (SingleR/CellDex), Differential Expression & RCTD Deconvolution

Comparing marker-based, reference-based (SingleR), and label transfer annotations; assessing delta scores and pruned labels; differential expression with FindAllMarkers; cell type deconvolution in Visium HD using RCTD.

⏱️ Estimated Time: 55 min 💻 Environment: R 4.4+ • Seurat v5 • Space Ranger 3.0+ 📁 Dataset: 10x Genomics Visium HD Colorectal Cancer (FFPE)

Key Learning Deliverables & Competencies

  • Compare three cell annotation strategies: marker curation, automated SingleR reference mapping, and label transfer.
  • Evaluate SingleR annotation confidence using delta scores and pruned label filters.
  • Perform differential expression testing with FindAllMarkers() and apply stringent statistical filters.
  • Implement RCTD (Robust Cell Type Decomposition) to deconvolve multi-cellular spatial bins.

1. Automated Annotation with SingleR & CellDex

Rather than relying solely on manual marker curation, SingleR maps spatial bin transcriptomes against curated reference atlases (e.g., HumanPrimaryCellAtlasData and BlueprintEncodeData):

library(SingleR)
library(celldex)

# Load Curated Human Primary Cell Reference
hpca_ref <- HumanPrimaryCellAtlasData()

# Extract Expression Matrix from Sketched Assay
expr_matrix <- GetAssayData(seurat_obj, assay = "sketch", layer = "data")

# Run Automated SingleR Annotation
pred_results <- SingleR(
    test = expr_matrix,
    ref = hpca_ref,
    labels = hpca_ref$label.main
)

# Inspect Assignment Confidence & Pruned Labels
table(pred_results$pruned.labels)

# Transfer Labels to Seurat Metadata
seurat_obj$SingleR_label <- pred_results$pruned.labels[colnames(seurat_obj)]

2. Cell Type Deconvolution with RCTD

While Visium HD's 8 µm bins are roughly the size of a single cell body, bins positioned along histological interfaces often capture a mixture of cell types (e.g., a tumor epithelial cell touching a CD8+ cytotoxic T lymphocyte and a cancer-associated fibroblast).

RCTD (Robust Cell Type Decomposition) solves this via a constrained Poisson generalized linear model that estimates the exact fractional proportions of individual cell types within each spatial bin:

library(spacexr)

# 1. Create SpatialRNA Object
coords <- GetTissueCoordinates(seurat_obj)
spatial_counts <- GetAssayData(seurat_obj, assay = "Spatial.008um", layer = "counts")
puck <- SpatialRNA(coords = coords, counts = spatial_counts)

# 2. Load Matched scRNA-Seq Reference Object
# ref_sc <- Reference(counts = ref_counts, cell_types = ref_labels)

# 3. Execute RCTD in Full or Doublet Mode
myRCTD <- create.RCTD(puck, ref_sc, max_cores = 8)
myRCTD <- run.RCTD(myRCTD, doublet_mode = "doublet")

# Extract Deconvolution Weights
weights <- get_deconvoluted_weights(myRCTD)
head(weights)

⚠️ 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's SketchData() 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 chr1 or 1; divergent naming causes silent alignment drops.
Was this guide helpful to your research?
Help us maintain 100% accurate, peer-reviewed bioinformatics standards.
📝 Propose Edit on GitHub ↗