Files
clawhdf5/crates/clawhdf5-py
osobhandClaude Opus 5.5 b43bd2e67f perf(py): read an index list one group of chunks at a time
Each run of consecutive indices was its own uncached hyperslab read, so
a list over a compressed chunked dataset decoded the same chunk once per
run (d[range(0, 200000, 40)] over 20 gzip chunks: 8 s, h5py 0.014 s).
Plan::reads now groups the indices — a group ends only where a whole
chunk holds no selected index, or, unchunked, at a gap over 64 KiB — and
the selected rows are gathered from each group's block in Rust. Now
3.8 ms (h5py 4.1 ms, release, tank). The new test (1-D, 2-D and
contiguous, compared with h5py, 2 s bound) took 5.8 s before.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-26 08:57:16 -05:00
..

clawhdf5-py

crates.io docs.rs

Python bindings for clawhdf5 — a pure-Rust HDF5 library. The package is clawhdf5 (import clawhdf5); it needs numpy and no libhdf5.

Install

Not on PyPI yet. Build it into a virtualenv with maturin:

pip install maturin numpy
cd crates/clawhdf5-py
maturin develop --release
python -c "import clawhdf5; print(clawhdf5.__version__)"

Reading

The read API follows h5py:

import numpy as np
import clawhdf5

with clawhdf5.File("data.h5", "r") as f:
    f.keys(), f["group"].items(), "group/data" in f
    ds = f["group/data"]           # or f["/group/data"], f["group"]["data"]
    ds.shape, ds.dtype, ds.attrs["units"]
    ds[10:20, ::2]                 # only the selected elements are read
    ds[-1], ds[..., 0], ds[[1, 4, 7]]
    np.asarray(ds)
    f["table"]["id"]               # a compound field
  • Dataset.dtype is the numpy dtype h5py reports: integers and IEEE floats of every width in either byte order, bool, enums (with dtype.metadata['enum']), complex, S<n> fixed strings, object for variable-length strings (bytes values) and sequences (array values), V<n> opaque, array types, and compounds as structured dtypes. Other types raise TypeError.
  • Keys are h5py's: integers, slices with a positive step, ..., one increasing list of integers, compound field names. Each maps onto a hyperslab selection. None, negative steps and boolean masks are refused with h5py's errors.
  • The bytes the library reads become the numpy array's buffer without a copy, and the read runs with the GIL released, so threads read in parallel.
  • Attributes return what h5py returns; clawhdf5.Empty stands for a null dataspace (h5py's Empty).

Writing

clawhdf5.File(path, "w") with create_dataset(name, data=array, chunks=..., compression="gzip"), create_group and attrs[...] = ... writes float64, float32, int64, int32 and uint8 arrays; the file is written on close().

Tests

pip install pytest h5py
pytest crates/clawhdf5-py/tests

tests/test_read_vs_h5py.py compares every read with h5py on a file h5py writes. scripts/ci-test.sh builds the wheel and runs these in CI.

License

MIT