Skip to content

Viz Module API Reference

For a conceptual overview of what each widget shows and how to use it, see the Visualizations section.

Widget Classes

The Clustergram widget accepts a parquet_data argument for efficient initialization. Use Matrix.export_viz_parquet to generate this data from a clustered matrix. Passing a JSON network object is deprecated; pass matrix or parquet_data instead.

Yearbook Selection

A Yearbook renders a grid of cell "portraits". There are three ways to choose which cells it shows, in increasing order of power:

  1. An explicit id listcells=["cell_1", "cell_2", ...]. The simplest path: you already know the cells you want.
  2. A back-end selectionselection=.... Accepts a celldega.select.Selection, a JSON-ready selection dict, or a plain id list. This is the recommended way to drive the grid from a Python AnnData object, because it carries the query, sampler, scores, and provenance with the cells. See the select module docs for the full query/sampling algebra.
  3. A stateless front-end queryfront_end_query=.... Evaluated in the browser against the dataset's LandscapeFiles, so it needs only a base_url and no Python AnnData.

Passing both cells= and selection= is rejected. front_end_query= is independent of those two — when set, the browser computes the cell list itself.

Front-End Query

front_end_query is a small dict evaluated entirely in the browser. It is a deliberately narrow counterpart to the Python select module — it supports a single cluster filter and/or a single-gene ranking:

Query Behavior
{"cluster": {"attr": "leiden", "value": "8"}} Random cells from cluster 8 (capped at num_rows * num_cols * 10 by default).
{"gene": "BRCA1"} All cells ranked by BRCA1 expression, highest first.
{"cluster": {"attr": "leiden", "value": "8"}, "gene": "BRCA1"} Cells in cluster 8, ranked by BRCA1 expression.
{"gene": "BRCA1", "max_cells": 50} As above, capped at 50 cells.
yb = dega.viz.Yearbook(
    base_url="https://path-to-dataset",
    front_end_query={"gene": "BRCA1", "max_cells": 50},
    rows=2,
    cols=2,
)

Note

The former query= argument was renamed to front_end_query= to distinguish this stateless browser query from the Python-side celldega.select query module. Passing query= still works but emits a DeprecationWarning.

Module for visualization

CellCloud

Bases: _SpatialWidget

3D orbit view of cell centroids (replaces Landscape(technology="point-cloud")).

Renders a pre-built point-cloud DegaFiles directory — cell positions from cell_metadata.parquet (or cell_metadata_<alignment>.parquet when alignment is set), colored by cluster/gene. Build one with :func:celldega.align.write_alignment_point_cloud.

Parameters:

Name Type Description Default
base_url str or list

DegaFiles URL(s), as in Landscape.

required
adata AnnData

Source of cell attributes/metadata (clusters, colors, UMAP). Never used for spatial positions — those come from the DegaFiles — except when use_adata_3d_centroids is set.

required
alignment str

Named alignment variant; cell positions are read from cell_metadata_<alignment>.parquet.

required
use_adata_3d_centroids bool

When an adata with obsm["spatial"] is given, render its centroids (obs[z_key] for Z, falling back to 0) instead of the on-disk geometry — to preview a candidate alignment without rewriting DegaFiles. Default: True.

required
z_key str

obs column holding the Z coordinate for use_adata_3d_centroids. Default: "Z".

required

use_adata_3d_centroids writes centroids to a small sidecar file next to base_url and fetches it over HTTP when base_url is a local celldega.viz.get_local_server() address (millions of per-cell centroids don't fit through the widget's comm channel); otherwise it falls back to syncing them through widget state, fine for smaller datasets.

Clustergram

Bases: AnyWidget

Minimal version of the Clustergram widget.

  • Frontend still gets: matrix/parquet data, row/col names, manual_cat, manual_cat_config, etc.
  • Manual categories are treated as a simple JSON string.
  • All the old DataFrame-based manual_cat plumbing is removed.

manual_cat_dict property

Convenience accessor: parsed JSON from manual_cat.

__init__(**kwargs)

Parameters

parquet_data : dict, optional Pre-exported parquet payload from your matrix object. matrix : object, optional If provided and has .export_viz_parquet(), we'll call that. network : dict, optional Deprecated path, kept only for backwards-compatibility.

close()

Close the widget and notify the frontend to release resources.

to_cluster(axis='row', n_clusters=None, threshold=None, criterion=None)

Cut the dendrogram into flat cluster labels via the underlying Matrix.

Thin wrapper over :meth:celldega.clust.Matrix.to_cluster. When neither n_clusters nor threshold is passed, the cut is read from the front-end dendrogram slider state in dendro_cut[axis] — a dict of {"n_clusters": int} or {"threshold": float} that the JS widget writes as the user drags the slider. Passing an explicit value overrides the slider.

Parameters:

Name Type Description Default
axis str

"row" or "col" — which dendrogram to cut.

'row'
n_clusters int | None

Target number of flat clusters (overrides the slider).

None
threshold float | None

Linkage-distance cutoff (overrides the slider).

None
criterion str | None

Explicit scipy fcluster criterion.

None

Returns:

Type Description
Series

A pd.Series of cluster labels indexed by the axis names.

Raises:

Type Description
ValueError

If no Matrix is attached, or no cut is available from either the arguments or the front-end slider.

Composition

Bases: Clustergram

Composition view: count/proportion of categories compared across groups.

A Clustergram subclass with viz_mode="composition". The body draws each group (dataset/sample) as a stacked bar whose segments are populations (cell types), reusing the Clustergram's column-attribute tracks, reorder buttons (ini / sum / clust), and the control-panel PROP/COUNTS normalization toggle.

"Composition shows the count or relative proportion of categories within each group, and compares those compositions across groups."

Example::

dset = dega.DatasetCollection(adata, dataset_col="sample_id",
                               obs_columns=["condition"])
dset.calc_population(adata, category="cell_type")
dega.viz.Composition(
    dset, category="cell_type", group_attrs=["condition"]
)

Note: calc_population already copies adata.uns[f"{category}_colors"] onto the population modality it builds, so Composition picks up the same colors from dset alone — passing adata= is only needed as a fallback (e.g. a plain DataFrame input, or an AnnData/modality that has no color palette of its own).

__init__(data, modality='population', *, category=None, colors=None, adata=None, group_attrs=None, normalized=None, col_weights=None, cluster=True, name='composition', width=700, height=450, **kwargs)

Parameters:

Name Type Description Default
data Any

A Celldega collection (DatasetCollection / SetCollection), a MuData, an AnnData (obs = groups, var = populations), or a DataFrame (rows = groups, columns = populations) — typically the output of calc_population.

required
modality str

Modality key on a collection/MuData (default "population").

'population'
category str | None

Population obs column name used to resolve colors from adata.uns[f"{category}_colors"] when the modality has none.

None
colors dict[str, str] | None

Optional {population: hex} overrides.

None
adata Any

Optional source cell-level AnnData to fall back to for its color palette. Usually unnecessary: calc_population already copies the category's colors onto the modality it builds, so a DatasetCollection/SetCollection that has already run it carries its own colors.

None
group_attrs list[str] | None

Dataset/set obs columns to show as Clustergram column attribute tracks (e.g. ["condition", "timepoint"]).

None
normalized bool | None

Column-normalize each bar to 100%. Defaults to True for proportion matrices and False for count matrices.

None
col_weights dict[str, float] | None

Optional {group: n_cells} true per-group magnitude, used to scale bar height in non-normalized ("counts") mode. Defaults to DatasetCollection/calc_population's own n_cells obs column when available — pass explicitly to override, e.g. for a plain DataFrame input.

None
cluster bool

Run hierarchical clustering before display (default True).

True
name str

Clustergram registry name.

'composition'
width / height

Widget size in pixels.

required
**kwargs Any

Forwarded to :class:Clustergram.

{}

Enrich

Bases: AnyWidget

A widget for interactive enrichment analysis using the Enrichr API.

Allows users to select a gene list, choose an enrichment library, and specify the number of terms to display. Automatically replaces older widgets with the same name to prevent notebook bloat.

Landmark

Bases: AnyWidget

A widget for interactively marking corresponding landmark points across dataset slices, for procrustes/thin-plate-spline alignment.

Parameters:

Name Type Description Default
adatas AnnData | list[AnnData] | None

A single AnnData with slice_attr given, or a list of per-slice AnnData (list order is slice order) — the same two input shapes :func:~celldega.align.landmarks.calc_landmarks accepts. Must resolve to at least 2 slices; any number beyond 2 is fine — both viewports can swap to any slice in the resolved set after construction (driven by the front-end dropdowns), not just the initial pair.

None
slice_attr str | None

For a single combined AnnData, the obs column identifying each cell's slice.

None
slices Sequence[Any] | None

The initial (slice_id_a, slice_id_b) pair to show. Defaults to the first two resolved slice ids.

None
cluster_key str | None

Optional obs column to color centroids by, for visual context while marking. Purely cosmetic — has no effect on the resulting landmark table.

None
slice_labels dict[Any, str] | None

Optional {slice_id: display_name} overrides for the dropdown/panel labels. Slices not present default to str(slice_id).

None
landmarks DataFrame | None

An optional pre-existing landmark table to load — :func:~celldega.align.landmarks.calc_landmarks's output shape (columns label, x, y, and a slice-tagging column matching slice_attr), or this widget's own .landmarks from a previous session. Immediately visible on whichever of the initial pair already has points, reviewable/editable via MARK and MODIFY exactly like anything marked in this session, and safe to append new landmark sets onto (the auto-numbered label counter starts past whatever numeric labels are already present).

None
cell_radius

Cell-point radius in data-space (micron) units — the points scale with zoom, exactly like Landscape's cell layer (which defaults to 5.0), with a 1px on-screen floor. width/height/cell_radius are all plain synced traits, so this can also be set as Landmark(..., cell_radius=8.0) or afterward via lm.cell_radius = 8.0. The CELL control has a runtime opacity slider instead — radius rarely needs mid-session adjustment once set.

required
landscapes Any

Not implemented yet — planned future alternative to adatas that would point Landmark directly at two :class:~celldega.viz.widget.Landscape instances.

None

Raises:

Type Description
NotImplementedError

If landscapes is given.

ValueError

If adatas is missing, resolves to fewer than 2 slices, if a slices id isn't found among them, if a selected slice is missing obsm["spatial"], or if landmarks is missing a required column or references a slice id not among adatas.

calc_alignment_transform(**kwargs)

Fit a transform directly from the currently-marked landmarks.

Convenience wrapper over :func:~celldega.align.serial_slices.calc_alignment_transform — equivalent to calling it on :attr:landmarks directly.

close()

Close the widget and notify the frontend to release resources.

Landscape

Bases: AnyWidget

A widget for interactive visualization of spatial omics data. This widget currently supports segmented spatial transcriptomics data (Xenium, MERSCOPE, Visium HD) and H&E image data.

Parameters:

Name Type Description Default
ini_x float

The initial x-coordinate of the view.

required
ini_y float

The initial y-coordinate of the view.

required
ini_zoom float

The initial zoom level of the view.

required
rotation_orbit float

Rotating angle around orbit axis for point-cloud views.

required
rotation_x float

Rotating angle around X axis for point-cloud views.

required
token str

The token traitlet.

required
base_url str or list

The base URL(s) for the widget. Can be a single string or a list of dicts with 'url' and 'label' keys for multiple datasets. Example: [{'url': 'http://...', 'label': 'Dataset1'}, ...] You can also pass a simple list of URL strings.

required
dataset_names list

Short names for the datasets to display in the dropdown selector. Should match the length of base_urls. Example: ['Brain', 'Kidney'] for two datasets.

required
rotate float

Degrees to rotate the 2D landscape visualization.

required
AnnData AnnData

AnnData object to derive metadata from.

required
dataset_name str

The name of the dataset to visualize. This will show up in the user interface bar.

required
cell_name_prefix bool

If True, cell names in adata.obs.index are assumed to have a dataset prefix (e.g., "dataset-name_cell-name") that should be trimmed when mapping to LandscapeFiles. Default: False.

required
use_adata_3d_centroids bool

For technology="point-cloud" views given an adata, render that AnnData's obsm["spatial"]/obs[z_key] centroids instead of the geometry baked into cell_metadata.parquet — no DegaFiles rewrite needed to preview a candidate alignment. Has no effect on 2D (non point-cloud) views, which always use the on-disk x/y. Default: True.

required
z_key str

adata.obs column holding the Z coordinate used for use_adata_3d_centroids (falls back to 0 if absent). Default: "Z".

required

use_adata_3d_centroids writes centroids to a small file next to base_url and fetches it over HTTP when base_url is a local celldega.viz.get_local_server() address (millions of per-cell centroids don't fit through the widget's comm channel); otherwise it falls back to syncing them directly through the widget state, which is fine for smaller datasets.

A point-cloud (3D) view requires a real, pre-built DegaFiles base_url like any other technology — build one with the celldega.pre module (e.g. after running an alignment with :func:~celldega.align.serial_slices.align_serial_slices, regenerate LandscapeFiles from the aligned AnnData before visualizing it). adata here is only ever used for cell attributes/metadata, never for spatial positions.

The AnnData input automatically extracts cell attributes (e.g., leiden clusters), the corresponding colors (or derives them when missing), and any available UMAP coordinates.

close()

Close the widget and notify the frontend to release resources.

highlight_cells(cell_ids)

Highlight specific cells by their identifiers.

trigger_update(new_value)

Update the update_trigger traitlet with a new value.

update_cell_clusters(new_clusters)

Update cell clusters with new data.

NeighborhoodCloud

Bases: _SpatialWidget

3D orbit view of neighborhood alpha shapes (replaces Landscape(technology="neighborhood-cloud")).

Renders a pre-built neighborhood-cloud DegaFiles directory: one precomputed alpha-shape polygon per (cluster, slice), cheap to display regardless of dataset size, with real cell centroids loaded on demand when a cluster is selected. Build one with :func:celldega.align.write_nbhd_cloud (or :func:celldega.pre.write_nbhd_cloud_dataset).

The neighborhood geometry lives entirely on disk under the DegaFiles nbhd_cloud/ tree and is fetched by the front-end; this widget carries only the shared spatial trait surface plus the 3D orbit camera. (The 2D neighborhood drawing editor is a Landscape feature and intentionally not part of NeighborhoodCloud.)

Parameters:

Name Type Description Default
base_url str or list

DegaFiles URL(s), as in Landscape.

required
adata AnnData

Source of cell attributes/metadata.

required

Yearbook

Bases: AnyWidget

A widget for visualizing cell portraits in a yearbook-style grid layout.

This widget creates a grid of cell "portraits" - zoomed-in views centered on selected cells. All portraits share synchronized zoom state but display different spatial regions. The control panel works similarly to Landscape, showing gene and cell bars based on visible content.

Parameters:

Name Type Description Default
base_url str

The base URL for the dataset.

required
cells list

List of cell identifiers to display as portraits. If not provided and no query is given, random cells will be selected.

required
selection Selection or dict or list

Ordered selection of cells to display as portraits. Accepts a celldega.select.Selection returned by dega.select.Selector.select, a JSON-ready selection dict, or a plain list of cell ids. Yearbook uses its ids as the portrait cell order and stores the JSON-ready payload for provenance. Pass either selection or cells, not both.

required
front_end_query dict

Stateless query evaluated in the browser against LandscapeFiles (no Python/AnnData required). This is separate from the Python-side celldega.select query module. Supports the following formats:

  • Cluster only: {"cluster": {"attr": "leiden", "value": "8"}} Returns random cells from the specified cluster.
  • Gene only: {"gene": "BRCA1"} Returns cells ranked by gene expression (highest first).
  • Cluster + Gene: {"cluster": {"attr": "leiden", "value": "8"}, "gene": "BRCA1"} Returns cells from the cluster ranked by gene expression.
  • Max cells: {"max_cells": 100} Limits the number of cells returned (default: num_rows * num_cols * 10).

(The former query argument is deprecated; it now maps to front_end_query.)

required
num_rows int

Number of rows in the portrait grid. Alias: rows.

required
num_cols int

Number of columns in the portrait grid. Alias: cols.

required
portrait_size_um float

Size of each portrait in micrometers.

required
portrait_gap int

Gap between portraits in pixels. Default is 4.

required
pixel_width float

Pixel width for scale bar calculation. If provided, a scale bar will be displayed.

required
token str

Authentication token for data access.

required
dataset_name str

Name to display in the UI.

required
width int

Widget width in pixels. 0 means 100%.

required
height int

Widget height in pixels.

required
segmentation str

Segmentation version to use. Default is "default".

required
adata AnnData

AnnData object for cell metadata.

required
cell_attr list

List of cell attributes to extract from adata.

required

Example::

# Using an explicit list of cell ids
yb = Yearbook(
    base_url="https://path-to-dataset",
    cells=["cell_1", "cell_2", "cell_3", "cell_4"],
    rows=2,
    cols=2,
    portrait_size_um=100,
)

# Using a Python selector result
selector = dega.select.Selector(adata)
selection = selector.select(query=selector.attr("leiden") == "5")
yb = Yearbook(
    base_url="https://path-to-dataset",
    selection=selection,
    rows=2,
    cols=2,
)

# Using a stateless front-end query (no AnnData needed)
yb = Yearbook(
    base_url="https://path-to-dataset",
    front_end_query={"gene": "BRCA1", "max_cells": 50},
    rows=2,
    cols=2,
    portrait_size_um=100,
)

total_pages property

Calculate total number of pages based on cells and grid size.

close()

Close the widget and notify the frontend to release resources.

go_to_page(page)

Navigate to a specific page.

next_page()

Navigate to next page.

prev_page()

Navigate to previous page.

clustergram_enrich(cgm, *, row_enrich=True, col_enrich=False)

Display a Clustergram widget and an Enrich widget side by side.

Parameters:

Name Type Description Default
cgm Clustergram

A Clustergram widget.

required
row_enrich bool

If True (default), run enrichment analysis when row dendrogram clusters are selected.

True
col_enrich bool

If True, run enrichment analysis when column dendrogram clusters are selected.

False

Returns:

Name Type Description
HBox HBox

Visualization display containing both widgets.

get_local_server()

Start a local HTTP server with CORS support and return the port number.

Returns:

Name Type Description
int int

The port number on which the server is running.

get_proxy_server(remote_base_url=None, verbose=False)

Start a local proxy server that forwards requests to a remote URL.

This is useful for bypassing CORS restrictions when the remote server (like Hugging Face) doesn't support CORS for Range requests.

Security: The proxy validates all URLs to prevent SSRF attacks: - Only http/https schemes are allowed - Private/loopback IP addresses are blocked - When remote_base_url is set, /proxy/ requests are constrained to that host

Parameters:

Name Type Description Default
remote_base_url str | None

Optional base URL for the remote server. If provided, requests to the proxy will be forwarded to this URL. If not provided, use /proxy/FULL_URL format.

None
verbose bool

If True, print log messages.

False

Returns:

Name Type Description
int int

The port number on which the proxy server is running.

Example

port = get_proxy_server("https://huggingface.co/datasets/user/repo/resolve/main/folder")

Now use http://localhost:{port}/file.parquet

Or use http://localhost:{port}/proxy/https://huggingface.co/.../other/file.parquet

landscape_clustergram(landscape, mat, width='600px', height='700px', *, enrich=False, row_enrich=True, col_enrich=False, enrich_kwargs=None)

Deprecated alias for :func:spatial_clustergram, kept for backward compatibility. Prefer spatial_clustergram, which also works with CellCloud, NeighborhoodCloud, and Yearbook.

landscape_yearbook(landscape, yearbook, width='100%', height='400px', cluster_attr='leiden')

Display a Landscape widget above a Yearbook widget with linked queries.

When the user clicks on a cluster in the Landscape, the Yearbook automatically updates to show cells from that cluster. When a gene is selected, cells are ranked by gene expression.

Parameters:

Name Type Description Default
landscape Landscape

A Landscape widget.

required
yearbook Yearbook

A Yearbook widget.

required
width str

The width of the widgets.

'100%'
height str

The height of each widget.

'400px'
cluster_attr str

The cell attribute (adata.obs column) a clicked cluster value refers to (default "leiden"). If the click payload carries its own attr it takes precedence, so linked Clustergrams over non-leiden sets (cell types, domains) color the right cells.

'leiden'

Returns:

Name Type Description
VBox VBox

Visualization display containing both widgets stacked vertically.

Example::

landscape = dega.viz.Landscape(base_url="...", adata=adata)
yearbook = dega.viz.Yearbook(base_url="...", rows=2, cols=4)
display = dega.viz.landscape_yearbook(landscape, yearbook)

landscape_yearbook_clustergram(landscape, yearbook, cgm, width='600px', height='400px', cluster_attr=None)

Display a Landscape and Clustergram side by side, with a Yearbook below.

All three widgets are linked: - Clustergram clicks update both Landscape and Yearbook - Gene selections rank cells in Yearbook by expression - Cluster selections filter cells in Yearbook

Parameters:

Name Type Description Default
landscape Landscape

A Landscape widget.

required
yearbook Yearbook

A Yearbook widget.

required
cgm Clustergram

A Clustergram widget.

required
width str

The width of each widget in the top row.

'600px'
height str

The height of each widget.

'400px'

Returns:

Name Type Description
VBox VBox

Visualization display with Landscape+Clustergram on top, Yearbook below.

Example::

landscape = dega.viz.Landscape(base_url="...", adata=adata)
yearbook = dega.viz.Yearbook(base_url="...", rows=2, cols=4)
cgm = dega.viz.Clustergram(matrix=mat)
display = dega.viz.landscape_yearbook_clustergram(landscape, yearbook, cgm)

spatial_clustergram(spatial, mat, width='600px', height='700px', *, enrich=False, row_enrich=True, col_enrich=False, enrich_kwargs=None, cluster_attr=None)

Display a spatial widget and a Clustergram widget side by side, linked so that clicking a Clustergram row/column updates the spatial widget.

Works with any of celldega's spatial widgets: Landscape, CellCloud, NeighborhoodCloud, or Yearbook. Landscape/CellCloud/ NeighborhoodCloud share an update_trigger trait and are linked via a front-end jslink (no round-trip through Python); Yearbook has no such trait and is instead linked by observing the Clustergram's click_info in Python and translating it into a front_end_query (same mechanism as landscape_yearbook_clustergram).

Parameters:

Name Type Description Default
spatial Landscape | CellCloud | NeighborhoodCloud | Yearbook

The spatial widget to link.

required
mat Clustergram

A Clustergram widget.

required
width str

The width of the widgets.

'600px'
height str

The height of the widgets.

'700px'
enrich bool | Enrich

If True, create an Enrich widget; if an Enrich instance is provided, use it directly. If False, no enrichment widget is shown. Ignored for a Yearbook spatial.

False
row_enrich bool

If True (default), run enrichment analysis when row dendrogram clusters are selected.

True
col_enrich bool

If True, run enrichment analysis when column dendrogram clusters are selected.

False
enrich_kwargs dict | None

Optional kwargs passed to Enrich when enrich=True.

None
cluster_attr str | None

The cell attribute (adata.obs column) a clicked cluster refers to. Only used when spatial is a Yearbook; defaults to the Clustergram's own col_entity attribute (see _clustergram_col_attr).

None

Returns:

Name Type Description
HBox HBox

Visualization display containing the widgets.