PBZ (Per-Base Zarr) — a Zarr v3 convention for per-base genomic data
Project description
Overview
pbzarr is a Zarr v3 convention for storing per-base resolution genomic data — read depths, methylation, boolean masks, and other cohort-shaped per-base values. Built as an alternative to D4 and bigWig that compresses cleanly across samples and integrates with the xarray / zarr ecosystem.
This repo provides:
pbzarr(Rust crate) — store layout, metadata, region I/O. Delegates array storage and compression tozarrs. This is the only crate published to crates.io.pbzarr-readers(Rust crate, unpublished) — input-format readers (currently d4). Kept separate so the core crate stays free of git dependencies and remains publishable. d4 import is reachable from the Python wheel or when building from this repo, not from the crates.iopbzarrcrate.pbzarr(Python wheel) — PyO3 binding forimport_d4plus pure-Pythoncreate_store/create_trackoverzarr-python. Read API is an xarray accessor.
The on-disk format is the same; both libraries write .pbz stores that the other can read.
Install — Rust
[dependencies]
pbzarr = "0.1"
Install — Python
pip install pbzarr # once published on PyPI
# or from source: pixi run install-wheel
The Python wheel pulls in zarr>=3, xarray>=2024.10, numpy>=2.
Quickstart — Python
import pbzarr
# 1. Create the store
pbzarr.create_store(
"out.pbz",
contigs=["chr1", "chr2"],
contig_lengths=[248_956_422, 242_193_529],
coordinate_space="GRCh38",
)
# 2. Register a 1D scalar track
pbzarr.create_track("out.pbz", track="mask", dtype="bool")
# 2b. Or a 2D cohort track
pbzarr.create_track(
"out.pbz",
track="depth",
dtype="int32",
columns=["A", "B", "C"],
column_dim="sample",
)
# 3a. Bulk-import from d4 (PyO3 -> Rust)
pbzarr.import_d4(
"out.pbz",
track="depth",
sources=[("/data/A.d4", "A"), ("/data/B.d4", "B"), ("/data/C.d4", "C")],
)
# 3b. Or write arbitrary numpy data via zarr-python
import zarr, numpy as np
g = zarr.open_group("out.pbz", mode="r+")
g["chr1/mask"][:] = np.random.rand(248_956_422) > 0.5
Read with xarray
import pbzarr
dt = pbzarr.open("out.pbz") # xr.DataTree
dt.pbz.tracks # ['depth', 'mask']
dt.pbz.region("chr1:1000-2000") # xr.Dataset (one contig, sliced)
dt.pbz.region("chr1:1000-2000", track="depth") # xr.DataArray
dt.pbz.region("chr1:1000-2000", track="depth", column="A") # 1D DataArray
The .pbz accessor on xr.DataTree is registered when you import pbzarr. Regions use 0-based, half-open coordinates (chr1:1000-2000 is [1000, 2000)).
Note: Python
create_store/create_trackconsolidate metadata after each call. Stores written by the Rust crate don't consolidate yet, sopbzarr.open(...)will emit a benignRuntimeWarningfor those; runzarr.consolidate_metadata(path)once to silence.
Quickstart — Rust
use ndarray::Array2;
use pbzarr::io::Dtype;
use pbzarr::import::Config;
use pbzarr::{Contig, Genome, PbzStore, Region, TrackConfig};
// d4 import lives in the unpublished pbzarr-readers crate (it carries a git
// dependency on d4); depend on this repo by path or git to use it.
use pbzarr_readers::d4::{from_d4, D4Source};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let genome = Genome::new(vec![
Contig { name: "chr1".into(), length: 248_956_422 },
Contig { name: "chr2".into(), length: 242_193_529 },
])?;
let mut store = PbzStore::create("out.pbz", genome, Some("GRCh38".into()))?;
// 1D scalar track
store.create_track("mask", TrackConfig::new(Dtype::Bool))?;
// 2D cohort track; d4 import requires int32
store.create_track(
"depth",
TrackConfig::new(Dtype::I32)
.columns(vec!["A".into(), "B".into(), "C".into()])
.column_dim("sample"),
)?;
// Import from d4
from_d4(
&store,
"depth",
&[
D4Source { path: "/data/A.d4".into(), sample_label: Some("A".into()) },
D4Source { path: "/data/B.d4".into(), sample_label: Some("B".into()) },
D4Source { path: "/data/C.d4".into(), sample_label: Some("C".into()) },
],
Config::default(),
)?;
// Read a region
let chr1 = store.genome().id("chr1").unwrap();
let region = Region { contig: chr1, start: 1_000, end: 2_000 };
let data = store.track("depth").unwrap().read_region::<i32>(®ion)?;
let arr2: Array2<i32> = data.into_dimensionality::<ndarray::Ix2>()?;
let _ = arr2;
Ok(())
}
Format at a glance
- Layout: contig-major Zarr v3 store with
<contig>/<track>arrays. Position is the first axis; an optional column dim (default name"column", often overridden to"sample") is the second. - Tracks: 1D for scalar (e.g., masks), 2D for cohort (e.g., per-sample depths). Rank-faithful on disk.
- Coordinates: 0-based, half-open.
- Compression: Blosc(zstd-5, byte-shuffle) on every data array.
- Coord arrays: cohort tracks write per-contig 1D string arrays at
<contig>/<column_dim>listing the column labels; xarray promotes them to coordinates automatically.
For the full design see docs/DESIGN.md.
Links
- Rust API docs: docs.rs/pbzarr
- Design doc:
docs/DESIGN.md - Motivating issues: d4-format#82, d4-format#64, clam#25
Development note
The per-base Zarr format that pbzarr standardizes was first prototyped by hand in clam, where the initial concepts (the contig-major layout, cohort-shaped tracks, and the zarr/ndarray I/O path) were fleshed out before AI tooling was introduced. pbzarr lifts those concepts into a dedicated, spec-driven library.
From that point, development of pbzarr was heavily assisted by Claude (Anthropic), accelerating the library implementation, d4 import, tests, and documentation. The architecture, domain knowledge, and direction remain the author's own; Claude was used as an accelerant, not an author.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pbzarr-0.2.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pbzarr-0.2.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.3 MB
- Tags: CPython 3.11+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5bb176796be646ce440ddb512bb68016e8ac717962b92cc7d13d0576d77ee170
|
|
| MD5 |
372cb91411d4322773132fb720597cc6
|
|
| BLAKE2b-256 |
f9d2ef44e7331a19362f854b03b411e98fad6e56c802af7c5cf2f9c2d0891350
|
Provenance
The following attestation bundles were made for pbzarr-0.2.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on pbzarr/pbzarr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pbzarr-0.2.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
5bb176796be646ce440ddb512bb68016e8ac717962b92cc7d13d0576d77ee170 - Sigstore transparency entry: 1861058422
- Sigstore integration time:
-
Permalink:
pbzarr/pbzarr@0ae85b13e807e899512e4de9c1f2cee6ffbc36d5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/pbzarr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0ae85b13e807e899512e4de9c1f2cee6ffbc36d5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pbzarr-0.2.1-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: pbzarr-0.2.1-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 5.8 MB
- Tags: CPython 3.11+, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b70d56a85f54330f3f3ba3e1558170f454f624882d84c6bca218d833dc9ecb26
|
|
| MD5 |
7863231dd3e5d4f200e2758acf92f43b
|
|
| BLAKE2b-256 |
279e23d3f488ef7af6b3009b858da96685cc823dd17c290c76aa42ae1dccea84
|
Provenance
The following attestation bundles were made for pbzarr-0.2.1-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:
Publisher:
release.yml on pbzarr/pbzarr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pbzarr-0.2.1-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl -
Subject digest:
b70d56a85f54330f3f3ba3e1558170f454f624882d84c6bca218d833dc9ecb26 - Sigstore transparency entry: 1861058616
- Sigstore integration time:
-
Permalink:
pbzarr/pbzarr@0ae85b13e807e899512e4de9c1f2cee6ffbc36d5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/pbzarr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0ae85b13e807e899512e4de9c1f2cee6ffbc36d5 -
Trigger Event:
push
-
Statement type: