Linked expression summaries

Select cells in a UMAP to compare their gene expression with all cells. Drag a box to select. Double-click to clear. The other plots update as you drag.

The count appears inside the box when it fits. Set show_count=False to hide it.

Download notebook

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

pbmc = sc.datasets.pbmc68k_reduced()
genes = ["CD3D", "CD79A", "MS4A1", "NKG7", "LYZ", "FCER1A"]

Compare detected genes and marker expression

Select cells to compare their detected-gene counts and average gene expression by cell-cycle phase.

phase_qc = (
    gsc.pl.EmbeddingSummary(
        pbmc,
        genes,
        "phase",
        use_raw=False,
        obs_keys=["n_genes"],
        title="Cell-cycle phase",
        show_count=True,
    )
    .add_histogram(
        obs="n_genes",
        position="top",
        width=500,
        height=110,
        bin_width=100,
        title="Detected genes per cell",
    )
    .add_heatmap(
        ["CD3D", "NKG7", "LYZ"],
        position="right",
        width=180,
        height=160,
        cmap="viridis",
        vmin=-2.5,
        vmax=2.5,
        title="Selected marker means",
        show_values=True,
    )
    .style(umap_size=260, size=12, alpha=0.85)
    .legend(position="bottom")
    .to_chart()
)
phase_qc

Compare gene expression

Gray bars show all cells; blue bars show your selection.

marker_distribution = (
    gsc.pl.EmbeddingSummary(
        pbmc, genes, "bulk_labels", use_raw=False, title="Cell types", show_count=True
    )
    .add_histogram(
        ["LYZ", "CD3D"],
        position="left",
        width=150,
        height=75,
        bin_width=0.5,
        title=None,
    )
    .add_histogram(
        ["MS4A1", "NKG7", "FCER1A"],
        position="bottom",
        width=110,
        height=90,
        bin_width=0.5,
        title=None,
    )
    .style(umap_size=260, size=12, alpha=0.85)
    .legend(position="right")
    .to_chart()
)
marker_distribution

Change the layout and colors

Use position= to place plots around the UMAP and .legend(position=...) to move the legends. Set show_values=True to show numbers when they fit.

The seurat colors run from magenta through black at zero to yellow.

plot = (
    gsc.pl.EmbeddingSummary(
        pbmc,
        genes,
        "bulk_labels",
        use_raw=False,
        obs_keys=["phase", "S_score"],
        title="PBMC cells",
        show_count=True,
    )
    .add_heatmap(
        position="bottom",
        width=660,
        height=160,
        cmap="seurat",
        vmin=-2.5,
        vmax=2.5,
        title="Selected marker expression",
        show_values=True,
    )
    .add_histogram(
        obs="S_score", position="right", width=150, bin_width=0.1, title="S-phase score"
    )
    .add_composition(
        "phase", position="right", width=130, height=240, title="Cell-cycle phase"
    )
    .style(umap_size=280, size=12, alpha=0.85, spacing=12)
    .legend(position="bottom")
)
linked_expression = plot.to_chart()
linked_expression

Read the summaries

Histograms show percentages within all cells or within your selection. Histograms and averages skip missing values. Blank heatmap squares mean no selected values are available. Everything updates in the browser, without a running notebook.

Use Scanpy for statistical tests of expression differences.

Note

Cells exactly on the top or right edge of a selection can appear in the plots but be missing from the count and Python results.