Lecture 14 — Trajectory Inference & Cell–Cell Communication

Bill Cresko

Lecture 14: Trajectory Inference & Cell–Cell Communication

Where this lecture fits

Goals of this lecture

  • See when continuous structure (a trajectory) is the right model instead of discrete clusters
  • Understand pseudotime, and how Slingshot / Monocle3 / PAGA order cells
  • Understand RNA velocity — how nascent vs. mature mRNA adds direction to a trajectory
  • Understand cell–cell communication inference (ligand–receptor) with CellChat / CellPhoneDB / LIANA
  • Know the failure modes of both — these are the most over-interpreted analyses in the field

Note

Both analyses sit on the annotated, integrated object from the core workshop. They answer “how do cells move through states?” (trajectory) and “which cell types talk to which?” (communication) — questions clustering alone cannot.

Part 1 — Trajectory inference & pseudotime

When clusters are the wrong model

  • Clustering imposes discrete labels. But differentiation, activation, and cell-cycle are continuous processes — cells form a continuum, not islands.
  • A trajectory models cells as lying along one or more paths; pseudotime is a cell’s position along that path (a number, not real clock time).
  • Use it when you have reason to expect a process: development, a stimulation time-course, a maturation axis.

Warning

Trajectory inference will always return a trajectory — even on noise. The method does not check whether a continuum exists. If your biology is genuinely discrete (e.g. resting PBMC subsets), a pseudotime axis is meaningless. Decide a priori whether a continuum is plausible.

Pseudotime — the core idea

  • Build a graph (or tree) on cells in a reduced space, pick a root, and measure distance along the graph
  • Genes that change smoothly along pseudotime are the drivers of the process
Tool Idea Notes
Slingshot smooth principal curves through clusters robust, R/Bioconductor, needs a start cluster
Monocle3 learns a principal graph; supports branches popular; learn_graph() + order_cells()
PAGA (scanpy) abstracted graph of cluster connectivity great for “is there even a continuum?”
Diffusion pseudotime random-walk distance from a root underlies several Python tools
library(slingshot)
sce <- slingshot(sce, clusterLabels = "celltype", reducedDim = "UMAP",
                 start.clus = "progenitor")
slingPseudotime(sce) |> head()

Important

You must choose the root. Pseudotime has no inherent direction — the algorithm orders cells, but you decide which end is “start” (usually from a known progenitor marker). Get the root wrong and the whole story reverses.

Note

Two practical gotchas. Monocle 3’s order_cells() is interactive by default (it pops up a GUI to pick the root) — in a batch/HPC script you must pass the root programmatically (root_pr_nodes= / root_cells=). And to find genes that change along a trajectory, use a dedicated test like tradeSeq (GAM-based, branch-aware) rather than a plain two-group FindMarkers.

RNA velocity — adding direction

RNA velocity uses the ratio of unspliced (nascent) to spliced (mature) mRNA to predict each cell’s near-future state; arrows on the embedding show the inferred direction of motion (recreated schematic).

  • Pseudotime gives an axis but not a direction; RNA velocity supplies the arrow
  • Reads are split into unspliced (intron-containing, newly transcribed) and spliced (mature) counts per gene
  • A high unspliced/spliced ratio ⇒ the gene is being induced ⇒ the cell is heading toward a state with more of that transcript

Note

Recreated in our style. Original concept & movies: La Manno et al. 2018, Nature (velocyto.org); modern dynamical model: Bergen et al. 2020, Nat Biotechnol (scVelo, scvelo.org).

RNA velocity — code & cautions

import scvelo as scv
scv.pp.filter_and_normalize(adata, min_shared_counts=20, n_top_genes=2000)
scv.pp.moments(adata, n_pcs=30, n_neighbors=30)
scv.tl.velocity(adata, mode="dynamical")
scv.tl.velocity_graph(adata)
scv.pl.velocity_embedding_stream(adata, basis="umap")

Warning

Velocity needs a spliced/unspliced matrix — the standard Cell Ranger filtered_feature_bc_matrix does not contain this. Generate it with velocyto run or kb count --workflow lamanno before running scVelo. If only the filtered matrix is available, velocity cannot be run — the most common reason velocity returns flat arrows.

Warning

Velocity assumptions break quietly. Assumes near-steady-state kinetics; unreliable when capture is shallow or the process is fast. Treat the arrows as a hypothesis, not a measurement.

CytoTRACE — ordering by gene-count breadth

  • A simpler, assumption-light alternative: less-differentiated cells tend to express more genes (broader transcriptional state)
  • CytoTRACE (Gulati et al. 2020, Science) ranks cells by the number of detected genes (and co-expression structure) as a proxy for differentiation potential
  • Useful sanity check on a velocity/pseudotime root: do the two methods agree on which end is “start”?

Tip

Triangulate. When Slingshot, RNA velocity, and CytoTRACE agree on the ordering and root, you can believe it. When they disagree, you’ve learned the trajectory is fragile — report that, don’t pick the prettiest one.

Part 2 — Cell–cell communication

The question, and the trick

  • Cells coordinate via secreted/membrane ligands binding receptors on other cells
  • We can’t observe binding from scRNA-seq — but we can ask: is the ligand expressed in cluster A and its receptor expressed in cluster B?
  • Curated ligand–receptor databases + per-cluster expression → a predicted signaling network

Ligand–receptor inference scores expressed L–R pairs between every cluster pair, with significance from a permutation null; results aggregate into a directed signaling network (recreated schematic).

Methods & how they differ

Tool Ecosystem Distinctive feature
CellPhoneDB Python permutation test; handles multi-subunit complexes
CellChat R signaling pathways + nice circle/chord visualizations
NicheNet R links ligands to downstream target genes in the receiver
LIANA R/Py consensus across many methods/databases
library(CellChat)
cc <- createCellChat(object = seu, group.by = "celltype")
cc@DB <- CellChatDB.human
cc <- subsetData(cc) |> identifyOverExpressedGenes() |>
  identifyOverExpressedInteractions() |> computeCommunProb() |>
  aggregateNet()
netVisual_circle(cc@net$weight, weight.scale = TRUE)

Note

Recreated in our style. Original methods/figures: Jin et al. 2021, Nat Commun (CellChat, cellchat.org); Efremova et al. 2020, Nat Protoc (CellPhoneDB).

Reading communication results responsibly

Warning

Co-expression is not interaction. These tools report that a ligand and receptor are expressed in the right places — not that signaling occurs. Pitfalls:

  • No spatial constraint — sender and receiver may never be adjacent (pair with spatial data, Lec 16)
  • Database bias — curated for human/mouse; sparse for non-model systems
  • Secretion/diffusion ignored — mRNA ≠ protein ≠ active ligand
  • Always validate top hits (IHC, perturbation, spatial co-localization) before claiming a circuit

ifnb is a demo, not a model system for trajectories

Note

The tutorial uses ifnb (resting + IFN-β-stimulated PBMCs) as a mechanics demo — not biology. PBMCs are not a developmental continuum. A pseudotime on ifnb shows you how to run the tools; interpreting it as a real differentiation axis would be wrong. On real data (development, maturation, a time-course), you would:

  1. Check a priori whether a continuum is plausible
  2. Pick the root from independent evidence (progenitor markers, CytoTRACE, RNA velocity)
  3. Triangulate at least two methods before reporting a trajectory

Part 3 — A note on long reads

Single-cell isoforms need long reads

  • Standard 3′ short-read scRNA-seq counts genes, not isoforms — it can’t see which splice variant a cell uses
  • Pairing single-cell barcoding with long-read sequencing (PacBio Iso-Seq, ONT) recovers full-length, isoform-resolved transcripts per cell (e.g. scISO-seq)
  • Ties back to the 3′ UTR annotation problem from Lec 00: long reads both improve annotations and enable per-cell isoform analysis — especially valuable in non-model systems

Recap & what’s next

What to remember from Lecture 14

  • Trajectory/pseudotime models cells as a continuum — only valid when a continuum actually exists, and you must set the root
  • RNA velocity adds direction from unspliced/spliced ratios; CytoTRACE gives an assumption-light cross-check
  • Cell–cell communication infers ligand–receptor signaling from co-expression — a hypothesis generator, not proof of interaction
  • Both are heavily over-interpreted: triangulate methods and validate before you believe the picture

Coming up next

Further reading

  • Saelens et al. 2019, Nat Biotechnol — benchmark of 45 trajectory methods (a reality check)
  • La Manno et al. 2018 (velocyto.org); Bergen et al. 2020 (scVelo)
  • Gulati et al. 2020 — CytoTRACE
  • Jin et al. 2021 — CellChat; Armingol et al. 2021, Nat Rev Genet — review of cell–cell communication inference