ALL - IMPROVEMENT - Self-describing HDF5 metadata (issue #226, PR B) - #364
ALL - IMPROVEMENT - Self-describing HDF5 metadata (issue #226, PR B)#364logan-nc wants to merge 2 commits into
Conversation
…dims, scales) Every gpec.h5 dataset outside Input/ and the debug-only GalerkinIntegration/Match/ now answers "what is this, in what units, plotted against what" without opening the source, readable natively by h5py/xarray/HDFView: - New Utilities.HDF5Annotations: annotate!(parent, table) applies per-writer path => (; long_name, units, dims) tables post-write (skipping absent paths); make_scale!/attach_scale! wrap the H5DS dimension-scale API (netCDF-4 coordinate mechanism) with Julia-axis -> C-dim index translation; write_root_attrs! stamps schema_version=2.0, Conventions=GPEC-HDF5-2.0, references, title, date_created. - Table-driven, not per-write-call: writers are untouched except one annotate call at the end of each (src/HDF5Schema.jl for the main writer; tables live next to write_galerkin!, the PE writer, KineticForces/Output.jl, and Tearing/Runner/HDF5Output.jl). ~340 dataset annotations total. - Coordinate datasets (psi grids, rational-surface psi, geometry xs/ys) are marked as HDF5 Dimension Scales and attached to the profiles sharing the axis; a greppable "dims" attribute mirrors the scales in Julia axis order. - Attribute wording/units audited by the fortran-physics-reviewer against the layer/field-reconstruction sources; 27 corrections applied (J-weighted field units T*m^2, Q-normalization time vs resistive-kink time, island half-width vs full width, omega_Hz actually rad/s, etc.). - runtests_h5_schema.jl now enforces the contract: long_name+units on every non-exempt dataset, dims on rank >= 2 arrays, root attrs present, scales attached; docs/development/hdf5-conventions.md gains the metadata contract. Attributes are invisible to the rerun leaf-walk and the regression extractor: no tracked value moves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129rSTCmYJDBbcH9khHqYnz
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129rSTCmYJDBbcH9khHqYnz
|
@d-burg please review your outputs carefully here. In particular, the PR overview points out:
It looks like you also have a |
|
@d-burg is voluntold to do the full diff review on this one since he has some specific things called out. |
Summary
PR B of the two stacked PRs closing #226 (stacked on #363 — review/merge that first; this diff is additive on top of it). Every
gpec.h5dataset now answers "what is this, in what units, plotted against what" without opening the source — netCDF-grade, natively readable by h5py/xarray/HDFView.What every dataset gets
long_name— plain-text physics description.units— SI strings;"1"for dimensionless (CF convention); normalized quantities state the normalization in the long_name.dims(rank ≥ 2) — greppable axis-name string in Julia (column-major) order, e.g."(psi, mode)".h5ds_set_scaleand attached per axis with labels: h5py.dims, xarray, and HDFView resolve axes natively (verified with h5py:DIMENSION_LIST+ labels present).schema_version="2.0"(readers get a dispatch point for future breaking changes),Conventions="GPEC-HDF5-2.0",references,title,date_created(ISO 8601 UTC).Exempt (whitelisted in the enforcement test):
Input/**(raw rerun snapshot) andGalerkinIntegration/Match/**(debug-only, drop pending Galerkin-owner decision — no point hand-curating ~15 entries for it).Mechanism — one deviation from the approved plan wording
The plan said "route all writers through a
write_annotated!helper". Implemented instead as table-driven post-hoc annotation: each writer keeps apath => (; long_name, units, dims)table next to it and applies it with oneannotate!call after its datasets are written (Utilities.HDF5Annotations+src/HDF5Schema.jlfor the main writer). Same contract, enforced identically by the schema test — but the writer bodies are untouched, keeping this PR genuinely low-conflict with #354/#345/#339/#318 and handling dynamic writes (per-field equilibrium loop, per-method KF groups) naturally. ~340 annotation entries total.Physics review
The tables were audited by the fortran-physics-reviewer agent against the layer/field-reconstruction sources and the Fortran gpout.f attribute crib; 27 corrections applied, including: J-weighted contravariant fields are
T*m^2(χ₁-weighted), notT;Tearing/PerSurface/taukis the Q-normalization time S^⅓·τ_H, not a resistive-kink time;island_width_sqis the squared half-width;Roots/omega_Hzis actually an angular frequency (rad/s) — the dataset name is a misnomer, flagged here rather than renamed (renaming is a breaking change; candidate for a future schema bump);delta_nis the Δ′-normalization S^⅓/r_s in 1/m. Reviewers: the covariant-component units (T*m,m^2) were settled by dimensional analysis — worth a second look.Enforcement
test/runtests_h5_schema.jlnow asserts on a full-run output:long_name+unitson every non-exempt dataset,dimson every rank ≥ 2 array, root attributes present, and the ψ_N scale attached (28/28 passing). Additional metadata walks were run on the DIIID SLAYER, Solovev kinetic-NTV, and DIIID gal-resistive decks — zero violations. When adding a dataset, add its table entry in the same commit or the test fails — this is the anti-drift teeth #226 asked for.Notes
h5ds_set_labelwrapper mis-types the Cconst char*asRef{UInt8}; we pass a NUL-terminated byte buffer.Dates(stdlib) added to Project.toml fordate_created.LocalStability/di/drhave no stored coordinate grid to attach (their ψ grid isn't written); theirdimsattribute documents the axis name only.Regression harness (mandatory gate) — zero movement
regress --cases <all 12> --refs develop,local: identical table to PR A — every surviving quantity OK at 0.0e+00 (48/21/15/16/10/4+4 pre-existing N/A/14/14/6/5/4/4). Attributes are invisible to the extractor and the rerun leaf-walk, as designed; the bit-for-bit rerun round-trip test passes with annotations present.Other verification
Full schema test 28/28; SLAYER runner, coils, fullruns, rerun-from-h5 all pass; docs build clean (new
HDF5Annotationsautodocs covered); h5py external check confirms scales/attrs.This PR must not be merged until a third-party human reviewer has approved it — non-negotiable project policy. Merge order: #363 first, then this.
🤖 Generated with Claude Code
https://claude.ai/code/session_0129rSTCmYJDBbcH9khHqYnz