pbzarr stores per-base genomic data in Zarr v3. A .pbz collection can hold depth, signal, masks, and other tracks for one sample or many samples.
pbzarr supports:
- fast reads over genomic regions
- one value or many labeled values at each base
- compression across samples or other columns
- parallel calculations with xarray and Dask
- d4, bigWig, and BED imports
The project provides Rust and Python libraries. A command-line tool is planned.
Per-base data often lives in one file per sample. Analysis then spends time opening files and joining results in Python.
pbzarr stores related values in one array. This improves compression and lets array tools calculate across positions and samples at once.
import pbzarr
pbzarr.create_store("depth.pbz")
pbzarr.import_d4(
"depth.pbz",
"depth",
[("brain.d4", "brain"), ("liver.d4", "liver")],
column_dim="sample",
)This creates a depth track with one row per genomic position and one column per sample.
depth = pbzarr.open("depth.pbz/depth")
window = depth.pbz.region("chr1:100000-101000")
brain = depth.pbz.region("chr1:100000-101000", column="brain")
values = window.compute()pbz uses zero-based, half-open coordinates.
peaks = [
("chr1", 100000, 100200),
("chr1", 150000, 150300),
("chr2", 200000, 200150),
]
peak_means = depth.pbz.reduce_regions(peaks, "mean")
result = peak_means.compute()The result has one mean for each peak and sample. Other reductions include sum, min, max, count, std, var, median, and quantile.
Dask keeps reads and calculations lazy until compute(). The computed result must still fit in memory.
Opening a track returns an xarray.Dataset. Opening a collection returns an xarray.DataTree whose children are tracks.
study = pbzarr.open("study.pbz")
depth = study["depth"].to_dataset()
mask = study["mask"].to_dataset()Each track records its own genome. Tracks with matching genomes can be used together.
pbzarr.create_store("signals.pbz")
pbzarr.import_bigwig("signals.pbz", "signal", "sample.bw")
pbzarr.create_store("scores.pbz")
pbzarr.import_bed(
"scores.pbz",
"score",
"sites.bed.gz",
column="score",
dtype="float32",
genome="genome.fai",
)BED imports need a .fai or chromosome-sizes file because BED does not record chromosome lengths.
A .pbz collection is a Zarr v3 directory. Each child directory is a track.
study.pbz/
├── zarr.json
├── depth/
│ ├── zarr.json
│ ├── values
│ ├── offsets
│ ├── contigs
│ └── sample
└── mask/
├── zarr.json
├── values
├── offsets
└── contigs
values holds the data. contigs and offsets map each chromosome to its rows in values. A track with columns also stores their labels.
See the design document for the full file rules and Rust API.
pbzarr is under active development and has not reached version 1.0. The API and file rules may change. Remote writes and variable chunk sizes are planned.
- Rust API
- Design
- d4
- Motivating issues: mask generation, cross-sample compression, and per-base sample statistics