Numbers, API names, feature defaults and PR references checked against CONFORMANCE.md, BENCHMARKS.md, CHANGELOG.md, the code and git history. - int8 index figures (1.74x memory, 1.63x QPS) carry the dates git gives them (2026-09-19/20, machine not recorded, not re-run) instead of none; the Pi 5 1.18x carries 2026-09-21. - BENCHMARKS headline: the libhdf5 chunked-write figure is the newest measurement (35x, 2026-09-23), not 45.3x (2026-08-03). - Conformance counts follow the 2026-09-28 run (1 our-error, 2 ref-bug) in conformance/README.md, ROADMAP.md and CLAUDE.md, with a pointer to the bad_nbit_parms_walk.h5 flip. - README: LZ4 is opt-in; the browser refuses reference/opaque/bitfield/ time datasets too; zlib-rs byte-identity scoped to what was measured; macOS default links the system libz for inflate. - Crate READMEs: system-zlib-decompress does something (macOS), SweepDetector lives in prefetch, checkpoint after more than 500 WAL entries, NetCDF-4 unlimited-dimension size warning. - agent-memory.md: string-dataset compression threshold, agents-md prints Markdown, float16 file sizes linked to their study. - known-issues.md: contiguous selection reads, 1.21x vs h5py threads. - docs/README.md, USE_CASES.md, ROADMAP.md, CLAUDE.md: range-read milestones M0-M5 and PRs #17-#19, missing README rows, CLI keygen/verify, dated figures, fast-math is not BLAS. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
54 lines
2.4 KiB
Markdown
54 lines
2.4 KiB
Markdown
# clawhdf5-netcdf4
|
|
|
|
Read NetCDF-4 files in pure Rust. NetCDF-4 files are HDF5 files with
|
|
conventions for dimensions, coordinate variables and attributes; this crate
|
|
reads them through the [`clawhdf5`](../clawhdf5/README.md) facade, with no
|
|
libnetcdf or libhdf5. Read-only: NetCDF-3 (classic) files are not HDF5 and
|
|
are not supported.
|
|
|
|
Not on crates.io yet; depend on it from git:
|
|
|
|
```toml
|
|
[dependencies]
|
|
clawhdf5-netcdf4 = { git = "https://git.redclaw.dev/quantumclaw/clawhdf5" }
|
|
```
|
|
|
|
## Usage
|
|
|
|
```rust,no_run
|
|
use clawhdf5_netcdf4::NetCDF4File;
|
|
|
|
let nc = NetCDF4File::open("climate.nc")?;
|
|
for dim in nc.dimensions()? {
|
|
println!("{}: {} (unlimited = {})", dim.name, dim.size, dim.is_unlimited);
|
|
}
|
|
let mut temp = nc.variable("temperature")?;
|
|
let dims: Vec<&str> = temp.dimensions().iter().map(|d| d.name.as_str()).collect();
|
|
println!("{:?} over {:?}", temp.shape()?, dims);
|
|
let cf = temp.cf_attributes()?;
|
|
println!("units: {:?}", cf.units);
|
|
// scale_factor/add_offset applied; _FillValue and missing_value become NaN
|
|
let values: Vec<f64> = temp.read_f64()?;
|
|
# Ok::<(), clawhdf5_netcdf4::Error>(())
|
|
```
|
|
|
|
## API
|
|
|
|
| Item | What |
|
|
|---|---|
|
|
| `NetCDF4File` | `open`, `from_bytes`, `dimensions`, `variables`, `variable`, `global_attrs`, `group`, `group_names`, `nc_properties`, and `hdf5_file` for the underlying `clawhdf5::File` |
|
|
| `NetCDF4Group` | the same for a sub-group (`dimensions`, `variables`, `attrs`, nested `group`) |
|
|
| `Variable` | `name`, `shape`, `dimensions`, `nc_type`, `is_coordinate`, `attrs`, `cf_attributes`; `read_f64` (CF scale/offset and fill applied), `read_raw_f32`/`_f64`/`_i32`/`_i64`/`_u64`, `read_string`, `read_raw` |
|
|
| `Dimension` | `name`, `size`, `is_unlimited` (an unlimited dimension's `size` is wrongly 0 when it holds records; use the variables' shapes — [known issue](../../docs/known-issues.md#netcdf-4-an-unlimited-dimension-reports-size-0)) |
|
|
| `CfAttributes` | CF convention attributes: `units`, `long_name`, `standard_name`, `fill_value` (`_FillValue`), `missing_value`, `scale_factor`, `add_offset`, `valid_range`, `calendar`, `axis` |
|
|
| `NcType` | the NetCDF type of a variable |
|
|
|
|
No cargo features. Tests compare against files written by netCDF4-python
|
|
(`tests/interop_tests.rs`; the CI job requires them with
|
|
`CLAWHDF5_REQUIRE_INTEROP=1`). What the HDF5 reader underneath cannot
|
|
read is listed in [`docs/known-issues.md`](../../docs/known-issues.md).
|
|
|
|
## License
|
|
|
|
MIT
|