Chapter 11: Cell-Cell Communication & Ligand-Receptor Networks
Chapter 11: Cell-Cell Communication & Ligand-Receptor Networks
No cell operates in biological isolation. Tissues, organs, and tumors are coordinated by intercellular signaling networks where sender cells secrete ligand proteins that bind to cognate cell-surface receptors on target cells, activating downstream signaling pathways.
By mapping single-cell expression profiles against curated databases of experimentally validated ligand-receptor interactions (e.g. VEGFA \( ightarrow\) FLT1, PDCD1 \( ightarrow\) CD274, CXCL12 \( ightarrow\) CXCR4), computational algorithms infer active communication channels between distinct cell populations.
1. Intercellular Communication with CellChat in R
CellChat models communication probability using the law of mass action, incorporating multimeric ligand-receptor complexes (e.g. TGF-\(eta\) heterotetramers) along with soluble cofactors and inhibitors.
library(CellChat)
library(patchwork)
# Create CellChat object from Seurat
cellchat <- createCellChat(object = pbmc, group.by = "cell_type", assay = "RNA")
# Load CellChatDB (Human or Mouse)
CellChatDB <- CellChatDB.human
# Filter to specific interaction categories (Secreted Signaling, ECM-Receptor, Cell-Cell Contact)
cellchat@DB <- CellChatDB
# Preprocess expression data and identify overexpressed signaling genes
cellchat <- subsetData(cellchat)
cellchat <- identifyOverExpressedGenes(cellchat)
cellchat <- identifyOverExpressedInteractions(cellchat)
# Calculate communication probabilities using mass action modeling
cellchat <- computeCommunProb(cellchat, raw.use = TRUE)
cellchat <- filterCommunication(cellchat, min.cells = 10)
cellchat <- computeCommunProbPathway(cellchat)
cellchat <- aggregateNet(cellchat)2. Visualizing Signaling Cross-Talk
# 1. Circle plot: Aggregate number of interactions between cell types
par(mfrow = c(1,2))
netVisual_circle(cellchat@net$count, vertex.weight = groupSize, weight.scale = T, label.edge= F, title.name = "Number of interactions")
netVisual_circle(cellchat@net$weight, vertex.weight = groupSize, weight.scale = T, label.edge= F, title.name = "Interaction weights/strength")
# 2. Hierarchy and Circle plot for specific pathways (e.g. VEGF or CXCL)
pathways.show <- c("CXCL")
netVisual_aggregate(cellchat, signaling = pathways.show, layout = "circle")
# 3. Bubble plot showing specific ligand-receptor pairs
netVisual_bubble(cellchat, sources.use = c("Monocytes"), targets.use = c("CD4 T cells", "CD8 T cells"), remove.isolate = FALSE)3. CellPhoneDB Permutation Testing in Python
CellPhoneDB calculates the mean expression of ligands and receptors across interacting cell pairs and assesses statistical significance using 1,000 empirical label permutations.
# Run CellPhoneDB statistical analysis from terminal
cellphonedb method statistical_analysis \
meta_table.tsv \
counts_normalized.tsv \
--counts-data=gene_name \
--threads=16 \
--output-path=./cellphonedb_results/
# Outputs:
# ├── pvalues.txt -> Significance of each ligand-receptor pair
# ├── means.txt -> Mean expression level of interactions
# └── significant_means.txt -> Filtered significant interactionsCommon 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.