Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Explore CyteBase

CyteBase provides cloud-hosted CyteArc DataStores that you can connect to directly for exploration and analysis, without first downloading an H5AD or a complete data.zarr. Search the catalog, choose a dataset, and open its published store from a local notebook or a Python session on cloud compute.

CyteArc reads metadata and count blocks over the network as needed. Computation runs where your Python session runs; connecting to CyteBase does not provision a cloud worker. Shared stores are read-only. A mount lets you save new analysis results on your execution machine while the counts stay in CyteBase.

This tutorial uses datasets sourced from CELLxGENE. It searches the catalog, reads cell annotations, and plots the UMAP coordinates supplied by CELLxGENE. Gene expression comes from the published RNA counts; no new embedding or analysis pipeline is run in this walkthrough.

The saved results on this page were built with the CyteBase October 2026 release (2610), published in the public Nygen/cytebase-2610 bucket, which readers can access without credentials. Each release has its own bucket, so rerunning this page against 2610 reads the same catalog; cytebase.releases() lists newer releases.

Use the page download menu to save the source notebook. For a longer worked example, see the CyteBase case study: COVID-19 blood case study.

Install CyteArc’s SDK and plotting dependencies in your notebook environment:

# Install the CyteBase connector and a notebook environment.
uv pip install --prerelease allow 'cytearc[cytebase]' jupyterlab

When working from a CyteArc checkout, use uv sync --extra cytebase --extra extra and select its Python kernel. cytebase.Catalog() connects to the latest public release by default; this page pins version="2610". To use another bucket, pass bucket= to Catalog instead of version=, or omit both and set CYTEBASE_BUCKET before starting Jupyter. Explicit arguments take precedence over the environment variable. For a private bucket, supply HF_TOKEN through your environment or use your existing Hugging Face login. Keep credentials and private bucket names out of notebook source and outputs.

Started: 2026-10-12T13:54:14.773091Z | Wall time: 2.715 s

Catalog(version="2610") connects to the October 2026 release and keeps a small local copy of its catalog. Searches use this catalog, so they do not read any count data. By default, they return datasets ready to open.

The example is a single-nucleus RNA-seq dataset of human kidney cortex from donors with and without diabetic kidney disease (Wilson et al., 2022). Search for its author and tissue, then keep the returned identifier rather than constructing an ID yourself.

Loading...

Started: 2026-10-12T13:54:17.490114Z | Wall time: 2.306 s

Loading...

Started: 2026-10-12T13:54:19.798251Z | Wall time: 4.555 s

entry is a DatasetEntry containing metadata about the scientific dataset. Displaying it reads the catalog and dataset record. It does not open the remote Zarr hierarchy. The citation and CELLxGENE links identify the original study; retain these when using the data.

Open the remote DataStore

catalog.open_datastore(entry.id) validates the published dataset version and build receipt, then returns a DataStore with zarr_mode="r". Counts remain remote and the SDK does not write back to the bucket. Keep this object as ds for metadata queries, plotting, and other datastore operations.

DataStore has 39176 (39176) cells with 1 assays: RNA Cell metadata: 'I', 'ids', 'names', 'RNA_nCounts', 'RNA_nFeatures', 'RNA_percentMito', 'RNA_percentRibo', 'assay', 'assay_ontology_term_id', 'author_cell_type', 'cell_type', 'cell_type_ontology_term_id', 'development_stage', 'development_stage_ontology_term_id', 'disease', 'disease_ontology_term_id', 'donor_id', 'doublet_id', 'is_primary_data', 'library_uuid', 'mapped_reference_annotation', 'nCount_RNA', 'nCount_SCT', 'nFeature_RNA', 'nFeature_SCT', 'observation_joinid', 'percent.mt', 'percent.rpl', 'percent.rps', 'reported_diseases', 'sample_preservation_method', 'sample_uuid', 'self_reported_ethnicity', 'self_reported_ethnicity_ontology_term_id', 'seurat_clusters', 'sex', 'sex_ontology_term_id', 'suspension_type', 'suspension_uuid', 'tissue', 'tissue_ontology_term_id', 'tissue_type' RNA assay has 35469 features and following metadata: 'I', 'ids', 'names', 'dropOuts', 'feature_biotype', 'feature_length', 'feature_reference', 'feature_type', 'nCells'

Started: 2026-10-12T13:54:24.354425Z | Wall time: 23.616 s

Small Zarr metadata objects are cached in memory for this open store. Count chunks are fetched when needed; the SDK does not maintain a persistent local count cache. Opening and plotting still depend on network latency.

The source H5AD may contain more embeddings than the pipeline imported. Check the imported keys before plotting:

Source embedding keys: ['X_harmony', 'X_pca', 'X_umap']
Imported embedding keys: ['X_umap']

Started: 2026-10-12T13:54:47.971824Z | Wall time: 3.872 s

The current pipeline imports obsm/X_umap. An X_pca key in the source list alone does not mean its coordinates are available in the CyteArc store.

Read cell metadata

CELLxGENE annotations are stored beside CyteArc’s QC columns, such as RNA_nCounts and RNA_nFeatures. Request only the columns needed for a figure:

cell_typediseasedonor_id
ids
AAACCTGAGTGTTAGA-1epithelial cell of proximal tubulenormalcontrol_1
AAACCTGCAAGCGCTC-1kidney loop of Henle thick ascending limb epithelial cellnormalcontrol_1
AAACCTGCACCAGATT-1kidney loop of Henle thick ascending limb epithelial cellnormalcontrol_1
AAACCTGCAGTCAGAG-1epithelial cell of proximal tubulenormalcontrol_1
AAACCTGCATGGAATA-1kidney distal convoluted tubule epithelial cellnormalcontrol_1

Started: 2026-10-12T13:54:51.845275Z | Wall time: 10.092 s

This materializes the selected metadata columns as a pandas DataFrame, not the expression matrix. On a large atlas, metadata and coordinates still require memory proportional to the selected cells.

Use ds.cells.columns to check the available names. CyteArc replaces / and \ in imported column names with _ so they can be stored safely.

cells
cell_type
epithelial cell of proximal tubule11478
kidney distal convoluted tubule epithelial cell8469
kidney loop of Henle thick ascending limb epithelial cell7749
renal principal cell3295
renal alpha-intercalated cell2029
endothelial cell1702
parietal epithelial cell1103
podocyte1069
kidney loop of Henle thin ascending limb epithelial cell679
renal beta-intercalated cell670
mesangial cell385
fibroblast338
leukocyte210

Started: 2026-10-12T13:55:01.938620Z | Wall time: 0.009 s

Compare cell-type composition between the donor groups:

diseasenormaltype 2 diabetes mellitus
cell_type
endothelial cell1167535
epithelial cell of proximal tubule88182660
fibroblast210128
kidney distal convoluted tubule epithelial cell60992370
kidney loop of Henle thick ascending limb epithelial cell54322317
kidney loop of Henle thin ascending limb epithelial cell324355
leukocyte54156
mesangial cell268117
parietal epithelial cell696407
podocyte679390
renal alpha-intercalated cell1491538
renal beta-intercalated cell376294
renal principal cell20531242

Started: 2026-10-12T13:55:01.949401Z | Wall time: 0.026 s

Plot the stored UMAP

ds.plots.embedding(layout=umap_ref, ...) uses the exact imported coordinates without recomputing UMAP. With a moderate number of cell types, the default legend placement writes each label on its cluster. A large atlas with many labels is better viewed with selected groups or legend_loc="none".

Published kidney UMAP colored and labeled by cell type, including tubular epithelial cells, intercalated cells, podocytes, endothelial cells, fibroblasts, and leukocytes.

Started: 2026-10-12T13:55:01.976529Z | Wall time: 11.770 s

Focus on the five most common cell types without changing the source dataset:

The published kidney UMAP restricted to its five most abundant cell types. Colors distinguish proximal tubule, distal convoluted tubule, thick ascending limb, principal, and alpha-intercalated cells.

Started: 2026-10-12T13:55:13.748015Z | Wall time: 8.485 s

Gene expression

CyteArc looks up gene symbols without regard to case. Here we use UMOD for the thick ascending limb of the loop of Henle, SLC34A1 for the proximal tubule, NPHS1 for podocytes, and PECAM1 for endothelial cells. An unknown or ambiguous name raises an error, so check the feature metadata when adapting this panel to another dataset.

Started: 2026-10-12T13:55:22.234517Z | Wall time: 0.003 s

Expression values are normalized on read; this example explicitly requests a log1p transform. Neither the count matrix nor the imported coordinates are modified. Drawing high values last makes expressing cells easier to see. Each gene is read from the remote counts, so every panel adds network reads.

Kidney UMAP panels show log-normalized UMOD, SLC34A1, NPHS1, and PECAM1 expression in distinct regions corresponding to the selected marker populations.

Started: 2026-10-12T13:55:22.238621Z | Wall time: 22.918 s

Other plots from the same assay

The read-only DataStore also supports plots from existing metadata and counts. For example, compare a QC measure across cell types:

Violin plots of total RNA counts across the five most common kidney cell types. Each distribution shows per-cell counts rather than a comparison of gene expression.

Started: 2026-10-12T13:55:45.158439Z | Wall time: 2.369 s

Gene distributions use the same interface; this optional example reads additional expression values:

# Compare distributions within the stated groups.
ds.plots.distribution(
    genes[:2],
    grouping=CellField("cell_type"),
    groups=top_types,
    figsize=(12, 5),
)

Coordinates for custom plots

Coordinates follow the embedding artifact’s frozen cell selection and are indexed by cell ID. Join on those IDs instead of assuming the same row order as a separate metadata table:

umap_1umap_2cell_type
ids
AAACCTGAGTGTTAGA-1-0.523972-8.470732epithelial cell of proximal tubule
AAACCTGCAAGCGCTC-1-7.0737313.068685kidney loop of Henle thick ascending limb epithelial cell
AAACCTGCACCAGATT-1-6.2798584.984632kidney loop of Henle thick ascending limb epithelial cell
AAACCTGCAGTCAGAG-10.838804-11.116598epithelial cell of proximal tubule
AAACCTGCATGGAATA-13.5738105.386316kidney distal convoluted tubule epithelial cell

Started: 2026-10-12T13:55:47.529047Z | Wall time: 4.546 s

The joined table is ready for a custom figure or for export. For most views, the CyteArc plotting calls above already handle group selection and legends.

Save a figure

CyteArc returns a PlotResult. Save the first cell-type figure without repeating its remote reads, and close the result when finished. For a new figure that should only be saved, pass show=False to the plotting call.

Saved figures/cytebase_cell_types.png

Started: 2026-10-12T13:55:52.076241Z | Wall time: 0.180 s

Writable analysis and larger datasets

The snippets in this section are optional and were not executed for this page. Run them in your local Python environment or on cloud compute. Create a mount before running CyteArc operations that save new results:

# Mount a writable analysis store while keeping counts remote.
analysis_ds = catalog.mount_datastore(entry.id, at="./analysis.zarr")

The mount stores metadata and new analysis results at ./analysis.zarr on the machine running Python, including when that machine is a cloud worker. Counts remain remote. Reopening through catalog.mount_datastore checks the source build identity. If that build has changed, choose a new mount directory. Latest-only remote storage cannot guarantee an immutable source during an already-open session; a new catalog.open_datastore call revalidates the current published build.

A fresh mount copies cell and feature metadata and resolves the published analysis artifacts read only, so cytebase.embeddings(analysis_ds) also finds the imported UMAP and analysis_ds.plots.embedding(layout=...) works on the mount. New artifacts you create are written to ./analysis.zarr.

The same search and plotting calls work for larger studies. A Tabula Sapiens plot can be substantially slower and require more memory. Hide its long tissue legend to preserve the plotting area:

# Find the larger atlas in the same catalog.
atlases = catalog.search("tabula sapiens", ready_only=True)

# Open the atlas only when the catalog search returned a match.
if atlases:

    # Open the selected atlas without downloading all counts.
    atlas_ds = catalog.open_datastore(atlases[0]["cytebase_id"])

    # Reuse the atlas's imported UMAP.
    atlas_umap_ref = cytebase.embedding(atlas_ds, "X_umap")

    # Plot atlas tissues without an oversized legend.
    atlas_ds.plots.embedding(
        layout=atlas_umap_ref,
        color_by="tissue",
        legend_loc="none",
        figsize=(8, 8),
    )

Search by exact labels or SQL

search matches words without regard to case. find_datasets matches exact ontology labels. list_terms supplies the available labels in natural order; its counts cover registered datasets, including those that are not ready.

Loading...

Started: 2026-10-12T13:55:52.257667Z | Wall time: 2.318 s

Take an exact tissue label from the selected dataset:

Loading...

Started: 2026-10-12T13:55:54.577908Z | Wall time: 2.229 s

SQL queries run against the verified local catalog. Select just the columns you need and bind values with parameters:

Loading...

Started: 2026-10-12T13:55:56.808009Z | Wall time: 2.122 s

Pass ready_only=False to discover datasets that are still being prepared.

Common issues

  • No matching dataset: check bucket selection, access, and whether the desired version is ready. ready_only=False includes unfinished registrations.

  • Missing embedding: use cytebase.embeddings(ds) to check imported coordinates. entry.source_embeddings() also lists source keys that were not imported.

  • Crowded figure: increase figsize, reduce the number of groups or panels, or hide the legend. The examples use explicit sizes instead of suppressing plotting warnings.

  • Unexpected expression costs: count blocks are remote, and a single-gene request may read a larger storage chunk. Start with a small dataset and a few genes.

  • Writing to a read-only store: use a local mount for analysis that saves results.

  • 429 Too Many Requests: anonymous Hugging Face access allows 500 API requests per 5 minutes per IP address, and opening a store and reading its metadata uses a share of them. Wait for the window to reset and rerun the cell, or sign in with hf auth login. Catalog() then reads with your token, which has a higher limit.

See the CyteBase API reference for the full SDK and Remote stores for mounted analysis mechanics. Saved documentation outputs come from the 2610 release. Rerunning against it reproduces them; newer releases from cytebase.releases() may return different discovery results.