CONTRIBUTING.md asks for a new dependency, especially a non-Rust one, to be raised before the PR. This is that issue. The decision is yours; I am laying out the options rather than arguing for one, though I do say at the end which I would pick and why.
What it is for
cellranger count writes its matrices twice: once as MEX (raw_feature_bc_matrix/, three files) and once as HDF5 (raw_feature_bc_matrix.h5). #XXX gets the MEX side right, down to the directory names and the -1 barcode suffix, and against a real CellRanger 10.0.0 run the raw barcode sets now match exactly, 200 of 200. The .h5 files are the remaining piece.
They matter because a good deal of tooling reads only the .h5: scanpy.read_10x_h5, Seurat's Read10X_h5, and anything built on cellranger's own loaders. The file is small and its layout is documented by 10x:
/matrix/barcodes [n_cells] string
/matrix/data [nnz] int32
/matrix/indices [nnz] int64
/matrix/indptr [n_cells+1] int64
/matrix/shape [2] int32
/matrix/features/{id, name, feature_type, genome, _all_tag_keys}
CSC, chunked, gzip-filtered. That is the whole file.
Option A — hdf5-metno, dynamically linked
|
|
| Crate |
hdf5-metno 0.14.0 over hdf5-metno-sys 0.12.1 |
| Upstream |
https://github.com/metno/hdf5-rust (maintained fork of the dormant hdf5 crate) |
| Licence |
MIT OR Apache-2.0 on both |
| Build deps pulled in |
pkg-config, regex, serde, serde_derive, libloading, winreg |
| Runtime deps pulled in |
libc, parking_lot |
| System requirement |
libhdf5 must already be installed |
The build probes for a system libhdf5 with pkg-config (and the registry on Windows). That is the part I would not want to sign off casually: rustar-aligner is published to crates.io, so cargo install rustar-aligner would start failing on any machine without libhdf5 development headers. It also has to be installed on all five CI runners, including Windows MSVC, where HDF5 packaging is the least pleasant.
serde and regex as build dependencies of a -sys crate are also worth a look before agreeing to it.
Option B — hdf5-metno with features = ["static"]
Pulls in hdf5-metno-src 0.10.2, which vendors the HDF5 C source and builds it with cmake as a build dependency. Licence on that crate reads as non-standard on crates.io — it is HDF5's own BSD-style licence, which is permissive, but it is a third licence text to carry in LICENSES/.
No system library, so cargo install keeps working. The cost is cmake on the build path for every user and every CI runner, and a multi-minute C build on a cold cache for a feature that writes one small file.
Option C — write the file in-tree, no dependency
The 10x .h5 uses a small, fixed subset of HDF5: one group, nine datasets, one filter. Writing that subset is not out of reach, and it is the same reasoning that put the Smith-Waterman engine in-tree in #148 rather than binding a C library.
I want to be honest about the risk, because it cuts the other way here. HDF5 is a container format, not a serialisation: a conformant file needs a superblock, object headers with correctly laid-out messages, a B-tree and local heap for the group's links, and a chunk index for each chunked dataset. "It opens in h5py on my machine" is a much weaker guarantee than a passing test. I would want the acceptance criterion to be a round-trip against real readers (h5py, scanpy.read_10x_h5) in the differential harness, not a unit test asserting our own bytes.
Ballpark: 1000-1500 lines, most of it format plumbing, plus that external round-trip. Materially more work than Options A or B, and the failure mode is subtler.
Option D — do not write .h5 at all
The MEX output from #XXX is complete and loads in scanpy and Seurat. Anyone needing the .h5 can convert:
import scanpy as sc
sc.read_10x_mtx("outs/raw_feature_bc_matrix").write("raw_feature_bc_matrix.h5ad")
That is .h5ad, not 10x .h5 — near enough for scanpy users, not for a tool that specifically wants CellRanger's file. Note also that #1 asks for AnnData output, which would land in the same place and has the same dependency question underneath it.
My reading
I would not take Option A: a crates.io-published binary that fails to install without a system C library is a real cost paid by every user, in exchange for one optional output file.
Between B, C and D, I would ask what the .h5 is actually for. If it is "so scanpy users can load our output", D already works today and B is not worth cmake. If it is "so tools that read only CellRanger's .h5 work unchanged", then it has to be a real 10x .h5, and the question is whether the maintenance you prefer is a cmake build dependency (B) or ~1200 lines of format code that only we maintain (C).
If you want it, I would go with B, static only, so cargo install keeps working, and gated behind a Cargo feature that is off by default so the ordinary build is untouched. I will happily do C instead if you would rather keep the dependency tree pure — say which and I will build it. What I would not do is start either one before you have picked.
CONTRIBUTING.mdasks for a new dependency, especially a non-Rust one, to be raised before the PR. This is that issue. The decision is yours; I am laying out the options rather than arguing for one, though I do say at the end which I would pick and why.What it is for
cellranger countwrites its matrices twice: once as MEX (raw_feature_bc_matrix/, three files) and once as HDF5 (raw_feature_bc_matrix.h5). #XXX gets the MEX side right, down to the directory names and the-1barcode suffix, and against a real CellRanger 10.0.0 run the raw barcode sets now match exactly, 200 of 200. The.h5files are the remaining piece.They matter because a good deal of tooling reads only the
.h5:scanpy.read_10x_h5, Seurat'sRead10X_h5, and anything built oncellranger's own loaders. The file is small and its layout is documented by 10x:CSC, chunked, gzip-filtered. That is the whole file.
Option A —
hdf5-metno, dynamically linkedhdf5-metno0.14.0 overhdf5-metno-sys0.12.1hdf5crate)MIT OR Apache-2.0on bothpkg-config,regex,serde,serde_derive,libloading,winreglibc,parking_lotThe build probes for a system libhdf5 with
pkg-config(and the registry on Windows). That is the part I would not want to sign off casually: rustar-aligner is published to crates.io, socargo install rustar-alignerwould start failing on any machine without libhdf5 development headers. It also has to be installed on all five CI runners, including Windows MSVC, where HDF5 packaging is the least pleasant.serdeandregexas build dependencies of a-syscrate are also worth a look before agreeing to it.Option B —
hdf5-metnowithfeatures = ["static"]Pulls in
hdf5-metno-src0.10.2, which vendors the HDF5 C source and builds it withcmakeas a build dependency. Licence on that crate reads asnon-standardon crates.io — it is HDF5's own BSD-style licence, which is permissive, but it is a third licence text to carry inLICENSES/.No system library, so
cargo installkeeps working. The cost iscmakeon the build path for every user and every CI runner, and a multi-minute C build on a cold cache for a feature that writes one small file.Option C — write the file in-tree, no dependency
The 10x
.h5uses a small, fixed subset of HDF5: one group, nine datasets, one filter. Writing that subset is not out of reach, and it is the same reasoning that put the Smith-Waterman engine in-tree in #148 rather than binding a C library.I want to be honest about the risk, because it cuts the other way here. HDF5 is a container format, not a serialisation: a conformant file needs a superblock, object headers with correctly laid-out messages, a B-tree and local heap for the group's links, and a chunk index for each chunked dataset. "It opens in
h5pyon my machine" is a much weaker guarantee than a passing test. I would want the acceptance criterion to be a round-trip against real readers (h5py,scanpy.read_10x_h5) in the differential harness, not a unit test asserting our own bytes.Ballpark: 1000-1500 lines, most of it format plumbing, plus that external round-trip. Materially more work than Options A or B, and the failure mode is subtler.
Option D — do not write
.h5at allThe MEX output from #XXX is complete and loads in scanpy and Seurat. Anyone needing the
.h5can convert:That is
.h5ad, not 10x.h5— near enough for scanpy users, not for a tool that specifically wants CellRanger's file. Note also that #1 asks for AnnData output, which would land in the same place and has the same dependency question underneath it.My reading
I would not take Option A: a crates.io-published binary that fails to install without a system C library is a real cost paid by every user, in exchange for one optional output file.
Between B, C and D, I would ask what the
.h5is actually for. If it is "so scanpy users can load our output", D already works today and B is not worthcmake. If it is "so tools that read only CellRanger's.h5work unchanged", then it has to be a real 10x.h5, and the question is whether the maintenance you prefer is acmakebuild dependency (B) or ~1200 lines of format code that only we maintain (C).If you want it, I would go with B,
staticonly, socargo installkeeps working, and gated behind a Cargo feature that is off by default so the ordinary build is untouched. I will happily do C instead if you would rather keep the dependency tree pure — say which and I will build it. What I would not do is start either one before you have picked.