View and prepare single-cell data in R for Cellucid — interactive, GPU-accelerated visualization in the browser.
cellucid (repo: cellucid-r) opens a Seurat, SingleCellExperiment or SummarizedExperiment object in the Cellucid viewer from R — in the RStudio or Positron Viewer pane or a browser, with no Python — and writes it (or your embeddings, metadata, gene expression, neighbour graph and vector fields) as a Cellucid-ready AnnData: a standard AnnData Zarr store that the Cellucid web app opens directly and Python’s anndata reads like any other. Several assays become a Cellucid-ready MuData.
Active package version — 0.9.7
Version 0.9.7 is the active Cellucid for R source and documentation version, and it is the CRAN submission release. The CRAN package index is authoritative for registry availability; the Installation guide below gives both exact installation paths.
Highlights
-
View an object from R:
cellucid_view(seu)serves the object from memory as the storecellucid_prepare()would write, uncompressed over loopback and making only what the viewer reads (a million-cell object’s first gene in about a third of a second, never transposing its matrix), so a 100,000-cell object opens in under a second; do anything a person can do in the viewer from R – every action of its catalogue,cellucid_act(viewer, "color.by", ...)or its own function,cellucid_color_by(),cellucid_highlight_cells(),cellucid_history_get(), … – each one step of the viewer’s history, labelled as R’s; listen withcellucid_on("selection", ...); ask for its session (its whole history) withcellucid_request_session()(thencellucid_session_result()), read it withcellucid_read_session()– trackers, branches, groups, steps, notes and turns as data frames (cellucid_steps(),cellucid_groups(),cellucid_turns(), …), the methods paragraph and pseudocode of a branch – and apply any step or branch back onto the object withcellucid_apply_session()(a plan first, thencellucid_apply_plan(); each apply recorded); group R’s actions into one turn of the history withcellucid_turn(), hear every change withcellucid_on("history_changed", ...)and push a session file into the viewer withcellucid_load_session(); write everything made in it (highlights, labels, scores, gene sets) back onto the object in one call withcellucid_pull(seu, viewer)(or from the web app’s exports,cellucid_pull(seu, "exports/")), and send a column to it withcellucid_push()(a gene set withcellucid_gene_set_save());cellucid_serve()for a cluster behind an SSH tunnel; in a Jupyter notebook (IRkernel) the viewer is the cell’s output, the widget cellucid-python shows, with no port -
Objects in, directly:
cellucid_prepare(data = seu)reads Seurat (v3–v5), SingleCellExperiment and SummarizedExperiment objects as the web app reads them; any argument given replaces that component -
One standard format: an AnnData Zarr store (format 2, or 3 with
zarr_format = 3) with consolidated metadata — a.zarrfolder for GitHub (format = "zarr"), or one.zarr.zipfile (format = "zarr.zip") for everywhere else: single-file hosts (Zenodo, Figshare, Hugging Face, S3, a lab server), local files,cellucid serveand Jupyter -
Fast in the browser: gene-major expression (CSC), chunked for range reads, byte-shuffled where that helps and compressed with deflate, which browsers decompress natively; a
.zarr.zipkeeps its metadata at the end of the archive, so it opens with one read -
Subsamples read only their cells: the cells are stored (and served by
cellucid_view()) in priority order (priority_seed, default 0), so a share the viewer opens is the first rows of every array and the first values of every gene;cellucid_subsample_cells()gives exactly the cells the viewer and Python’scellucid.subsample_cells()keep, andcellucid_restore_original_order()puts an object read from such a file back in the order its cells were given -
Self-describing: the dataset’s id, name, citation, source, and launch defaults live in
uns['cellucid'], with each categoricalobscolumn’s outlier quantiles in the latent space named bylatent_key, so the viewer’s outlier filter works as soon as the file opens -
Light dependencies:
jsonlite, andhttpuv,laterandcurlfor the viewer (optional:Matrix,SeuratObject,SingleCellExperiment/SummarizedExperiment, each needed only for its own objects;IRkernelandIRdisplayfor the viewer in a Jupyter notebook) - Flexible inputs: R objects, or raw matrices and data frames
Every value is stored as float32 (embeddings, expression, vector fields, the graph; expression as float64 only for integer counts above 2^24, which float32 cannot hold exactly) and must be finite. A neighbour graph must be exactly symmetric, with a zero diagonal and non-negative weights; a stored zero in a sparse input is not an edge and is dropped.
gene_expression is always interpreted as cells × genes. Cellucid validates its row and column counts but never guesses or transposes orientation; for a square matrix, shape alone cannot reveal a genes × cells input.
Installation
Use the dedicated Installation guide to choose CRAN or GitHub based on current registry availability. To install the active source directly from the official GitHub repository:
install.packages("remotes")
remotes::install_github("theislab/cellucid-r")Source installation compiles a few small C routines (checksums, the outlier quantiles, one-pass matrix checks, the decoders of a saved session, linked against zlib) and therefore needs Rtools on Windows, the Xcode Command Line Tools on macOS, or a C toolchain plus the R and zlib development headers on Linux. A platform CRAN binary, when available, does not require a local compiler.
Optional but recommended (sparse expression matrices and neighbour graphs):
install.packages("Matrix")See the dedicated Installation guide for requirements, verification, upgrades, and the CRAN availability status.
Quickstart
library(cellucid)
# View an object
viewer <- cellucid_view(seu) # a Seurat, SingleCellExperiment or SummarizedExperiment
cellucid_color_by(viewer, field = list(source = "obs", key = "seurat_clusters"))
cellucid_selection(viewer) # the cells you selected in the viewer
seu <- cellucid_pull(seu, viewer) # every highlight, label and score made in the viewer, as meta.data columns
cellucid_push(viewer, seu$seurat_clusters, key = "seurat_clusters") # a column of yours, into the viewer
cellucid_stop(viewer)
# Write it for sharing
cellucid_prepare("pbmc.zarr", "zarr", data = seu, dataset_id = "pbmc", dataset_name = "PBMC")
# Or write components you hold as matrices
cellucid_prepare(
out_path = "my_dataset.zarr", # or "my_dataset.zarr.zip" with format = "zarr.zip"
format = "zarr",
embeddings = list( # obsm: any number, every column kept
X_umap = umap,
X_pca = pca
),
dataset_id = "my-dataset",
dataset_name = "My dataset",
obs = obs, # data.frame, one row per cell
var = var, # data.frame, one row per gene
gene_expression = expr, # cells × genes, sparse or dense
connectivities = knn, # optional cells × cells graph
embedding_defaults = c("2d" = "X_umap"),
latent_key = "X_pca"
)In a Jupyter notebook show the viewer in one cell and call cellucid_pull() in the next: R hears the viewer between cells. Seven runnable notebooks, each with a Python twin and an “Open in Colab” badge, walk through the round trip: Notebook tutorials.
Open a .zarr.zip file from your computer in the web app at https://www.cellucid.com, or a .zarr folder or .zarr.zip file published at a web address with the Link or server address bar; read either in Python with anndata.read_zarr() (its cells in priority order: cellucid.restore_original_order() in Python, or cellucid_restore_original_order() on what anndataR or zellkonverter read, gives them back in the order you passed them).
The store is written beside out_path under a temporary name and moved into place only when it is complete; force = TRUE replaces an existing store. Vector fields are stored under scVelo’s names and drawn over the embedding they are named for: vector_fields = list(velocity = list(X_umap = v)) stores obsm['velocity_umap'], and X_branches = vb stores obsm['velocity_branches'], both listed by the viewer as the field velocity. cellucid_transition_drift() computes such a field from a cell-cell transition matrix (CellRank’s, for example), the computation of Python’s compute_transition_drift(). Repeated cell or gene names are made unique the way anndata does it (MATR3, MATR3-1), and var_gene_id_column names the var column, such as gene symbols beside Ensembl row names, that the viewer shows.
Agent apps on your computer
cellucid_mcp() is a local MCP server that lets an agent app on your computer (Claude Code, Claude Desktop, Cursor) work in a Cellucid viewer, with the web app’s own tools under your permission settings: every change is a step of your history, asked in the viewer’s confirm card (and in the app) when your settings say so, and one Undo turn takes the agent’s turn back. Register it once:
It drives the newest viewer open on this computer (cellucid_view() or cellucid_serve() in R, show_anndata() in Python); viewer = names one, and open = "data.zarr" serves a file in a viewer of its own. A notebook widget’s viewer (IRkernel) has no server and is not reached; CELLUCID_AGENTS=off publishes no viewer to agents at all. A dataset’s “Agents see names and summaries only” switch, set in the viewer, applies to these agents too. See ?cellucid_mcp.
Documentation and ecosystem
- R package guide with pages for Seurat and SingleCellExperiment objects, for viewing them from R (Viewing and loading), and notebook tutorials
- Complete Cellucid documentation
- Live web application and web viewer source
- Python package
- Official public demo datasets
- Custom dataset repository examples
- Community annotation repository
- Citation:
citation("cellucid")
Citation
Placeholder citation. The Cellucid preprint is in preparation for bioRxiv and has no DOI yet; the reference below is a placeholder and will be replaced when the preprint is published.
If you use Cellucid, please cite:
Inecik, K. PLACEHOLDER: Cellucid preprint, title to be announced (forthcoming on bioRxiv). bioRxiv (in preparation).
BibTeX and other formats: Citing Cellucid.
Community
- Contributing: CONTRIBUTING.md
- Code of Conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
- Support: SUPPORT.md
- GitHub citation metadata: CITATION.cff