UMAP and embeddings

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

Plot your Scanpy results with GenomeSpy. Scanpy computes the coordinates; GenomeSpy reads them.

The PBMC examples use supplied UMAP coordinates. The ovarian cortex example loads Expression Atlas data and computes UMAP with Scanpy. For your own data, run sc.tl.umap(adata) after your usual Scanpy preprocessing and neighbor calculation.

Download notebook

import scanpy as sc
import genome_spy as gs
import genome_spy.integrations.scanpy as gsc
pbmc = sc.datasets.pbmc68k_reduced()

Plot

Color cells by a cluster label or gene expression. Scroll over either plot to zoom both axes. Drag to pan. Hover over a cell for details.

basic = gsc.pl.umap(
    pbmc,
    color=["louvain", "CD79A"],
    size=12,
    width=240,
    height=240,
    zoom=True,
    show=False,
)
basic

Select cells

Drag a rectangle in the left plot. The same region appears in both panels, with a cell count below. Double-click in the left plot to clear it. Zoom is off in this example so dragging selects cells.

brush = gs.selection_interval("cells", encodings=["x", "y"], on="mousedown", zoom=False)
linked = gsc.pl.umap(
    pbmc,
    color=["louvain", "CD79A"],
    selection=brush,
    size=12,
    width=240,
    height=240,
    zoom=False,
    show=False,
)

Get the selected cells in Python

Run these cells in Jupyter. The web page can select and count cells; returning them to Python needs a running notebook.

view = linked.widget(parameter_names=[brush.name], inline=True, controls=False)
view

Draw a selection, then run this cell to get its cell IDs and an AnnData subset. An empty selection returns no cells.

mask = gsc.selection_mask(pbmc, view.parameter_values.get(brush.name))
selected_ids = pbmc.obs_names[mask]
selected_adata = pbmc[mask].copy()
selected_adata

Prepare ovarian cortex data

Load 36,785 cells from Expression Atlas in one line. The first download is about 240 MB. Scanpy normalizes the counts and computes UMAP below. This takes longer than the small PBMC examples. All cells are kept.

ovary = sc.datasets.ebi_expression_atlas("E-MTAB-8381")
sc.pp.normalize_total(ovary, target_sum=1e4)
sc.pp.log1p(ovary)
sc.pp.highly_variable_genes(ovary, n_top_genes=2000)
sc.pp.pca(ovary, mask_var="highly_variable", random_state=0)
sc.pp.neighbors(ovary, random_state=0)
sc.tl.umap(ovary, random_state=0)

Customize

Color VWF expression in all 36,785 ovarian cortex cells. The data uses Ensembl gene IDs. Set smaller points for the overview; they grow as you zoom. The color scale stops at the 99th percentile.

custom = gsc.pl.umap(
    ovary,
    color="ENSG00000110799",
    cmap="viridis",
    vmax="p99",
    size=2,
    frameon=False,
    title="VWF expression (36,785 cells)",
    width=400,
    height=340,
    zoom=True,
    show=False,
)
custom

Save a chart

Run this cell in Jupyter to save a self-contained HTML file. Hover and zoom work without a notebook server.

custom.save("umap.html", inline=True)

Set category colors

Choose colors by category name. The same names appear in the legend.

phase_colors = gsc.pl.umap(
    pbmc,
    color="phase",
    palette={"G1": "#bcbd22", "S": "#17becf", "G2M": "#d62728"},
    size=12,
    width=280,
    height=260,
    zoom=True,
    show=False,
)
phase_colors

Outline cells

Add outlines to separate nearby clusters. Hover and zoom work as before.

outlines = gsc.pl.umap(
    pbmc,
    color="louvain",
    add_outline=True,
    size=12,
    width=280,
    height=260,
    zoom=True,
    show=False,
)
outlines

Show the neighbor graph

Show edges from the neighbor graph already stored in the data. This call does not compute neighbors.

edges = gsc.pl.umap(
    pbmc,
    color="phase",
    edges=True,
    edges_width=0.3,
    size=10,
    width=280,
    height=260,
    zoom=True,
    show=False,
)
edges

Center a color scale

Use two colors for a stored score, with zero at the midpoint. The scores stay unchanged.

centered = gsc.pl.umap(
    pbmc,
    color="S_score",
    cmap="redblue",
    vcenter=0,
    size=12,
    width=280,
    height=260,
    zoom=True,
    show=False,
)
centered

Plot stored PCA coordinates

Try the same plotting call with 2,638 PBMC3k cells. The dataset includes PCA coordinates; axis titles show the explained variance.

pbmc3k = sc.datasets.pbmc3k_processed()
pca = gsc.pl.pca(
    pbmc3k,
    color=["louvain", "CD79A"],
    annotate_var_explained=True,
    size=12,
    width=200,
    height=240,
    zoom=True,
    show=False,
)
pca

Scatter cell annotations

Compare counts and detected genes using existing cell annotations. Color shows the mitochondrial percentage.

cell_scatter = gsc.pl.scatter(
    pbmc,
    x="n_counts",
    y="n_genes",
    color="percent_mito",
    size=12,
    width=320,
    height=260,
    zoom=True,
    show=False,
)
cell_scatter

Scatter gene annotations

Plot stored gene statistics instead of cells. Hover for the gene name and its values.

gene_scatter = gsc.pl.scatter(
    pbmc,
    x="means",
    y="dispersions",
    color="dispersions_norm",
    use_raw=False,
    size=12,
    width=320,
    height=260,
    zoom=True,
    show=False,
)
gene_scatter

Prepare embedding density

Compute density with Scanpy using the stored UMAP coordinates. This does not recalculate UMAP.

sc.tl.embedding_density(pbmc, basis="umap", groupby="phase")

Plot embedding density

Show S-phase cells by their density, with other cells in gray. Scroll to zoom and hover for cell details.

density = gsc.pl.embedding_density(
    pbmc,
    basis="umap",
    groupby="phase",
    group="S",
    fg_dotsize=18,
    bg_dotsize=5,
    width=280,
    height=260,
    zoom=True,
    show=False,
)
density

Plot t-SNE

Use the saved t-SNE coordinates from the same PBMC3k dataset. Scroll to zoom, drag to pan and hover for cell details.

tsne = gsc.pl.tsne(
    pbmc3k,
    color="louvain",
    size=12,
    width=320,
    height=280,
    zoom=True,
    show=False,
)
tsne

Prepare a diffusion map

Use the PBMC68k subset’s stored neighbor graph. Scanpy computes the diffusion coordinates once.

sc.tl.diffmap(pbmc, random_state=0)

Plot diffusion components

Show CD79A expression on diffusion components 2 and 3. Scroll to zoom both axes, drag to pan and hover for cell details.

diffusion = gsc.pl.diffmap(
    pbmc,
    color="CD79A",
    components="2,3",
    cmap="viridis",
    size=12,
    width=320,
    height=280,
    zoom=True,
    show=False,
)
diffusion

Compare genes and cell details

Show seven genes, counts and cell labels in a grid. The panels are square. Scroll to zoom, drag to pan and hover for cell details.

color_vars = [
    "CD79A",
    "MS4A1",
    "IGJ",
    "CD3D",
    "FCER1A",
    "FCGR3A",
    "LYZ",
    "n_counts",
    "bulk_labels",
]
panels = [
    gsc.pl.umap(
        pbmc,
        color=field,
        size=12,
        frameon=False,
        vmax="p99",
        width=140,
        height=140,
        legend_fontsize=8,
        zoom=True,
        show=False,
    )
    for field in color_vars
]
panels[-1] = panels[-1].configure_legend(labelFontSize=8, rowPadding=1, symbolSize=36)
umap_grid = gs.concat(*panels, columns=3, spacing=8).resolve_scale(
    x="shared", y="shared", color="independent", size="independent"
)
umap_grid

Data use and provenance

These examples use Scanpy’s processed PBMC68k subset (700 cells) and PBMC3k (2,638 cells). Credit 10x Genomics and Scanpy’s preprocessing contributors (CC BY 4.0). Supplied coordinates and annotations are kept. Scanpy computes density and diffusion coordinates explicitly above.

The ovarian cortex data is E-MTAB-8381, from Wagner et al. (2020). Credit the authors and EMBL-EBI Single Cell Expression Atlas (terms of use). The example keeps all 36,785 Atlas cells, normalizes/log-transforms counts and computes PCA, neighbors and UMAP with Scanpy. It illustrates plotting; it does not reproduce the paper’s analysis.