This page describes the metadata stored in an .mla file (format version 1). The normative definition is
the v1 specification and the JSON Schemas shipped with the package
(mlarray/schemas/mlarray-1.0.json, profile-ml-1.0.json, profile-medical-1.0.json).
An .mla file is a blosc2 NDArray. Its metadata lives in three blosc2 vlmeta keys, each a msgpack map
that blosc2 compresses separately:
| key | content | read |
|---|---|---|
mlarray |
version, writer, axes, spaces, values, profiles, history, storage |
on open |
mlarray.source |
{"source": [...]}, original metadata of converted files |
on first access |
mlarray.user |
{"user": {...}}, arbitrary user metadata |
on first access |
- Only plain msgpack types are stored: maps, arrays, strings, integers, floats, booleans, nil, binary. Nothing is pickled, and readers decode the raw bytes with plain msgpack, never through blosc2's own vlmeta decoder.
- Opening a file reads only the
mlarraykey, so it stays fast however largesourceis. - Unknown keys are kept and written back at every level.
- Files written by MLArray before v1 are not readable; convert them again from their original files.
Inspect a file with mlarray_header file.mla (add --source and --user for the lazy keys).
version: "1.0" # metadata format version; readers accept any 1.x
writer: "mlarray 1.0.0" # software that wrote the fileOne entry per array axis, in array (C) order. Required.
| field | meaning |
|---|---|
name |
unique name, e.g. z, y, x, t, c. A name only: it says nothing about direction. Defaults: axis_0, axis_1, ... |
type |
space · time · channel · component · other |
labels |
one label per index, for categorical axes: ["T1", "T2", "FLAIR"] |
start, step, unit, unit_code |
uniform sampling of a non-space axis: coordinate of index i = start + i·step |
coordinates, unit, unit_code |
explicit coordinate per index (timestamps, b-values, wavelengths) |
Space axes carry no sampling or unit here: their geometry lives in spaces.
Optional. Without spaces the array lives in index space only (photos, ML tensors). Each space is a named coordinate system and the matrix that maps array indices into it:
spaces:
- name: patient
reference: {scheme: dicom_frame_of_reference, id: "1.2.826.0.1.3680043.8.498.1"}
axes:
- {name: x, unit: millimeter, unit_code: mm, increases_toward: left}
- {name: y, unit: millimeter, unit_code: mm, increases_toward: posterior}
- {name: z, unit: millimeter, unit_code: mm, increases_toward: superior}
from_array:
array_axes: [z, y, x]
matrix: # rows: space axes x, y, z (+1)
- [ 0.0, 0.0, 0.7, -170.1] # columns: array_axes z, y, x (+ translation)
- [ 0.0, 0.7, 0.0, -201.3]
- [-2.5, 0.0, 0.0, -87.0]
- [ 0.0, 0.0, 0.0, 1.0]referenceidentifies the physical frame; two spaces are the same frame ifschemeandidmatch.increases_towardsays in which direction a coordinate grows:left/right,anterior/posterior,superior/inferior,east/west,north/south,up/down. It replaces letter codes such asRASorLPS, which mean different things in different tools. The example is the DICOM patient frame (LPS), the recommended world frame for medical images (space="patient"in the Python API).from_array.matrixhas one row per space axis plus[0, ..., 0, 1], and one column per entry ofarray_axesplus the translation. Rotations, oblique and mirrored grids and shear are allowed. Axis-aligned grids may usescaleandtranslation(per array axis) instead.- An integer index is the centre of its voxel:
matrix · [index, 1]is the coordinate of the voxel centre. - Spacing, origin, direction and letter codes are derived (
MLArray.spacing,.origin,.direction,.letter_codes()), never stored. - Several spaces are allowed (e.g.
patientandatlas); the first is the default.
What the stored numbers mean. Defaults to {kind: measurement}.
| field | meaning |
|---|---|
kind |
measurement · label · instance · probability · vector · other |
unit, unit_code |
unit of the values, e.g. hounsfield_unit |
scale, offset |
physical value = scale · stored + offset; stored values are never pre-scaled |
fill |
value meaning "no data" |
labels |
for label kinds: map from value (as a decimal string) to {name, color, code}; code is an ontology reference {scheme, value, meaning} |
label_layout |
index (one label value per element) or channel (one channel per label) |
Units are a readable name plus an optional UCUM code. Use a name from the curated list
(mlarray/schemas/units-1.0.json: nanometer ... kilometer, second, degree, hounsfield_unit, counts,
percent, kelvin, arbitrary, ...); MLArray fills in unit_code for listed names. Free text is allowed
when no listed unit fits.
Optional, independent domain metadata. Profiles never repeat what the core states.
profiles:
medical:
profile_version: "1.0"
dicom: {Modality: MR, BodyPartExamined: BRAIN, RepetitionTime: 2300} # DICOM keywords
ml:
profile_version: "1.0"
statistics: {min: -1024, max: 3071, mean: 40.2, standard_deviation: 410.0, percentiles: {"99.5": 1500}}
boxes:
frame: index # "index" (array axes) or a space name (space coordinates)
axes: [z, y, x]
items: [{min: [10, 50, 60], max: [40, 90, 120], label: 1, score: 0.97}]
patch_size: [128, 128, 128]
split: trainmedical.dicomholds curated medical metadata for files without a DICOM source, or deliberate overrides of source values. Files converted from DICOM keep their full DICOM metadata insource.- Profiles from third parties use a reverse-domain name (
org_example_cryoem) and are kept as they are.
history:
- {action: converted, tool: "medvol 2.0.0", time: "2026-11-06T10:12:00Z", from: nifti, warnings: [...]}
storage:
chunk_size: [1, 256, 256]
block_size: [1, 64, 64]
patch_size: [128, 128, 128]
compression: {codec: LZ4HC, level: 5, filters: [SHUFFLE]}storage records only portable layout settings. Thread counts, typesize and similar runtime settings
are never stored; they come from the library defaults (see ML Optimization).
meta.storage.to_cparams() returns the recorded compression as blosc2.CParams.
source keeps the original metadata of converted files readable and complete, so a converter can write
the original format back. Each entry has format, files, reader, an index_map (how the stored
array relates to the source file's own index order), a fingerprint (shape, dtype and hashes of the
geometry and data) and the header as nested native values. It is read-only, and images derived from
another image do not inherit it unless asked to (copy_source=True).
user holds any msgpack-compatible metadata of your own and is never interpreted.