smftools.analysis.compute.read_cache#
Reader/writer utilities for the per-read modification matrix cache.
Two cache backends are supported:
- Zarr cache (recommended)
One Zarr store per run containing all layers. Obs is sorted by
(Barcode, Reference_strand)so any barcode × strand combination can be read as a contiguous slice in ~138 ms regardless of which layer is needed. A companionbarcode_index.jsonmapsbarcode → ref_strand → [start, end]for O(1) slice lookup.Layout:
<run>.zarr/ obs/ # all obs columns var/ # all var columns (reindexed coords, C_site flags, …) layers/ C_site_binary/ C_nucleosome_depleted_region_merged/ …Example:
from smftools.analysis.compute.read_cache import ( open_zarr_cache, load_barcode_index, load_zarr_layer, ) z = open_zarr_cache("cache/260406_run.zarr") index = load_barcode_index("cache/260406_run_index.json") mat = load_zarr_layer(z, index, "NB01", "6B6_top", "C_site_binary")
- Parquet cache (legacy)
One parquet file per barcode × ref_strand × layer.
Layout:
var_info/<ref_strand>_var_info.parquet <barcode>_<ref_strand>/obs_metadata.parquet <barcode>_<ref_strand>/<layer_name>.parquet
Parquet columns are
str(int(TSS_coord)), e.g."-1690". Cast back to int withnp.array(df.columns, dtype=int).
Functions
|
Build a barcode × ref_strand → [start, end] slice index. |
|
|
|
|
|
|
|
Load a barcode index previously saved by |
|
Load a modification matrix layer from the parquet cache. |
|
Load per-read metadata for a barcode × ref_strand pair. |
|
Load var_info for a reference strand. |
|
Load one layer for a barcode × ref_strand pair from a Zarr cache. |
|
Load obs metadata for a barcode × ref_strand pair. |
|
Load the full var DataFrame from a Zarr cache using anndata. |
|
Load var columns directly from the Zarr store — avoids full anndata load. |
|
Open a Zarr store in read-only mode and return the root group. |
|
Resolve an integer barcode number to its string key in a Zarr barcode index. |
|
Write an AnnData to a Zarr cache, sorting obs and optionally subsetting layers. |
|
Return True if both the Zarr store and its index file exist. |
|
Return the conventional index path for a given Zarr store path. |
- smftools.analysis.compute.read_cache.write_zarr_cache(adata, zarr_path, sort_cols=None, layers=None, obs_chunk=512)#
Write an AnnData to a Zarr cache, sorting obs and optionally subsetting layers.
- Return type:
Parameters#
- adataAnnData
In-memory AnnData to write (backed mode not supported — materialise first).
- zarr_pathPath
Destination Zarr store path. Created if it does not exist.
- sort_colslist of str, optional
obs column names to sort by before writing, e.g.
["Barcode", "Reference_strand"]. Sorting ensures contiguous slices for fast barcode-level access. Defaults to no sorting.- layerslist of str, optional
Layer names to include.
Nonewrites all layers. Non-existent layer names are silently skipped.- obs_chunkint
Number of obs (reads) per Zarr chunk along the obs axis.
- smftools.analysis.compute.read_cache.build_barcode_index(zarr_path, barcodes, ref_strands, index_path=None)#
Build a barcode × ref_strand → [start, end] slice index.
Call this immediately after
write_zarr_cache(), passing the sorted obs arrays from the in-memory AnnData (before it goes out of scope). This avoids decoding the obs from the Zarr store, which requires navigating AnnData's categorical encoding.- Return type:
Parameters#
- zarr_pathPath
Path to the Zarr store (used only to determine the default index path).
- barcodesnp.ndarray
Barcode values in sorted order, matching the Zarr obs rows.
- ref_strandsnp.ndarray
Reference strand values in sorted order, matching the Zarr obs rows.
- index_pathPath, optional
Where to save the JSON index. Defaults to
zarr_path.parent / (zarr_path.stem + "_index.json").
Returns#
- dict
{barcode: {ref_strand: [start, end]}}
- smftools.analysis.compute.read_cache.load_barcode_index(index_path)#
Load a barcode index previously saved by
build_barcode_index().- Return type:
- smftools.analysis.compute.read_cache.zarr_index_path(zarr_path)#
Return the conventional index path for a given Zarr store path.
- Return type:
- smftools.analysis.compute.read_cache.zarr_cache_exists(zarr_path)#
Return True if both the Zarr store and its index file exist.
- Return type:
- smftools.analysis.compute.read_cache.open_zarr_cache(zarr_path)#
Open a Zarr store in read-only mode and return the root group.
- smftools.analysis.compute.read_cache.load_zarr_layer(z, index, barcode, ref_strand, layer, pos_mask=None)#
Load one layer for a barcode × ref_strand pair from a Zarr cache.
- Return type:
Parameters#
- zzarr.Group
Open Zarr root group (from
open_zarr_cache()).- indexdict
Barcode index from
load_barcode_index().- barcodestr
e.g.
"NB01".- ref_strandstr
e.g.
"6B6_top".- layerstr
Layer name, e.g.
"C_site_binary".- pos_masknp.ndarray of bool, optional
Boolean position mask to apply after slicing (column filter). Must have length equal to
n_var.
Returns#
- np.ndarray
Float array of shape (n_reads, n_positions) or (n_reads, n_masked_positions).
- smftools.analysis.compute.read_cache.load_zarr_obs(zarr_path, index, barcode, ref_strand)#
Load obs metadata for a barcode × ref_strand pair.
Uses anndata to decode the Zarr obs (handles categorical encoding). This is not on the critical performance path — use
load_zarr_layer()for fast repeated layer access.- Return type:
DataFrame
Parameters#
- zarr_pathPath
Path to the Zarr store.
- indexdict
Barcode index from
load_barcode_index().
Returns#
- pd.DataFrame
obs rows for the selected barcode × ref_strand.
- smftools.analysis.compute.read_cache.load_zarr_var(zarr_path)#
Load the full var DataFrame from a Zarr cache using anndata.
- Return type:
DataFrame
- smftools.analysis.compute.read_cache.load_zarr_var_fast(z, zarr_path)#
Load var columns directly from the Zarr store — avoids full anndata load.
Reads each column array via
zarr.open_array. ~10x faster thanload_zarr_var()for large stores because it bypasses anndata's categorical / sparse decoding overhead.- Return type:
DataFrame
- smftools.analysis.compute.read_cache.resolve_barcode_str(barcode_int, index)#
Resolve an integer barcode number to its string key in a Zarr barcode index.
Tries
NB{n:02d}first (the standard format for most runs), then scans for keys ending in_barcode{n:02d}to handle SQK-style barcodes used by some earlier runs (e.g.SQK-NBD114-24_barcode07).Raises
KeyErrorif no match is found.- Return type:
- smftools.analysis.compute.read_cache.is_cached(cache_root, barcode, ref_strand, layer_name)#
- Return type:
- smftools.analysis.compute.read_cache.load_var_info(cache_root, ref_strand)#
Load var_info for a reference strand.
Returns DataFrame with int TSS-coord index and bool columns C_site, GpC_site.
- Return type:
DataFrame
- smftools.analysis.compute.read_cache.load_obs_metadata(cache_root, barcode, ref_strand)#
Load per-read metadata for a barcode × ref_strand pair.
Returns DataFrame indexed by obs_name with all adata.obs columns plus precomputed max_cigar_del (int).
- Return type:
DataFrame
- smftools.analysis.compute.read_cache.load_layer(cache_root, barcode, ref_strand, layer_name)#
Load a modification matrix layer from the parquet cache.
Returns#
- tuple of (pd.DataFrame, np.ndarray)
DataFrame of shape (n_reads × n_positions) — index is obs_name, columns are
str(int(TSS_coord)), values are float (NaN = no coverage) — and an int array of TSS-centred coordinates matching the DataFrame columns.