Jupyter (notebook embedding + hooks)#
This page documents the notebook-facing APIs:
Fastest notebook preview:
show_anndata()(serve AnnData directly)Reproducible notebook view:
show()(view an exported dataset directory)Interactive control: viewer objects (
AnnDataViewer,CellucidViewer) support hooks + Python→frontend commands
Audience + prerequisites#
Audience
Wet lab / beginner: copy/paste the “Fast path” and use the troubleshooting section when something looks wrong.
Computational: use “Practical path” + “Edge cases” to avoid performance and data-shape pitfalls.
Power user: use “Deep path” to understand how the server + hooks + session capture work.
Prerequisites
pip install cellucidIf you use AnnData: install
anndata(and typicallynumpy,scipy,pandas).A notebook environment: classic Jupyter, JupyterLab, VSCode notebooks, or Google Colab.
Fast path (beginner-friendly)#
A) “I have an AnnData”#
from cellucid import show_anndata
viewer = show_anndata(adata) # or "data.h5ad" / "data.zarr"
What you should see:
A Cellucid viewer embedded in the notebook output, showing your embedding.
(Optionally) a one-time “viewer UI cache” download progress message on first run.
B) “I already exported a dataset folder”#
from cellucid import show
viewer = show("./my_export")
Practical path (step-by-step + common workflows)#
1) Notebook display vs browser tab#
Cellucid always runs in a browser context (the viewer UI), but you choose where it appears:
Notebook embedding: viewer appears inline (this page).
Browser tab: use
serve()/serve_anndata()/cellucid serve …(see Server (browser tab + local HTTP server)).
2) Choosing show_anndata vs show#
Use show_anndata() when:
you’re iterating quickly in analysis notebooks,
you don’t want to write an export folder yet,
you can accept slower loads and less shareable artifacts.
Use show() when:
you want reproducibility (the export folder is a concrete artifact),
you want speed (pre-quantized, pre-packed binaries),
you want to share the dataset directory or host it.
3) A minimal “hooks” example (viewer → Python)#
from cellucid import show_anndata
viewer = show_anndata(adata)
@viewer.on_selection
def on_selection(event):
# event["cells"] is a list[int] of selected indices (row indices into adata)
print("Selected", len(event.get("cells", [])), "cells")
4) A minimal “control” example (Python → viewer)#
# Highlight a few cells (indices into the dataset)
viewer.highlight_cells([0, 10, 20], color="#ff0000")
# Color points by an obs field (must exist in the dataset/AnnData)
viewer.set_color_by("cell_type")
# Hide a subset (or pass None to apply to all)
viewer.set_visibility([1, 2, 3], visible=False)
# Reset the camera
viewer.reset_view()
5) Waiting for the viewer to be ready (robust notebooks)#
If you need to run code only after the UI finished loading:
viewer.wait_for_ready(timeout=30)
6) Capturing a .cellucid-session bundle without downloading (advanced)#
This is the “no browser download” workflow:
bundle = viewer.get_session_bundle(timeout=60)
print(bundle.list_chunk_ids())
See Sessions (.cellucid-session bundles) for what a session bundle contains and how to apply it back onto an AnnData.
Screenshot placeholders (optional but recommended)#
The Cellucid viewer running inline in a notebook after calling show_anndata(adata); the sidebar controls and the embedding plot confirm the viewer is interactive.#
Deep path (how notebook embedding works)#
What starts when you call show(...) / show_anndata(...)#
A local HTTP server starts (on
127.0.0.1:<port>).Exported data:
CellucidServerAnnData mode:
AnnDataServer
The viewer UI is loaded from the same origin via a hosted-asset proxy (to avoid mixed-content and cross-origin issues).
The viewer UI posts interaction events back to the local server at
/_cellucid/events.The Python viewer routes those events to your hook callbacks (e.g.,
@viewer.on_selection).
Environment caveat: when the browser cannot reach the kernel’s localhost#
Some notebook setups run the kernel remotely. In those cases, your browser may not be able to reach http://127.0.0.1:<port> directly.
If that happens, set:
CELLUCID_CLIENT_SERVER_URLto a browser-reachable URL for the running Cellucid server (HTTPS if required).
API reference#
Functions#
show_anndata#
- cellucid.show_anndata(data, height=600, **kwargs)[source]#
Quickly display an AnnData object, h5ad file, or zarr store in a notebook.
This is the easiest way to visualize AnnData directly without running prepare first. However, it’s slower than using pre-exported data.
- Parameters:
data (str | Path | anndata.AnnData) – AnnData object, path to h5ad file, or path to zarr directory.
height (int) – Height of the viewer in pixels.
**kwargs – Additional arguments passed to AnnDataAdapter - latent_key: Key in obsm for latent space (auto-detected) - gene_id_column: Column in var for gene IDs (“index” by default) - normalize_embeddings: Normalize to [-1,1] (default True) - dataset_name: Human-readable name
- Return type:
AnnDataViewer
- Returns:
AnnDataViewer instance for interaction via hooks.
- Supported formats:
In-memory AnnData objects
.h5ad files (HDF5-based, lazy loading via backed mode)
.zarr directories (directory-based, inherently lazy-loaded)
Example
>>> from cellucid import show_anndata >>> viewer = show_anndata(adata) >>> >>> @viewer.on_selection ... def handle(event): ... subset = adata[event['cells']] ... sc.pl.violin(subset, 'gene1')
>>> # With custom options >>> viewer = show_anndata(adata, latent_key="X_pca", height=800)
Note
For production use or sharing, consider using prepare to create optimized binary files, then use show() to display them.
show#
- cellucid.show(data_dir, height=600)[source]#
Quick function to display a cellucid dataset in a notebook.
- Parameters:
- Return type:
- Returns:
CellucidViewer instance for interaction via hooks.
Example
>>> from cellucid.jupyter import show >>> viewer = show("/path/to/my_dataset") >>> >>> @viewer.on_selection ... def handle(event): ... print(f"Selected {len(event['cells'])} cells")
Classes (see dedicated page)#
AnnDataViewerandCellucidViewerare documented on Viewer classes (Jupyter objects you control from Python).
Edge cases (do not skip)#
Data size and performance#
Very large
adata.Xcan be slow in AnnData mode; consider exporting withprepare().If your
.h5adis huge, prefer serving in backed/lazy mode (default) rather than loading fully into RAM.
“My embedding is not 2D/3D”#
Cellucid supports 1D/2D/3D embeddings; if the embedding is missing or has an unexpected shape, you’ll see missing plot / errors.
Duplicate gene identifiers#
If gene IDs are duplicated, gene lookup behavior can be ambiguous; ensure you have a stable gene ID strategy (see Export / Data Preparation (prepare) and Adapters (AnnData → Cellucid data model)).
Troubleshooting (symptom → diagnosis → fix)#
Symptom: “Viewer does not appear in the notebook output”#
Likely causes:
You are not actually running inside a notebook (e.g., plain Python script).
The notebook output is blocked (content security policy / iframe blocked).
How to confirm:
Print
viewer.viewer_urland try opening it in a new browser tab.
Fix:
Use a notebook environment (Jupyter, JupyterLab, VSCode notebooks, Colab).
If iframes are blocked, open the printed URL manually.
Symptom: “Notebook proxy required” / the iframe shows a proxy warning#
Likely causes:
The browser cannot reach the kernel’s localhost server (remote kernel or strict origin policy).
Fix options:
Recommended: install/enable
jupyter-server-proxy(environment dependent).Or set
CELLUCID_CLIENT_SERVER_URLto a browser-reachable URL for the server.
Symptom: “Port already in use”#
Fix:
Choose a different port (pass
port=...to the viewer class, or stop the process using the port).
Symptom: “I registered @viewer.on_selection but nothing prints”#
Likely causes:
The viewer is not ready yet.
You selected nothing (or selection tools differ from expectation).
How to confirm:
Call
viewer.wait_for_ready()and then try selecting again.
Fix:
Ensure the viewer is loaded, then select cells (lasso/shift-click/etc.).
Symptom: “The iframe is blank / white / stuck loading”#
Likely causes:
The viewer UI failed to load (offline, blocked network, or cache missing).
The server isn’t reachable from the browser (remote kernel / HTTPS notebook constraints).
How to confirm:
Open
viewer.viewer_urlin a new browser tab (sometimes notebook output hides useful errors).
Fix:
If you are offline, run once while online (to populate the viewer UI cache), then retry.
If the browser cannot reach localhost, set
CELLUCID_CLIENT_SERVER_URL(or use a notebook proxy).
Symptom: “viewer.set_color_by(...) does nothing”#
Likely causes:
The field name does not exist in
obs(or has a different spelling/case).The viewer is not ready yet.
How to confirm:
Wait for readiness:
viewer.wait_for_ready().In AnnData mode, print
adata.obs.columnsand confirm the field exists.
Fix:
Use the exact field name.
Prefer exporting with
prepare()for stable field naming across sessions.
Symptom: “viewer.highlight_cells(...) does nothing”#
Likely causes:
The viewer is not ready yet.
Indices are out of range (wrong dataset / wrong cell order).
How to confirm:
viewer.wait_for_ready()Try highlighting a small index like
[0].
Fix:
Ensure indices correspond to the dataset loaded in the viewer.
If you subset/reorder AnnData, re-run the viewer from the same object.
Symptom: “Selections map to the wrong cells in my AnnData”#
Likely causes:
The viewer is connected to a dataset whose row order does not match your
adata.
How to confirm:
Select a single cell and print identifying metadata from
adata.obs.iloc[cell_index].Compare with what you expect in the UI.
Fix:
Ensure you apply selection indices to the same AnnData used to create/serve the viewer.
Avoid reordering
adataafter starting the viewer; restart the viewer after reindexing.
Symptom: “My hook callback crashes silently”#
What’s happening:
Hook callbacks are wrapped; exceptions are logged rather than crashing the notebook cell.
How to confirm:
Enable debug logging:
import logging logging.basicConfig(level=logging.DEBUG)
Fix:
Add defensive checks inside callbacks (validate keys, lengths, types).
Start with
@viewer.on_messageto inspect raw event payloads.
Symptom: “I don’t know what’s wrong / I need a diagnostic dump”#
Fix:
Run:
report = viewer.debug_connection() report
The report includes:
server health/info probes,
detected notebook context (Jupyter/Colab/VSCode),
viewer UI cache status,
recent events and readiness state.
See also#
Server (browser tab + local HTTP server) for browser-tab workflows and SSH tunneling
Export / Data Preparation (prepare) for reproducible exports (
prepare(...))Sessions (.cellucid-session bundles) for
.cellucid-sessionbundles (capture + apply)