Data preparation (prepare)#
This page documents prepare(), which writes a Cellucid-ready
AnnData, and restore_original_order(), which reads one back
in its cells’ original order. A Cellucid-ready AnnData is one standard AnnData (.h5ad, .zarr folder, or .zarr.zip)
laid out for the web app’s range reads and naming itself in uns['cellucid'].
Given a MuData it writes a Cellucid-ready MuData (.h5mu, or MuData Zarr
as a folder or .zarr.zip): each modality a Cellucid-ready AnnData.
The result can be:
opened in the web app (Open…, or the Link or server bar once hosted),
served with
cellucid serve <file>,embedded in notebooks with
show_anndata(),read by any AnnData tool (
anndata.read_h5ad,anndata.read_zarr).
Long-form walkthroughs: Preparing an AnnData for Cellucid. The written contract: Cellucid-ready AnnData specification.
Fast path (copy/paste)#
from cellucid import prepare
# Everything the AnnData holds (obs, X with var, obsm, obsp['connectivities']):
path = prepare("my_study.h5ad", format="h5ad", data=adata, dataset_id="my-study-v1", dataset_name="My study")
# The same, component by component; an argument given with data= replaces that component.
path = prepare(
"my_study.h5ad",
format="h5ad",
force=True,
embeddings={"X_umap": adata.obsm["X_umap"], "X_pca": adata.obsm["X_pca"]},
dataset_id="my-study-v1",
dataset_name="My study",
obs=adata.obs,
var=adata.var,
gene_expression=adata.X,
connectivities=adata.obsp["connectivities"],
latent_key="X_pca",
)
prepare() returns the pathlib.Path it wrote.
Signature#
prepare(
out_path,
*,
format,
data=None,
embeddings=None,
dataset_id=None,
dataset_name=None,
obs=None,
var=None,
gene_expression=None,
connectivities=None,
vector_fields=None,
modalities=None,
gene_identifiers=None,
dataset_description=None,
citation_text=None,
citation_url=None,
source_name=None,
source_url=None,
embedding_defaults=None,
latent_key=None,
obs_keys=None,
var_gene_id_column=None,
vector_field_default=None,
normalize_embeddings=None,
centroid_min_points=None,
modality=None,
priority_seed=0,
zarr_format=None,
force=False,
) -> Path
Every argument after out_path is keyword-only. format is required and
has no default. embeddings, dataset_id and dataset_name are required
unless data holds them (obsm, uns['cellucid']['id'], ['name']). The R package’s cellucid_prepare() takes the same arguments
and writes the same Zarr layout (format = "zarr" or "zarr.zip"; R writes no
.h5ad or .h5mu, so a MuData from R is always MuData Zarr).
Which format?#
|
Writes |
Choose it for |
|---|---|---|
|
a |
GitHub: no file over 100 MB, no LFS, many small files at once over HTTP/2 |
|
one |
everything else: single-file hosts (Zenodo, Figshare, Hugging Face, S3, a lab server), local files, |
|
the Zarr store in one |
wherever an |
|
one |
a MuData wherever an |
The measurements behind this are in Which format?.
out_path must end in the suffix of format; a mismatch is refused with the
path to write instead.
Argument |
Stored as |
|---|---|
|
the output; ends in |
|
the container: |
|
an AnnData or a MuData whose components are the defaults of the arguments below (Prepare an AnnData or a MuData whole (data=)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
with a MuData, the modalities written, in order: several as a MuData of those, one as an AnnData |
|
keeps those genes, in that order |
|
|
|
|
|
also |
|
the cells’ order: by ascending priority, the subsampling |
|
2 (default) or 3, for |
|
replace an existing output of the same kind |
Interface reference#
A loaded dataset in Cellucid: the sidebar controls the active view while the categorical legend maps directly to the colored points.#
API reference#
- cellucid.prepare(out_path, *, format, data=None, embeddings=None, dataset_id=None, dataset_name=None, obs=None, var=None, gene_expression=None, connectivities=None, vector_fields=None, modalities=None, gene_identifiers=None, dataset_description=None, citation_text=None, citation_url=None, source_name=None, source_url=None, embedding_defaults=None, latent_key=None, obs_keys=None, var_gene_id_column=None, vector_field_default=None, normalize_embeddings=None, centroid_min_points=None, modality=None, priority_seed=0, zarr_format=None, force=False)[source]#
Write a Cellucid-ready AnnData (or MuData): a standard file laid out for the browser.
The output is an ordinary AnnData that
anndata.read_h5adoranndata.read_zarrreads, written so the Cellucid web app reads it fast over HTTP: the expression matrix gene-major (CSC), arrays chunked for range requests and compressed with codecs browsers decode natively, and the dataset’s name, citation and launch defaults inuns['cellucid']. Open it withcellucid serve,show_anndata(), or the web app directly. The written contract is the “Cellucid-ready AnnData” page of the documentation; cellucid-r’scellucid_prepare()writes the same.The inputs come from
data– an AnnData or a MuData – or are passed one by one, or both: every componentdataholds is its default, and an argument given explicitly replaces that one component. The output is byte for byte what the same components passed by hand write.A MuData is written as a Cellucid-ready MuData (
format="h5mu","zarr"or"zarr.zip"): a standard MuData whose modalities share the cells, each modality a Cellucid-ready AnnData (gene-majorX, chunked and compressed for the browser), the cells’ metadata, shared embeddings and graph at the root withuns['cellucid']. The written contract is the “Cellucid-ready MuData” section of the specification.Every input is checked before anything is written (a MuData modality’s matrix as it is written, one modality at a time), and the output is written beside
out_pathunder a temporary name and moved into place only once it is complete.- Parameters:
out_path (
str|PathLike[str]) – Where to write, ending in the suffix offormat:.h5ad,.zarr,.zarr.zipor.h5mu. A leading~is expanded.format (
Literal['h5ad','zarr','zarr.zip','h5mu']) –Required, with no default – which one depends on where the data goes (
"h5mu"is the single-file form of a MuData, like"h5ad";"zarr"and"zarr.zip"write a MuData as MuData Zarr):"zarr": a.zarrfolder of small files, for GitHub (a repository or its Pages site). GitHub refuses files over 100 MB and answers over HTTP/2, 100 requests at a time, so a folder’s one request per chunk costs nothing there."h5ad": one.h5adfile, for everything else: single-file hosts (Zenodo, Figshare, Hugging Face, S3, a lab server), local files,cellucid serveand Jupyter. Its ranges are merged into few requests; most such hosts answer over HTTP/1.1, six requests at a time, where a folder is several times slower. What opening reads comes first in the file (431 KB of a 561,947-cell atlas of 5,103 genes), which the web app reads with its first request of 512 KiB."zarr.zip": the Zarr store in one.zarr.zipfile (entries stored, metadata last), wherever an.h5adgoes.
Measured on a 561,947-cell atlas, every read the web app makes, in total: over GitHub’s HTTP/2 (80 ms, 50 MB/s) 8.3 s from the
.h5ad, 8.0 s from the folder, 8.2 s from the.zarr.zip; over HTTP/1.1 (80 ms, 50 MB/s) 9.0 s, 46.8 s and 9.0 s; from a local file in a browser 2.5, 2.6 and 2.7 s. The.zarr.zipis 13% smaller than the.h5ad(198 against 228 MB). The “Which format?” section of the documentation’s preparation guide has the full table.data (
Any) –An
anndata.AnnDataor amudata.MuData(pip install "cellucid[mudata]"to read and build one) that fills every component below an explicit argument does not:AnnData:
obs;Xasgene_expressionwithvar(neither whenXis absent); every numericobsmarray as an embedding under its own key, except a<field>_<basis>array as wide asX_<basis>, which is that vector field;obsp['connectivities']; and fromuns['cellucid']the identity (id,name,description,citation,source) and the launch defaults. Layers,raw, otherobspmatrices,obsmentries that are not numeric arrays, andobs/varcolumns of no AnnData encoding Cellucid writes (a date, a time span) are not written, and a message names each one, as cellucid-r names them (the same column given asobs=is refused, saying how to convert it). To leave out a componentdataholds, remove it from a copy first.MuData (modalities over shared cells,
axis0): the cells’mdata.obs,mdata.obsm(the shared embeddings and vector fields),mdata.obsp['connectivities']andmdata.uns['cellucid']at the root, as above; each modality whole – itsX,var,obs, numericobsmarrays andobsp['connectivities']– asmod/<name>. Columns and arrays mudata copies to the root from a modality (<name>:<column>) are not written twice: the viewer shows every modality’s own under that name. The genes are each modality’s own, sogene_expression,varandgene_identifiersare refused with a MuData: changemdata.mod[name]first.
embeddings (
Mapping[str,Any] |None) –{obsm key: (n_cells, k) array}, at least one (with a MuData, at the root or in a modality). Each is stored whole asobsm[key]in float32, every column, at its own coordinates (the viewer normalizes them). A latent space for outlier measurement is one of them, named bylatent_key. A plain(n_cells,)vector is one column; sparse input is densified. A row holding NaN (or an infinity) is a cell the embedding does not place (one computed on some of the cells): it is written as given, the viewer leaves it out of that embedding’s views, and in the latent space it gets no outlier quantile; at least one cell must have finite values.X_umap_1d/X_umap_2d/X_umap_3d, else the first 1- to 3-column ofX_umap,X_UMAP,X_wnn.umapandX_ref.umap, are shown by default.dataset_id (
str|None) – The dataset’s stable id: 1 to 180 ASCII letters, digits,.,_or-, starting with a letter or digit and not ending with.. Sessions and community annotations are keyed by it.dataset_name (
str|None) – The name shown for the dataset, also stored asuns['title'].obs (
DataFrame|None) – Cell metadata, one row per cell. Its index names the cells (pandas’ default0 .. n-1index names them"0"to"n - 1"); repeated names are made unique, as anndata does. Text columns become categoricals when a value repeats or is missing (anndata’s rule); numbers, booleans, categoricals and pandas nullable integers and booleans are stored as they are. Infinities are refused.var (
DataFrame|None) – Gene metadata, one row per column ofgene_expression. Its index names the genes; with pandas’ default index,var_gene_id_columnnames them. Every column is stored.gene_expression (
ndarray|spmatrix|sparray|None) –(n_cells, n_genes), sparse (any scipy format) or dense. Stored asX: CSC when sparse, dense otherwise, in float32 – or float64 when the genes it keeps (aftergene_identifiers) hold integer counts above 2^24, which float32 cannot hold exactly. Values must be finite. A stored zero is dropped.connectivities (
ndarray|spmatrix|sparray|None) –(n_cells, n_cells)neighbour graph, stored asobsp['connectivities'](CSR float32). Exactly symmetric, finite, non-negative; its diagonal is left out (a self-loop is no edge: Seurat’sRNA_snnhas 1 there), and a directed graph (RNA_nn,distances) is refused. From an AnnDatadata=, the graph the viewer’s default rule opens with:obsp['connectivities'], else Seurat’s<assay>_snn.vector_fields (
Mapping[str,Mapping[str,Any]] |None) –{field: {embedding key: (n_cells, k) array}}, one column per column of the embedding. Each array is stored asobsm['<field>_<basis>']for the embeddingX_<basis>, scVelo’s name ({"velocity": {"X_umap": v}}writesvelocity_umap), which the viewer draws as the field<field>over that embedding, so the embedding’s key must start withX_.modalities (
Sequence[str] |None) – With a MuData, the modalities to write, in this order (names ofmdata.mod); None writes every one, inmdata.modorder. Several are written as a Cellucid-ready MuData of those modalities (the rootvarandvarmaphold theirs alone). One is written as a plain Cellucid-ready AnnData (format="h5ad","zarr"or"zarr.zip"): the cells’obs, embeddings, graph anduns['cellucid']from the root, and that modality’sX,varandobsmarrays, its rows in the MuData’s cell order – so it must have measured every cell – withgene_expression,varandgene_identifiersthen applying to it. cellucid-r’scellucid_prepare(modalities = )takes the same names.gene_identifiers (
Sequence[str] |None) – Keep only these genes, in this order, matched against the names the viewer shows (var_gene_id_column, else the var index).dataset_description (
str|None) – One paragraph about the dataset.citation_text (
str|None) – How to cite the dataset; the address needs the text.citation_url (
str|None) – How to cite the dataset; the address needs the text.source_name (
str|None) – Where the data comes from; the address needs the name.source_url (
str|None) – Where the data comes from; the address needs the name.embedding_defaults (
Mapping[str,str|tuple[str,Sequence[int]]] |None) – The embedding each dimension opens on:{"2d": "X_tsne"}(its first columns) or{"2d": ("X_pca", [2, 0])}(0-based columns).latent_key (
str|None) – The embedding (anembeddingskey) the viewer’s outlier filter measures in: a latent space such as scVI or PCA, never a 2D/3D layout. The outlier quantiles of every categorical obs column (each cell’s distance to its category’s centre, as the share of its category at that distance or closer) are computed here and stored inuns['cellucid']['outlierQuantiles'], so the viewer filters outliers at once instead of reading the whole latent space to compute them.obs_keys (
Sequence[str] |None) – The obs columns the viewer lists, in this order; every column is stored either way.var_gene_id_column (
str|None) – The var column whose values name the genes in the viewer. Omitted, the var index names them; Data mapping can choose a column later.vector_field_default (
str|None) – Thevector_fieldsfield the overlay opens on; one of its embeddings must be shown when the file opens (a chosen or default embedding, or a 1-3 column array that is not the latent space).normalize_embeddings (
bool|None) – False shows embeddings at their own coordinates.centroid_min_points (
int|None) – The fewest cells a category needs to get outlier quantiles (10 when None).modality (
str|None) – With a MuData, the modality the viewer opens on (one ofmdata.mod);var_gene_id_columnnames a column of itsvar. When None the viewer opens on the first gene-expression modality (rna,gex,gene expression,gene_expression,sct, any case), else the first. Refused for an AnnData, which has one feature space.priority_seed (
int|None) – The seed of the cells’ priority order, an integer in[0, 2**32 - 1]. The cells are stored by ascending priority – theuniformrank of the subsampling specification (subsample_cells()) with this seed – so every subsample Cellucid opens with this seed is the first rows of every array, and reads nothing of the cells it leaves out. Each row’s original position is kept inobs['cellucid_original_position'];restore_original_order()puts the cells back in the order given. None stores the cells in the order given, without a priority.zarr_format (
Optional[Literal[2,3]]) – 2 or 3, forformat="zarr"or"zarr.zip"; Zarr v2 when None. Refused withformat="h5ad"and"h5mu".force (
bool) – Replace an existing output of the same kind. A folder that is not a Zarr store is never replaced.modality) (The launch defaults (embedding_defaults to)
choice (are written to uns['cellucid']['defaults'] only when given; a)
own. (left at None stays the viewer's)
- Returns:
The written file or folder.
- Return type:
Path
- Raises:
TypeError – A required input is missing (
dataset_idordataset_namethatdatadoes not name,embeddingswithoutdata) or an input has the wrong type.ValueError – An input is invalid or the inputs do not fit together (
out_pathnot ending in the suffix offormat, a MuData of several modalities withformat="h5ad", an AnnData withformat="h5mu",zarr_formatwith"h5ad"or"h5mu", …).FileExistsError –
out_pathexists andforceis False.
- cellucid.restore_original_order(data)[source]#
The cells of a file written in priority order, back in the order they were given.
A Cellucid-ready file stores its cells by priority (
prepare(),priority_seed), recorded inuns['cellucid']['priority'], each row’s original position inobs['cellucid_original_position'](and, in a MuData, each modality’s rows’ in its ownobs).anndata.read_h5adandanndata.read_zarr(mudata.read_h5mu,mudata.read_zarr) give the cells in that stored order; this returns a new object with every per-cell element –obs,obsm,obsp(both axes),X,layers, and in a MuData every modality’s cells – in the original order, without the position column,uns['cellucid']['priority']andvarm['cellucid_prefix_counts'], which describe the stored order only; the stored outlier quantiles (uns['cellucid']['outlierQuantiles'], one value per cell) follow the cells. A backed AnnData (anndata.read_h5ad(path, backed="r")) is read into memory in that order.datais returned as it is when its rows are each its own original position: it has no priority record, or one that no longer describes its cells – it was subset, concatenated or reordered after it was read (anndata keepsunsthrough all three) – which a warning reports. That is the rule the web app reads such a file by, so a session saved on it applies todataas it is.- Parameters:
data (
Any) – Ananndata.AnnDataor amudata.MuData.- Returns:
A new object in the original order, or
dataitself.- Return type:
AnnData or MuData
Examples
>>> adata = anndata.read_zarr("pbmc.zarr") >>> adata = cellucid.restore_original_order(adata)
Edge cases#
Validation first. Every input is checked before anything is written; a refusal leaves nothing on disk.
Atomic placement. The output is written beside
out_pathunder a temporary hidden name and moved into place only once complete.Existing outputs. Replaced only with
force=True; a folder that is not a Zarr store is never replaced.Names. Repeated cell or gene names are made unique (
MATR3,MATR3-1) and reported; keys and columns must be portable path components (Input requirements (global)).Values. Expression and the graph must be finite and fit in float32; embeddings and vectors fit float32, a row of NaN being a cell the array does not place (written as given, not drawn in that embedding);
obs/varnumbers may hold NaN but not infinities.Cell order. The cells are stored in priority order (
priority_seed), soanndata.read_h5ad/anndata.read_zarrgive them in that order;restore_original_order()puts them back in the order given.uns["cellucid"]["priority"]records the seed and the cell count (nObs) it was written for, and is verified before it is used: an object subset, combined or reordered since is taken as cells Cellucid did not write, with a warning (the specification’s “Verified before use”). An object in a verified stored order is put back in its original order before it is prepared again, whateverpriority_seedis. Every result Cellucid hands back (sessions, selections, exports) names cells by their original positions and obs names.Vector fields bind to an embedding named
X_<basis>, with exactly as many columns as it, under a key that reads back as that field and embedding (Vector fields (velocity / displacement)).
Troubleshooting#
Every refusal, its cause and its fix: Troubleshooting prepare().
See also#
Server (browser tab + local HTTP server) (
serve_anndata,cellucid serve)Jupyter (notebook embedding + hooks) (
show_anndata)