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.

Extending CyteArc with custom analyses

CyteArc’s memory limits do not prevent you from using an external analysis method. You can read its neighborhood graphs, process count blocks, and add cell-level results through public APIs. When another tool needs its own data format, export the cells and genes that method requires.

This tutorial calculates a graph statistic, streams counts without loading the complete matrix, creates a custom cell selection, and exports that selection to AnnData or a separate CyteArc store.

Import an existing store

The prepared PBMC store supplies counts and a saved example run labeled docs_default. Open the downloaded store directly because the examples write custom artifacts and metadata, then reuse the run’s frozen selection, graph, feature selection, and UMAP. The prepared store’s active I matches the run’s analysis selection. See Build a neighborhood graph stage by stage to build a graph by hand.

Started: 2026-10-11T18:54:43.100120Z | Wall time: 3.037 s

Open the downloaded store and its saved analysis.

DataStore has 3948 (5025) cells with 1 assays: RNA Cell metadata: 'I', 'ids', 'names', 'RNA_G2M_score', 'RNA_S_score', 'RNA_UMAP1', 'RNA_UMAP2', 'RNA_cell_cycle_phase', 'RNA_clusters', 'RNA_doublet_score', 'RNA_leiden_cluster', 'RNA_nCounts', 'RNA_nFeatures', 'RNA_paris_cluster', 'RNA_percentMito', 'RNA_percentRibo' RNA assay has 33538 features and following metadata: 'I', 'ids', 'names', 'dropOuts', 'feature_type', 'genome', 'nCells'

Started: 2026-10-11T18:54:46.139489Z | Wall time: 5.169 s

Calculate from the graph

Suppose an external method needs a measure of how strongly each cell connects to its neighbors. graph.load returns the selected neighborhood graph as a SciPy CSR matrix. Summing each row gives that cell’s total edge weight in the symmetric graph: cells with larger sums have stronger weighted connections in this particular graph. This is a graph statistic, not a biological confidence score or an automatic quality-control rule.

{'cells': 3948, 'edges': 64990, 'customGraphStrength mean': 8.832276344299316}

Started: 2026-10-11T18:54:51.310527Z | Wall time: 0.117 s

The insert writes one value per active cell in graph row order. The summary shows the graph size and the mean of the new column.

PBMC UMAP colored by a custom weighted graph-strength statistic. Higher values appear as scattered cells across several clusters.

Started: 2026-10-11T18:54:51.429243Z | Wall time: 1.097 s

The plot asks where cells have stronger or weaker weighted connectivity in this specific graph. Rebuilds with another feature set or neighbour count need a new statistic.

Stream count blocks

A custom calculation can stay within a small memory budget by processing one count block at a time. Avoid .compute() on a matrix that may exceed memory. Select the frozen run’s cells and highly variable genes before streaming, then keep only the small per-cell results from each block. Here we count detected HVGs per active cell:

{'selected cells': 3948, 'selected genes': 500}

Started: 2026-10-11T18:54:52.528527Z | Wall time: 0.269 s

Count detected genes one block at a time.

3948

Started: 2026-10-11T18:54:52.799586Z | Wall time: 0.455 s

Collect the per-cell results and save them in metadata.

{'cells': 3948, 'customDetectedHVGs mean': 123.48024316109422, 'customDetectedHVGs max': 250}

Started: 2026-10-11T18:54:53.256759Z | Wall time: 0.029 s

stream_blocks preserves row order. Because active I is the frozen run selection, inserting with that key keeps each streamed value aligned with its metadata row. The summary checks that every streamed cell received a detection count.

Create custom selections

A Boolean cell column can become a cell_key. Selecting cells this way does not delete their counts: the selection controls which rows an operation reads, while the original store remains available for a different selection later. Use fill_value=False when the new key is defined only for currently active cells: the inactive cells then hold False. Without it they are recorded as missing, which a key never selects either. Here we keep cells above the lowest quarter of graph strength as an example of making a selection. This is an illustration of the API, not a recommended quality-control filter:

{'selected cells': 2961, 'active cells': 3948}

Started: 2026-10-11T18:54:53.287760Z | Wall time: 0.019 s

Paired PBMC UMAPs show the number of detected highly variable genes and a Boolean selection excluding the lowest quarter of graph-strength values.

Started: 2026-10-11T18:54:53.309141Z | Wall time: 0.529 s

The first panel checks where the streamed count statistic varies. The second shows the lower-quartile graph-strength exclusion created from the same active cell order.

Pass a small selection to another tool

To pass a selection to a tool such as Scanpy, use to_anndata. It creates an in-memory AnnData object, so select the cells and genes you need before materializing it. Here we export the custom cell selection and a six-gene marker panel:

((2961, 6), ['ENSG00000167286', 'ENSG00000156738', 'ENSG00000170458', 'ENSG00000090382', 'ENSG00000105374', 'ENSG00000115523'])

Started: 2026-10-11T18:54:53.841484Z | Wall time: 1.130 s

to_anndata drops unselected features. It indexes var by gene ids (Ensembl here); gene symbols stay in var["names"]. So adata.var_names after feature_names=panel_genes lists ids, not the panel symbols. Check adata.var["names"] when you need the symbols. Omit feature_names to include every feature, provided the resulting AnnData fits in memory. See Import and export for H5AD and Matrix Market export, and Explore a remote dataset when the count source itself must remain remote.

Write a selected CyteArc store

Use SubsetZarr when the next analysis should stay in CyteArc. It writes only the selected cells while retaining every feature in the listed assays. This differs from the six-gene AnnData above: the resulting store can support analyses using a new feature set.

{'exported cells': 2961, 'retained genes': 33538}

Started: 2026-10-11T18:54:54.975546Z | Wall time: 2.732 s

Choose a persistent destination instead of TemporaryDirectory when you want to keep the subset after the notebook session.

Extension boundary

Direct arbitrary artifact writing is not a stable public extension API. Do not mutate ds.z, ds.zw, _matrix_z, or other private storage attributes from analysis code. Those objects expose implementation layout and can change as CyteArc changes.

Use public metadata insertion, result-returning methods, graph loading, block streams, and export APIs. Pipeline callbacks provide read-only execution events; their contract is documented in Analysis pipeline API reference.