PAGA graphs and paths

Compare connections between cell groups, then inspect expression along a supplied group order. This guide uses Scanpy’s packaged PBMC data.

Install or update with pip install --upgrade 'genome-spy-python[scanpy]'. Choose that environment as your Jupyter kernel.

Download notebook

import numpy as np
import scanpy as sc
import genome_spy.integrations.scanpy as gsc

Prepare the graph with Scanpy

Compute group connections and graph positions with Scanpy. plot=False saves the layout without drawing a plot.

pbmc = sc.datasets.pbmc68k_reduced()
sc.tl.paga(pbmc, groups="bulk_labels")
sc.pl.paga(pbmc, threshold=0.03, plot=False, random_state=0, show=False, save=False)

Plot group connections

Nodes represent cell groups; thicker edges show stronger connections. Hover for details, scroll to zoom and use the slider to hide weaker edges.

graph_options = dict(
    pos=pbmc.uns["paga"]["pos"],
    add_pos=False,
    threshold=0.03,
    fontsize=9,
    width=560,
    height=360,
    zoom=True,
    show=False,
)
network = gsc.pl.paga(pbmc, edge_slider=True, **graph_options)
network

Color nodes by gene expression

Color shows each group’s mean GNLY expression from the saved raw snapshot. Positions stay the same.

gene_network = gsc.pl.paga(pbmc, color="GNLY", **graph_options)
gene_network

Color nodes by a stored score

Use a numeric observation column to show its mean within each group.

score_network = gsc.pl.paga(pbmc, color="S_score", **graph_options)
score_network

Inspect graph degree

Color shows normalized weighted degree at the chosen edge threshold. More connected groups have higher values.

degree_network = gsc.pl.paga(pbmc, color="degree_solid", **graph_options)
degree_network

Focus on a connected component

A higher threshold separates this graph into components. Show the largest one while retaining the saved node positions.

component = gsc.pl.paga(
    pbmc,
    pos=pbmc.uns["paga"]["pos"],
    add_pos=False,
    threshold=0.2,
    single_component=True,
    fontsize=9,
    width=560,
    height=360,
    zoom=True,
    show=False,
)
component

Inspect adjacency

Show the connection matrix and its tree edges. Pass the stored matrices under the keys this Scanpy call expects; scroll to zoom.

pbmc.uns["connectivities"] = pbmc.uns["paga"]["connectivities"]
pbmc.uns["connectivities_tree"] = pbmc.uns["paga"]["connectivities_tree"]
adjacency = gsc.pl.paga_adjacency(
    pbmc,
    labels=pbmc.obs["bulk_labels"].cat.categories,
    zoom="xy",
    width=360,
    height=300,
    show=False,
)
adjacency

Inspect connections by source group

Each column is a source group. Blue points identify tree edges; hover for the target group and connection strength.

connectivity = gsc.pl.paga_adjacency(
    pbmc,
    as_heatmap=False,
    labels=pbmc.obs["bulk_labels"].cat.categories,
    zoom=True,
    width=480,
    height=280,
    show=False,
)
connectivity

Compare the graph with UMAP

View the same groups in the stored UMAP. Scroll or pan either panel to move both; labels move apart as you zoom.

comparison = gsc.pl.paga_compare(
    pbmc,
    basis="umap",
    palette="tableau10",
    legend_fontweight="normal",
    legend_loc="on data",
    show_node_labels=True,
    threshold=0.03,
    add_pos=False,
    width=280,
    height=300,
    zoom=True,
    show=False,
)
comparison

Prepare an expression path

Run diffusion pseudotime in Scanpy, starting from a CD34+ cell. Choose a group order explicitly; the plot does not infer a path.

sc.tl.diffmap(pbmc, random_state=0)
pbmc.uns["iroot"] = int(np.flatnonzero(pbmc.obs["bulk_labels"] == "CD34+")[0])
sc.tl.dpt(pbmc)
path_cells = pbmc[np.isfinite(pbmc.obs["dpt_pseudotime"])]
path_nodes = ["CD34+", "CD14+ Monocyte", "Dendritic"]
path_genes = ["LYZ", "FCER1A", "CST3", "FCGR3A", "NKG7", "CD3D"]

Show the path as a heatmap

Smooth expression over 25 ordered cells and scale each gene to 0–1. Zoom to inspect fitted values and group labels; hover for values.

path_heatmap = gsc.pl.paga_path(
    path_cells,
    nodes=path_nodes,
    keys=path_genes,
    n_avg=25,
    normalize_to_zero_one=True,
    zoom="xy",
    show_values=True,
    ruler=True,
    width=500,
    height=250,
    show=False,
)
path_heatmap

Show the same path as lines

Use the same cells, genes and smoothing. Choose a gene from the menu to emphasize its profile.

path_lines = gsc.pl.paga_path(
    path_cells,
    nodes=path_nodes,
    keys=path_genes,
    n_avg=25,
    normalize_to_zero_one=True,
    as_heatmap=False,
    zoom="xy",
    series_select=True,
    ruler=True,
    width=500,
    height=250,
    show=False,
)
path_lines

Data use and provenance

The 700-cell Scanpy PBMC subset comes from 10x Genomics PBMC68k, licensed CC BY 4.0. Credit 10x Genomics and Scanpy’s contributors. The supplied neighbor graph and UMAP are retained. Scanpy computes PAGA, graph positions and pseudotime explicitly above. The page reads prepared inputs; the notebook runs those steps in Python.