CLI reference¶
Exit codes are Unix-conventional: 0 success, 1 a handled error or a
failed check, 2 a usage error. Every inspection command takes --json and
writes a machine-readable document to stdout.
Inspecting¶
medh5 info¶
Grids, images, annotations, coverage, quality, codecs and content id.
Collections. info, tree, verify, timeline and track all take a
.medh5c shard with --key, which names one sample inside it — a member of a
shard is a sample root, so every per-sample view works on one. info and
tree without a key describe the shard itself; the commands that report on one
sample ask for a key and list the ones available.
medh5 tree¶
An annotated object listing — h5ls with each object's role in the spec.
medh5 validate¶
Check against the specification. --level is structural, semantic
(default), integrity or strict; each includes the ones before it.
--profile overrides the profiles the file declares, so you can hold a file to
det even if it does not claim it. Diagnostics carry stable codes (spec §15.2).
$ medh5 validate case.medh5 --level strict
case.medh5: FAILED [strict] profiles=core,seg (1 errors, 0 warnings)
ERROR E102 grids/ct: `direction` is not orthonormal to 1e-4
medh5 verify¶
Recompute every object's digest and the root content_id. --partial limits
it to named objects — useful when you only want to know whether one image
changed.
In a file that declares a content_id, a dataset inside a grid, image,
annotation or transform that carries no digest fails the check (UNSIGNED):
the root covers the digests present, so an undigested dataset added to an
object — instance_ids on a boxes annotation, say — changes what it means
without changing the root. The writer digests every dataset, so none of its
files has one.
medh5 fix¶
With no flags: diagnose and change nothing. Exit 1 if anything needs attention.
--rebuild-index recomputes stale sampling indices. Ordinary repair.
--rewrite-digests is not repair. A digest that no longer matches is evidence
that the bytes changed, and recomputing it destroys the evidence. It therefore
requires --reason, which is recorded in the file's provenance along with the
fact that the tool did not verify the content it just re-attested. --by names
who made the change, in the same record.
Longitudinal¶
medh5 timeline¶
Timepoints, their intervals, and what belongs to each visit.
medh5 track¶
Join instance ids across visits: per object, its volume at each timepoint, the
relative change, and whether it is present, resolved or unexamined.
Annotations¶
medh5 seg stats¶
Per-class voxel counts, the class overlap graph, and what the encoding auto-selector would cost for each candidate encoding.
medh5 seg convert¶
Losslessly re-encode a voxel annotation: labelmap, layers, bitmask,
instances, probmap. --dry-run prints the size change without writing.
From instances to a dense encoding the voxels survive and the object ids do
not, so it is refused unless --drop-identity says to drop them; the file then
records a transcode activity saying so.
medh5 index build¶
Build or refresh sampling indices, which make foreground patch sampling O(1) in
the volume. --max-coords bounds the stored coordinates per class (default
4096); --occupancy sets the block size of the coarse per-class occupancy map,
in voxels per axis (default 8, so the map is 1/8 resolution); --seed (default
0) fixes the coordinate subsample, so rebuilding an index reproduces it.
medh5 labels¶
medh5 labels show PATH [--json]
medh5 labels check PATH... [--json]
medh5 labels registry list [--json]
Inspect a file's label set, check a cohort's label sets against each other, and list the bundled vocabularies.
Curation¶
medh5 prov¶
Agents, activities, quality records and the de-identification record.
medh5 agree¶
Per-class Dice or IoU between two voxel annotations, and object F1 between two
instances or boxes annotations of the same sample — two readers, or a reader
and a model. --metric applies to the first and --threshold to the second;
the other is refused rather than ignored. Only classes both sides examined are
scored (§11.3), and a comparison with nothing to score says so rather than
reporting 0. The two must share a grid (for index boxes) or a frame (for world
boxes). --record prints the quality.agreement record the measurement
produces, keyed by class id, and exits 1 when there is nothing to record.
medh5 splits¶
Cross-file audit: conflicting split claims (W906) and subject leakage between
partitions. Needs the whole cohort, which is why it is not part of validate.
A leak is found over subjects and grouping keys together, so one subject
curated under two group_ids in two partitions is a leak.
medh5 scrub¶
medh5 scrub PATH... [--profile basic|strict] [--apply] [--date-shift-days N] [--salt S] [--by WHO] [--pseudonymise-ids] [--json]
Find identifiers in the container. Without --apply nothing is written and the
exit code is 1 if anything was found, so it works as a pipeline gate.
The scan covers every string in the file — all of /meta, every object name,
attribute and string dataset, including ones a newer version wrote — and skips
only fields named in the code with a reason (see the
de-identification guide).
--apply removes identifying attributes wherever the scan reports them,
pseudonymises UIDs (so files still join on a shared frame of reference) including
inside provenance references, reduces provenance paths to a file name, shifts
or drops dates, and writes a §11.4 de-identification record saying what was
and was not checked. It does not look at pixels: burned-in text and
identifiable anatomy are outside its reach, and the record it writes says so
rather than claiming a clean file.
--apply re-scans what it wrote, records the result in the
de-identification activity's parameters, and exits non-zero if anything
actionable is left — and, under --profile strict, while sample_id or
subject_id is still an identifier (the DICOM importer's are the PatientID).
An apply that exits 0 is a file the same rules now find nothing to fix in.
--pseudonymise-ids (with --apply and --salt) replaces sample_id and
subject_id — and a cohort.group_id equal to either — with salted stable
pseudonyms. A file still named after the old id is reported: scrub does not
rename files.
Running it twice does not shift dates twice.
Collections¶
medh5 pack¶
Bundle samples into one .medh5c. Chunks move as raw bytes, so packing is
byte-identical and content_id is preserved. Each member's key is its file
stem unless --key is repeated once per source, in order.
medh5 unpack¶
Extract — every member, or only the keys named — or list what is inside.
Cohorts¶
medh5 dataset index¶
Metadata-only scan of a directory tree. Reports what would not open instead of
aborting; --strict makes the first failure fatal.
medh5 dataset split¶
--set-id ID name of this split (default "default")
--group-by FIELD grouping key (default group_id — never a file)
--stratify-by FIELD balance a field across partitions
--ratios train=0.7,val=0.15,test=0.15
--k-folds N k-fold instead of ratios
--seed N deterministic given the manifest, seed and parameters (default 0)
-o, --out split.json
--write-claims stamp each sample with its partition and the manifest digest
--fold N with --k-folds --write-claims: which fold is validation
--assigned-by WHO recorded on each claim as who assigned it
--json
Groups, not files: a subject's baseline and follow-up cannot land on opposite sides. If the ratios cannot be met by an indivisible set of groups, the command says which partition got nothing rather than leaving you to notice later.
medh5 dataset stats¶
medh5 dataset stats manifest.json [--image K ...] [--annotation A ...] [--workers N]
[--stride S] [--stored] [--partition P] [--set-id ID]
[--out FILE] [--json]
Streaming intensity moments and class frequencies. Reads class counts from the
sampling index when it is current. --partition train restricts the pass to
one partition of --set-id (default default), which is how you compute
normalisation constants without looking at your test set. --stride N reads
every Nth slab along the first axis — faster, approximate, and opt-in.
Intensity moments are over physical values: each image's rescale is applied
first, which is what the loaders read with physical=True. --stored measures
the values the files store instead.
medh5 dataset check¶
Cross-file consistency. Findings carry
C1xx–C5xx codes.
--deep re-reads each content_id instead of trusting size and mtime.
Converting¶
Every convert command except to-nifti writes a report of what it
decided (determined from the data) and where it guessed (assumed
something it could not read). --report FILE keeps it as JSON and --json
prints it; without either, guesses and warnings still print.
medh5 convert from-nifti OUT --image NAME=PATH [--image ...] [--mask NAME=PATH ...]
[--modality NAME=CODE ...] [--coord-system LPS|RAS]
[--fourth-axis auto|time|channel] [--assume-geometry]
[--sample-id ID] [--subject-id ID]
medh5 convert to-nifti PATH IMAGE OUT [--annotation A --class K] [--stored]
medh5 convert from-dicom ROOT OUT [--group-by subject|study]
[--modality M ...] [--series UID ...]
medh5 convert from-dicom-seg SEG SAMPLE [--id ANN] [--grid G]
medh5 convert to-dicom-seg PATH ANNOTATION OUT --source DICOM [--source DICOM ...]
medh5 convert from-rtstruct RTSTRUCT SAMPLE [--id ANN] [--grid G] [--rasterize]
medh5 convert to-rtstruct PATH ANNOTATION OUT --source DICOM [--source DICOM ...]
medh5 convert from-nnunet ROOT OUT [--case ID ...]
medh5 convert to-nnunet OUT PATH... [--dataset-name NAME] [--annotation A]
All but to-nifti also take [--report FILE] [--json]. Options marked ...
repeat, one value per occurrence.
from-nifti --fourth-axis says what a 4-D series' extra axis is — time for
cine, DCE and 4-D CT, channel for multi-b-value DWI and multi-echo; auto
(the default) reads the file's sidecars and header and records a guess when they
do not say. --assume-geometry imports a file that declares no spatial mapping,
recorded as a guess; without it such a file is refused.
from-dicom --group-by subject (the default) merges a patient's studies into
one multi-timepoint sample. Identity is never inferred from filenames, dates or
accession numbers; when it cannot be established the command falls back to one
sample per study, warns, and records the fallback.
from-dicom-seg writes annotation seg and from-rtstruct writes contours
unless --id names another; to-nnunet exports annotation seg unless
--annotation names another, as dataset Dataset001_medh5 unless
--dataset-name does.
See Converters.
medh5 migrate¶
0.x files to 1.0 (spec Appendix B).
--group-by subject|study default study — a 0.x file has no subject key
--subject-key extra.patient_id
--write-labels FILE mint the cohort's label set for review, then stop
--label-set FILE reuse a reviewed label set
--report FILE
--json
See Migrate from 0.x for the two-pass procedure.
Storage¶
medh5 recompress¶
medh5 recompress PATH... --profile P [--rechunk] [--json]
medh5 recompress PATH --profile P --out FILE [--rechunk] [--json]
Re-encode bulk data under training, balanced, archive or portable.
Every stored byte changes; no content_id does, because the digest is over
content and not over its encoding.
The output is verified against the digests it carries before the command
returns, and the exit code follows: a file whose bytes had already been
corrupted before you re-encoded it now fails here rather than reporting a
preserved content_id and exiting 0.
medh5 bench¶
medh5 bench [PATH] [--patch N] [--repeats N] [--workers N] [--annotation A] [--no-throughput] [--json]
Reproduce the performance targets on your hardware. With no path it builds a
synthetic sample first, and a synthetic two-visit sample related by a
displacement field for the paired_center_ms row — one patch centre moved
between visits, the read a paired dataset does once per item — and a 63-class
sample for the foreground_sample_many_ms row, which holds the foreground draw
to its target where the class count is large. A longitudinal sample given as
PATH gets the paired row when a transform relates its first two visits.
Progress goes to stderr, so --json output is only the document.
Conformance¶
medh5 conformance list¶
Every corpus case, the clause it tests, and the codes it expects.
medh5 conformance build¶
Write the corpus files and expected.json, and nothing else. Use this when you
want the cases as fixtures; use publish when you want the whole distributable
suite.
medh5 conformance run¶
Build the corpus and check this validator against it.
medh5 conformance publish¶
Write the distributable suite: cases, expected.json, the code table, the JSON
Schema, SHA256SUMS and a README.
medh5 conformance score¶
Score any implementation's results against a published suite. See Conformance.
Related¶
- Check a file before training on it —
validateversusverify. - Diagnostic codes — every code these commands report.
- Cohort check codes — what
medh5 dataset checkreports. - How-to guides — these commands in the tasks they belong to.