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:
- An explicit id list —
cells=["cell_1", "cell_2", ...]. The simplest path: you already know the cells you want. - A back-end selection —
selection=.... Accepts acelldega.select.Selection, a JSON-ready selection dict, or a plain id list. This is the recommended way to drive the grid from a PythonAnnDataobject, because it carries the query, sampler, scores, and provenance with the cells. See the select module docs for the full query/sampling algebra. - A stateless front-end query —
front_end_query=.... Evaluated in the browser against the dataset's LandscapeFiles, so it needs only abase_urland no PythonAnnData.
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 |
required |
adata
|
AnnData
|
Source of cell attributes/metadata (clusters,
colors, UMAP). Never used for spatial positions — those come from the
DegaFiles — except when |
required |
alignment
|
str
|
Named alignment variant; cell positions are
read from |
required |
use_adata_3d_centroids
|
bool
|
When an |
required |
z_key
|
str
|
|
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'
|
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 |
None
|
Returns:
| Type | Description |
|---|---|
Series
|
A |
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 ( |
required |
modality
|
str
|
Modality key on a collection/MuData (default |
'population'
|
category
|
str | None
|
Population |
None
|
colors
|
dict[str, str] | None
|
Optional |
None
|
adata
|
Any
|
Optional source cell-level |
None
|
group_attrs
|
list[str] | None
|
Dataset/set |
None
|
normalized
|
bool | None
|
Column-normalize each bar to 100%. Defaults to |
None
|
col_weights
|
dict[str, float] | None
|
Optional |
None
|
cluster
|
bool
|
Run hierarchical clustering before display (default |
True
|
name
|
str
|
Clustergram registry name. |
'composition'
|
width / height
|
Widget size in pixels. |
required | |
**kwargs
|
Any
|
Forwarded to :class: |
{}
|
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 |
None
|
slice_attr
|
str | None
|
For a single combined |
None
|
slices
|
Sequence[Any] | None
|
The initial |
None
|
cluster_key
|
str | None
|
Optional |
None
|
slice_labels
|
dict[Any, str] | None
|
Optional |
None
|
landmarks
|
DataFrame | None
|
An optional pre-existing landmark table to load —
:func: |
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 |
required | |
landscapes
|
Any
|
Not implemented yet — planned future alternative to
|
None
|
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If |
ValueError
|
If |
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 |
required |
z_key
|
str
|
|
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 |
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 |
required |
front_end_query
|
dict
|
Stateless query evaluated in the browser
against LandscapeFiles (no Python/AnnData required). This is separate
from the Python-side
(The former |
required |
num_rows
|
int
|
Number of rows in the portrait grid. Alias: |
required |
num_cols
|
int
|
Number of columns in the portrait grid. Alias: |
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 |
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 |
required |
yearbook
|
Yearbook
|
A |
required |
width
|
str
|
The width of the widgets. |
'100%'
|
height
|
str
|
The height of each widget. |
'400px'
|
cluster_attr
|
str
|
The cell attribute ( |
'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 |
required |
yearbook
|
Yearbook
|
A |
required |
cgm
|
Clustergram
|
A |
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 |
required |
width
|
str
|
The width of the widgets. |
'600px'
|
height
|
str
|
The height of the widgets. |
'700px'
|
enrich
|
bool | Enrich
|
If True, create an |
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 |
None
|
cluster_attr
|
str | None
|
The cell attribute ( |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
HBox |
HBox
|
Visualization display containing the widgets. |