zea.data.spec

Module Attributes

ROOT_SPECS

Roots of a path into a zea file that are not fields of FileSpec itself: data and scan are the single-track shorthands that zea.File.__getitem__() remaps onto tracks/track_0/.

Functions

check_dtype(value, expected_dtype)

Check if the dtype of a value matches the expected dtype, allowing for compatible types.

check_track_rules(*, has_data, has_scan, ...)

Raise InvalidZeaFileError if a track breaks one of the format's rules.

dim_names_for_key(key, ndim)

Resolve a path into a zea file to one dimension name per axis of its array.

find_matched_shape(value, expected_shapes)

Find the first expected shape specification that matches the shape of the value.

is_array_like(value)

Whether value is an n-dimensional array the spec can describe and store.

is_lazy_array(value)

Whether value is an array whose contents are not (yet) in memory.

iter_slabs(array[, max_bytes, chunks, ...])

Iterate over array in slabs of at most max_bytes, as (selection, values).

match_shape(value, expected_shape)

Check if the shape of a value matches the expected shape specification.

strip_track_prefix(key)

Strip a leading tracks/track_N/ off a path into a zea file.

value_shape(value)

Return the shape tuple for arrays (lazy ones included) and scalar values.

Classes

AlignedData(values[, labels])

Time-of-flight corrected data.

Annotations([anatomy, view, label, ...])

Frame-level annotations, either one per frame or a single broadcast value.

AttenuationMap(values[, coordinates, ...])

Acoustic attenuation map with per-pixel Cartesian coordinates.

BeamformedData(values[, coordinates, ...])

Beamformed (beamsummed) data with per-pixel Cartesian coordinates.

BooleanMap(values[, coordinates, ...])

Map data with bool pixel values and per-pixel Cartesian coordinates.

ColorDopplerMap(values[, coordinates, ...])

Color Doppler (velocity) data with per-pixel Cartesian coordinates.

DataSpec([raw_data, aligned_data, ...])

Data group containing raw channels, derived pipeline products, and optional spatial maps.

EnvelopeData(values[, coordinates, ...])

Envelope-detected data with per-pixel Cartesian coordinates.

FileSpec([data, scan, tracks, ...])

A dataset containing all the data, scan parameters, metadata, and metrics for a single acquisition.

FloatMap(values[, coordinates, timestamps, ...])

Map data with float32 pixel values and per-pixel Cartesian coordinates.

Image(values[, coordinates, timestamps, ...])

Reconstructed (log-compressed) image data with per-pixel Cartesian coordinates.

Map(values[, coordinates, timestamps, ...])

Map data with per-pixel Cartesian coordinates.

MetadataSpec([subject, credit, probe_pose, ...])

Metadata group with subject, acquisition context, annotations, and extra signals.

MetricsSpec([common_midpoint_phase_error, ...])

Metrics group for acquisition-level quality/performance metrics.

ProbePose(start_time_offset, translation, ...)

Sampled probe pose metadata at the tip of the transducer.

ProbeSpec([name, type, ...])

Probe hardware specification.

ScanSpec(sampling_frequency, ...[, ...])

Scan group with acquisition and transmit metadata.

Segmentation(values[, coordinates, ...])

Segmentation data with per-pixel Cartesian coordinates.

ShearWaveElastographyMap(values[, ...])

Shear-wave elastography data with per-pixel Cartesian coordinates.

Signal(start_time_offset, *[, ...])

Base class for additional signals with timing metadata.

Signal1D(start_time_offset, samples, *[, ...])

One-dimensional sampled signal with timing metadata.

SignalND(start_time_offset, samples, *[, ...])

N-dimensional sampled signal with timing metadata.

SosMap(values[, coordinates, timestamps, ...])

Speed-of-sound map data with per-pixel Cartesian coordinates.

Spec()

Base class for data specifications with schema validation.

StrainPercentageMap(values[, coordinates, ...])

Strain map data with per-pixel Cartesian coordinates.

Subject([id, type, age, sex, weight, ...])

Subject metadata associated with the study.

TissueDopplerMap(values[, coordinates, ...])

Tissue Doppler data with per-pixel Cartesian coordinates.

TrackSpec([data, scan, label, transmit_only])

A single acquisition track with its own data and scan parameters.

UnsignedIntMap(values[, coordinates, ...])

Map data with uint8 pixel values and per-pixel Cartesian coordinates.

Exceptions

InvalidZeaFileError

Raised when data does not have the structure the zea format requires.

class zea.data.spec.AlignedData(values, labels=None)[source]

Bases: Spec

Time-of-flight corrected data.

Parameters:
  • values (ndarray) – The aligned data of shape (n_frames, n_tx, n_ax, n_el, n_ch) and type float32 or int16. n_ch is 1 for RF data or 2 for IQ data.

  • labels (ndarray | None) – The labels for the channel dimension, e.g. ["RF"] or ["I", "Q"]. Auto-generated from n_ch if not provided.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'labels': {'description': "Channel labels, e.g. 'RF' or ['I', 'Q'].", 'unit': '–'}, 'values': {'description': 'Time-of-flight corrected channel data.', 'unit': '–'}}
labels: ndarray | None = None
values: ndarray
class zea.data.spec.Annotations(anatomy=None, view=None, label=None, image_quality=None)[source]

Bases: Spec

Frame-level annotations, either one per frame or a single broadcast value.

Parameters:
  • anatomy (ndarray | str | None) – Anatomical structure imaged, e.g. carotid, liver, thyroid.

  • view (ndarray | str | None) – Imaging plane/orientation, e.g. longitudinal, transverse, apical_4_chamber.

  • label (ndarray | str | None) – Pathology or classification label, e.g. benign, malignant.

  • image_quality (ndarray | str | None) – Image quality label, e.g. low, mid, high.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'anatomy': {'description': 'Anatomical structure imaged (e.g. carotid, liver).', 'unit': '–'}, 'image_quality': {'description': 'Image quality label.', 'rare': True, 'unit': '–'}, 'label': {'description': 'Pathology or classification label.', 'unit': '–'}, 'view': {'description': 'Imaging plane/orientation (e.g. longitudinal, apical_4_chamber).', 'unit': '–'}}
anatomy: ndarray | str | None = None
image_quality: ndarray | str | None = None
label: ndarray | str | None = None
view: ndarray | str | None = None
class zea.data.spec.AttenuationMap(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None, gamma=1.0)[source]

Bases: FloatMap

Acoustic attenuation map with per-pixel Cartesian coordinates.

Acoustic attenuation describes the loss of acoustic energy as the wave propagates through tissue (through absorption and scattering). Attenuation is frequency dependent and is modelled here with the usual power law

\[\alpha(f) = \alpha_0 \, f^{\gamma},\]

where \(\alpha_0\) is the per-pixel attenuation coefficient stored in values and \(\gamma\) is the (scalar) power-law exponent stored in gamma. Reporting the coefficient normalized by frequency makes values comparable across systems and transmit frequencies.

The coefficient is stored in the spec’s base units of dB/m/Hz (rather than the common clinical dB/cm/MHz; note 1 dB/cm/MHz = 1e-4 dB/m/Hz). Strictly, when \(\gamma \neq 1\) the coefficient carries the exponent in its units (dB/m/Hz**gamma); the dB/m/Hz label reflects the linear (\(\gamma = 1\)) convention.

The exponent is close to 1 for most soft tissue (attenuation is roughly linear in frequency), e.g. liver \(\gamma \approx 1.14\), breast \(\gamma \approx 1.5\), while water / low-loss viscous media follow \(\gamma = 2\). It defaults to 1.0 (linear), which reproduces the plain frequency-normalized “attenuation coefficient slope”.

Parameters:
  • values (ndarray) – The attenuation coefficient \(\alpha_0\) in dB/m/Hz of shape (n_frames, z, x, y) and type float32.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres, shape (n_frames, z, x, 3) or (n_frames, z, x, y, 3). The leading frame axis may be omitted to broadcast one coordinate grid across all frames.

  • gamma (float) – Scalar power-law exponent \(\gamma\) of the frequency dependence \(\alpha(f) = \alpha_0 f^{\gamma}\). Defaults to 1.0 (linear frequency dependence).

FIELD_METADATA: ClassVar[dict[str, Any]] = {'coordinates': {'description': 'Per-pixel Cartesian positions (x, y, z) in metres.', 'unit': 'm'}, 'description': {'description': 'Free-text description of the map contents.', 'rare': True, 'unit': '–'}, 'gamma': {'description': 'Power-law exponent of the frequency dependence alpha(f) = alpha_0 * f**gamma. 1.0 is linear (soft tissue ~1-1.5, e.g. liver ~1.14), 2.0 for water.', 'rare': True, 'unit': '–'}, 'labels': {'description': 'Labels for each channel in values.', 'rare': True, 'unit': '–'}, 'max': {'description': 'Maximum value of the map.', 'rare': True, 'unit': '–'}, 'min': {'description': 'Minimum value of the map.', 'rare': True, 'unit': '–'}, 'start_time_offset': {'description': 'Time offset between the first transmit event of the ultrasound acquisition and frame 0 of this map. Negative means frame 0 was acquired before the first transmit event; positive means it was acquired after.', 'rare': True, 'unit': 's'}, 'timestamps': {'description': 'Per-frame acquisition timestamps relative to frame 0.', 'rare': True, 'unit': 's'}, 'unit': {'description': "Physical unit of the map values, e.g. 'm/s', '%'.", 'rare': True, 'unit': '–'}, 'values': {'description': 'Map pixel values.', 'unit': '–'}}
gamma: float = 1.0
class zea.data.spec.BeamformedData(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: FloatMap

Beamformed (beamsummed) data with per-pixel Cartesian coordinates.

Parameters:
  • values (ndarray) – The beamformed data of shape (n_frames, z, x, n_ch) or (n_frames, z, x, y, n_ch) and type float32. n_ch is 1 for RF data or 2 for IQ data.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres, shape (n_frames, z, x, 3) or (n_frames, z, x, y, 3). The leading frame axis may be omitted to broadcast one coordinate grid across all frames.

  • labels (ndarray | None) – The labels for the channel dimension, e.g. ["RF"] or ["I", "Q"]. Auto-generated from n_ch if not provided.

class zea.data.spec.BooleanMap(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: Map

Map data with bool pixel values and per-pixel Cartesian coordinates.

class zea.data.spec.ColorDopplerMap(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: FloatMap

Color Doppler (velocity) data with per-pixel Cartesian coordinates.

Parameters:
  • values (ndarray) – The color Doppler velocity values in m/s of shape (n_frames, z, x, y) and type float32. Positive values indicate flow towards the transducer, negative values indicate flow away from the transducer.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres.

class zea.data.spec.DataSpec(raw_data=None, aligned_data=None, beamformed_data=None, envelope_data=None, image=None, segmentation=None, sos_map=None, attenuation_map=None, strain_percentage_map=None, shear_wave_elastography_map=None, tissue_doppler=None, color_doppler=None, **extra_maps)[source]

Bases: Spec

Data group containing raw channels, derived pipeline products, and optional spatial maps.

Plain-array data products:
raw_data: Raw channel data of shape (n_frames, n_tx, n_ax, n_el, n_ch)

and type float32 or int16. The fourth axis counts receive channels, which normally means every probe element. Acquisitions using a receive sub-aperture (a sliding receive window, or a multiplexed front-end with fewer channels than elements) may carry fewer, in which case ScanSpec.rx_aperture_indices records which element each channel corresponds to.

Grouped data products (values + optional metadata):
  • aligned_data: Time-of-flight corrected data and optional labels.

  • beamformed_data: Beamformed (beamsummed) data and per-pixel coordinates.

  • envelope_data: Envelope-detected data and per-pixel coordinates.

  • image: Reconstructed image data and per-pixel coordinates.

  • segmentation: Segmentation data and per-pixel coordinates.

  • sos_map: Speed-of-sound map data and per-pixel coordinates.

  • attenuation_map: Acoustic attenuation map data and per-pixel coordinates.

  • strain_percentage_map: Strain map data and per-pixel coordinates.

  • shear_wave_elastography_map: Shear-wave elastography data and per-pixel coordinates.

  • tissue_doppler: Tissue Doppler data and per-pixel coordinates.

  • color_doppler: Color Doppler velocity data and per-pixel coordinates.

  • **kwargs: Any other spatially aligned map data and per-pixel coordinates.

At least one data field (plain-array or grouped) must be provided.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'aligned_data': {'description': 'Time-of-flight corrected data.', 'rare': True}, 'attenuation_map': {'description': 'Acoustic attenuation map data.', 'rare': True}, 'beamformed_data': {'description': 'Beamformed data.', 'rare': True}, 'color_doppler': {'description': 'Color Doppler velocity data.', 'rare': True}, 'envelope_data': {'description': 'Envelope-detected data.', 'rare': True}, 'image': {'description': 'Reconstructed image data.', 'rare': True}, 'raw_data': {'description': 'Raw channel data.', 'unit': '–'}, 'segmentation': {'description': 'Segmentation data.', 'rare': True}, 'shear_wave_elastography_map': {'description': 'Shear-wave elastography data.', 'rare': True}, 'sos_map': {'description': 'Speed-of-sound map data.', 'rare': True}, 'strain_percentage_map': {'description': 'Strain map data.', 'rare': True}, 'tissue_doppler': {'description': 'Tissue Doppler data.', 'rare': True}}
aligned_data: AlignedData | dict | None = None
attenuation_map: AttenuationMap | dict | None = None
beamformed_data: BeamformedData | dict | None = None
color_doppler: ColorDopplerMap | dict | None = None
envelope_data: EnvelopeData | dict | None = None
image: Image | dict | None = None
raw_data: ndarray | None = None
segmentation: Segmentation | dict | None = None
shear_wave_elastography_map: ShearWaveElastographyMap | dict | None = None
sos_map: SosMap | dict | None = None
strain_percentage_map: StrainPercentageMap | dict | None = None
tissue_doppler: TissueDopplerMap | dict | None = None
class zea.data.spec.EnvelopeData(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: FloatMap

Envelope-detected data with per-pixel Cartesian coordinates.

Parameters:
  • values (ndarray) – The envelope data of shape (n_frames, z, x) or (n_frames, z, x, y) and type float32.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres, shape (*values.shape, 3). The leading frame axis may be omitted to broadcast one coordinate grid across all frames.

class zea.data.spec.FileSpec(data=None, scan=None, tracks=None, track_schedule=None, metadata=None, metrics=None, probe_name=None, probe=None, us_machine=None, description=None, acquisition_time=None, custom=None)[source]

Bases: Spec

A dataset containing all the data, scan parameters, metadata, and metrics for a single acquisition.

A FileSpec always contains at least one track. When data and scan are supplied at construction time they are transparently wrapped into a single TrackSpec, so all existing call-sites continue to work unchanged. For multi-track files pass tracks directly.

Parameters:
  • data (DataSpec | dict | None) – Data for a single-track acquisition (wrapped into tracks[0]).

  • scan (ScanSpec | dict | None) – Scan parameters for a single-track acquisition.

  • tracks (list | None) – Explicit list of TrackSpec objects (multi-track mode). Mutually exclusive with data/scan.

  • track_schedule (ndarray | None) – 1-D int32 array of length n_total_tx giving the track index for each global transmit event.

  • metadata (MetadataSpec | dict | None) – Additional metadata about the acquisition.

  • metrics (MetricsSpec | dict | None) – Metrics computed from the acquisition.

  • probe (ProbeSpec | dict | None) – Physical probe specification (see ProbeSpec). The probe name is stored as probe.name; use zea.File.probe_name to read it back from an HDF5 file.

  • us_machine (str | None) – The ultrasound machine used to acquire the data.

  • description (str | None) – Free-text description.

  • custom (list | None) – Optional list of CustomElement objects holding data that does not fit the zea format. These are written to a custom group.

Example

>>> from datetime import datetime, timezone
>>> from zea.data.spec import FileSpec
>>> import numpy as np

>>> dataset = FileSpec(
...     data={
...         "raw_data": np.zeros((2, 4, 64, 8, 1), dtype=np.float32),
...     },
...     scan={
...         "sampling_frequency": np.float32(40e6),
...         "center_frequency": np.float32(5e6),
...         "demodulation_frequency": np.float32(5e6),
...         "initial_times": np.zeros(4, dtype=np.float32),
...         "t0_delays": np.zeros((4, 8), dtype=np.float32),
...         "tx_apodizations": np.ones((4, 8), dtype=np.float32),
...         "focus_distances": np.full(4, np.inf, dtype=np.float32),
...         "transmit_origins": np.zeros((4, 3), dtype=np.float32),
...         "polar_angles": np.zeros(4, dtype=np.float32),
...     },
...     probe={"name": "test_probe", "probe_geometry": np.zeros((8, 3))},
...     acquisition_time=datetime.now(timezone.utc).isoformat(),
... )
>>> dataset.data.raw_data.shape
(2, 4, 64, 8, 1)
>>> dataset.acquisition_time is not None
True
FIELD_METADATA: ClassVar[dict[str, Any]] = {'acquisition_time': {'description': "UTC acquisition timestamp in ISO 8601 format (e.g. '2026-06-12T14:30:00+00:00'). Optional — not recorded when omitted."}}
acquisition_time: str | None = None
custom: list
property data: DataSpec

Return the DataSpec of the single track.

Raises AttributeError when the file has more than one track — use spec.tracks[i].data instead.

description: str | None = None
metadata: MetadataSpec | dict
metrics: MetricsSpec | dict
probe: ProbeSpec | dict | None = None
save(path, compression=Blosc(cname='zstd', clevel=7, shuffle=2), chunk_axes=('n_frames',), warn_missing_optional_fields=True)[source]

Save the dataset to the specified path.

Fields that are lazy arrays — still backed by an open file rather than held in memory (see is_lazy_array()) — are copied across slab by slab, so a file far larger than RAM can be written. The source file has to stay open for the duration of the call; this is what zea data resave does.

Return type:

None

property scan: ScanSpec | None

Return the ScanSpec of the single track.

Raises AttributeError when the file has more than one track — use spec.tracks[i].scan instead.

to_dict()[source]

Return this spec as a nested dictionary.

Includes all SCHEMA fields plus the tracks list.

Return type:

dict

track_schedule: ndarray | None = None
tracks: list
us_machine: str | None = None
class zea.data.spec.FloatMap(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: Map

Map data with float32 pixel values and per-pixel Cartesian coordinates.

class zea.data.spec.Image(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: Map

Reconstructed (log-compressed) image data with per-pixel Cartesian coordinates.

Parameters:
  • values (ndarray) – The image values of shape (n_frames, z, x, y) or (n_frames, z, x) and type uint8 or float32. For float32 values, the values should be in dB (between -inf and 0).

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres, shape (*values.shape, 3). The leading frame axis may be omitted to broadcast one coordinate grid across all frames.

exception zea.data.spec.InvalidZeaFileError[source]

Bases: ValueError

Raised when data does not have the structure the zea format requires.

class zea.data.spec.Map(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: Spec

Map data with per-pixel Cartesian coordinates.

A map is a function from Cartesian space to some real values: every pixel at spatial index [f, i, j, ...] is assigned a 3-D position coordinates[f, i, j, ..., :] = [x, y, z] in metres.

The most flexible map spec, which can be used for any spatially aligned data product. See, for example, cartesian_pixel_grid() or polar_pixel_grid() to create a suitable coordinate array from your scan geometry.

Parameters:
  • values (ndarray) – The map values of shape (n_frames, z, x, y, n_ch) or (n_frames, z, x, y) or (n_frames, z, x, n_ch) or (n_frames, z, x) and type uint8, float32, int16, or complex64.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres, shape (*spatial_dims, 3) where spatial_dims matches the spatial (non-channel) dimensions of values. For non-channeled values the shape is (*values.shape, 3); for channeled values the shape is (*values.shape[:-1], 3). The last axis holds [x, y, z]. The leading n_frames axis may be omitted to broadcast one coordinate grid across all frames.

  • timestamps (ndarray | None) – Optional per-frame acquisition timestamps in seconds, shape (n_frames,), relative to frame 0. Use this to record the time of each frame when the sampling is irregular. Must start at 0 and be strictly increasing. Requires start_time_offset to also be provided.

  • start_time_offset (ndarray | float | None) – Time offset in seconds between the first transmit event of the ultrasound acquisition and frame 0 of this map. Negative means frame 0 was acquired before the first transmit event; positive means it was acquired after. Required when timestamps is provided.

  • labels (ndarray | None) – The labels corresponding to the n_ch channels in the values. This is required when values have an n_ch dimension, and should be None otherwise. For IQ data, this would typically be ["I", "Q"].

  • description (str | None) – An optional free-text description of the map.

  • unit (str | None) – An optional string specifying the physical unit of the map values, e.g. "m/s", "%", etc.

  • min (float | None) – The minimum value of the map.

  • max (float | None) – The maximum value of the map.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'coordinates': {'description': 'Per-pixel Cartesian positions (x, y, z) in metres.', 'unit': 'm'}, 'description': {'description': 'Free-text description of the map contents.', 'rare': True, 'unit': '–'}, 'labels': {'description': 'Labels for each channel in values.', 'rare': True, 'unit': '–'}, 'max': {'description': 'Maximum value of the map.', 'rare': True, 'unit': '–'}, 'min': {'description': 'Minimum value of the map.', 'rare': True, 'unit': '–'}, 'start_time_offset': {'description': 'Time offset between the first transmit event of the ultrasound acquisition and frame 0 of this map. Negative means frame 0 was acquired before the first transmit event; positive means it was acquired after.', 'rare': True, 'unit': 's'}, 'timestamps': {'description': 'Per-frame acquisition timestamps relative to frame 0.', 'rare': True, 'unit': 's'}, 'unit': {'description': "Physical unit of the map values, e.g. 'm/s', '%'.", 'rare': True, 'unit': '–'}, 'values': {'description': 'Map pixel values.', 'unit': '–'}}
coordinates: ndarray | None = None
description: str | None = None
labels: ndarray | None = None
max: float | None = None
min: float | None = None
start_time_offset: ndarray | float | None = None
timestamps: ndarray | None = None
unit: str | None = None
values: ndarray
class zea.data.spec.MetadataSpec(subject=None, credit=None, probe_pose=None, voice_narration=None, ecg=None, text_report=None, annotations=None, **extra_signals)[source]

Bases: Spec

Metadata group with subject, acquisition context, annotations, and extra signals.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'annotations': {'description': 'Frame-level annotations.', 'rare': True, 'unit': '–'}, 'credit': {'description': 'Credit or attribution for the dataset.', 'unit': '–'}, 'ecg': {'description': 'Electrocardiogram signal.', 'rare': True, 'unit': '–'}, 'probe_pose': {'description': 'Sampled probe pose at the transducer tip.', 'rare': True, 'unit': '–'}, 'subject': {'description': 'Subject associated with the study.', 'unit': '–'}, 'text_report': {'description': 'Free-text report associated with the study.', 'rare': True, 'unit': '–'}, 'voice_narration': {'description': 'Voice narration signal.', 'rare': True, 'unit': '–'}}
annotations: Annotations | dict | None = None
credit: str | None = None
ecg: Signal1D | dict | None = None
probe_pose: ProbePose | dict | None = None
subject: Subject | dict | None
text_report: str | None = None
voice_narration: Signal1D | dict | None = None
class zea.data.spec.MetricsSpec(common_midpoint_phase_error=None, coherence_factor=None)[source]

Bases: Spec

Metrics group for acquisition-level quality/performance metrics.

Parameters:
  • common_midpoint_phase_error (ndarray | None) – Common midpoint phase error in radians of shape (n_frames,) and type float32.

  • coherence_factor (ndarray | None) – Coherence factor of shape (n_frames,) and type float32.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'coherence_factor': {'description': 'Coherence factor; ratio of coherent to incoherent energy (0-1).', 'rare': True, 'unit': '–'}, 'common_midpoint_phase_error': {'description': 'Common midpoint phase error.', 'rare': True, 'unit': 'rad'}}
coherence_factor: ndarray | None = None
common_midpoint_phase_error: ndarray | None = None
class zea.data.spec.ProbePose(start_time_offset, translation, rotation, rotation_representation, *, sampling_frequency=None, timestamps=None)[source]

Bases: Signal

Sampled probe pose metadata at the tip of the transducer.

The pose uses the coordinate convention x = lateral along the transducer, y = elevation (out of plane), and z = axial (depth).

Parameters:
  • translation (ndarray) – Position of the transducer tip in meters of shape (T, 3), ordered as (x, y, z).

  • rotation (ndarray) – Orientation of the transducer tip of shape (T, 3) or (T, 4), interpreted according to rotation_representation.

  • rotation_representation (str) – Rotation parameterization. Supported values are "euler_xyz", "quaternion_wxyz", and "quaternion_xyzw".

  • start_time_offset (ndarray | float) – Time offset in seconds between the first transmit event of the ultrasound acquisition and sample 0 of this data.

  • sampling_frequency (ndarray | float | None) – Sampling frequency in Hz for probe pose samples.

  • timestamps (ndarray | None) – Explicit probe pose timestamps in seconds of shape (T,), relative to sample 0.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'rotation': {'description': 'Orientation associated with the transducer-tip pose in the x-lateral, y-elevation, z-axial coordinate convention, interpreted according to rotation_representation.', 'unit': '–'}, 'rotation_representation': {'description': 'Rotation parameterization: one of euler_xyz, quaternion_wxyz, or quaternion_xyzw.', 'unit': '–'}, 'sampling_frequency': {'description': 'Sampling frequency.', 'unit': 'Hz'}, 'start_time_offset': {'description': 'Time offset between the first transmit event of the ultrasound acquisition and sample 0 of this data. Negative means this data starts before the first transmit event; positive means it starts after.', 'unit': 's'}, 'timestamps': {'description': 'Explicit sample timestamps relative to sample 0.', 'unit': 's'}, 'translation': {'description': 'Position of the transducer tip, ordered as (x, y, z), where x is lateral along the transducer, y is elevation (out of plane), and z is axial (depth).', 'unit': 'm'}}
rotation: ndarray
rotation_representation: str
translation: ndarray
class zea.data.spec.ProbeSpec(name=None, type=None, probe_center_frequency=None, probe_bandwidth_percent=None, probe_geometry=None, element_width=None, element_height=None, lens_sound_speed=None, lens_thickness=None)[source]

Bases: Spec

Probe hardware specification.

Stores static, physical characteristics of the transducer that are not captured by the per-acquisition ScanSpec. All fields are optional so that partial information can be recorded.

Parameters:
  • name (str | None) – Probe model identifier (e.g. "verasonics_l11_4v").

  • type (str | None) – Probe geometry type: "linear", "phased", "curved", etc.

  • probe_center_frequency (Union[float, int, floating, integer, None]) – Probe nominal centre frequency in Hz. Named distinctly from ScanSpec.center_frequency (the per-acquisition transmit frequency) so the two never collide when merged into a single zea.Parameters object.

  • probe_bandwidth_percent (Union[float, int, floating, integer, None]) – Fractional bandwidth as a percentage.

  • probe_geometry (ndarray | None) – Element positions in metres, shape (n_el, 3) with columns (x, y, z). n_el and pitch are computed automatically as read-only properties from this array.

  • element_width (Union[float, int, floating, integer, None]) – Width of a single transducer element in metres.

  • element_height (Union[float, int, floating, integer, None]) – Height (elevation aperture) of a single element in metres.

  • lens_sound_speed (Union[float, int, floating, integer, None]) – Speed of sound in the acoustic lens in m/s.

  • lens_thickness (Union[float, int, floating, integer, None]) – Thickness of the acoustic lens in metres.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'element_height': {'description': 'Height (elevation aperture) of a single transducer element.', 'rare': True, 'unit': 'm'}, 'element_width': {'description': 'Width of a single transducer element.', 'unit': 'm'}, 'lens_sound_speed': {'description': 'Speed of sound in the acoustic lens.', 'rare': True, 'unit': 'm/s'}, 'lens_thickness': {'description': 'Thickness of the acoustic lens.', 'rare': True, 'unit': 'm'}, 'name': {'description': 'Probe model name/identifier.'}, 'probe_bandwidth_percent': {'description': 'Fractional bandwidth as a percentage.', 'unit': '%'}, 'probe_center_frequency': {'description': "Probe nominal centre frequency (midpoint of the probe's -6 dB band).", 'unit': 'Hz'}, 'probe_geometry': {'description': 'Element positions (x, y, z) per element, shape (n_el, 3).', 'unit': 'm'}, 'type': {'description': 'Probe geometry type (linear, phased, curved, ...).'}}
element_height: float | int | floating | integer | None = None
element_width: float | int | floating | integer | None = None
lens_sound_speed: float | int | floating | integer | None = None
lens_thickness: float | int | floating | integer | None = None
property n_el: int | None

Number of transducer elements, derived from probe_geometry.

name: str | None = None
probe_bandwidth_percent: float | int | floating | integer | None = None
probe_center_frequency: float | int | floating | integer | None = None
probe_geometry: ndarray | None = None
type: str | None = None
zea.data.spec.ROOT_SPECS = {'data': <class 'zea.data.spec.DataSpec'>, 'scan': <class 'zea.data.spec.ScanSpec'>}

Roots of a path into a zea file that are not fields of FileSpec itself: data and scan are the single-track shorthands that zea.File.__getitem__() remaps onto tracks/track_0/.

class zea.data.spec.ScanSpec(sampling_frequency, center_frequency, demodulation_frequency, initial_times, t0_delays, tx_apodizations, focus_distances, transmit_origins, polar_angles, time_to_next_transmit=None, azimuth_angles=None, rx_aperture_indices=None, sound_speed=None, tgc_gain_curve=None, waveforms_one_way=None, waveforms_two_way=None)[source]

Bases: Spec

Scan group with acquisition and transmit metadata.

All fields are aligned with the data format specification.

Parameters:
  • sampling_frequency (ndarray | float) – The sampling frequency in Hz.

  • center_frequency (ndarray[Any, dtype[Any]] | float) – The center frequency in Hz of the transmit pulse. Single scalar if all transmits share the same center frequency; otherwise an array of shape (n_tx,) with one frequency per transmit.

  • demodulation_frequency (ndarray[Any, dtype[Any]] | float) – The frequency in Hz at which the data should be demodulated. Usually the same as center_frequency, but different when doing harmonic imaging. Single scalar if all transmits share the same center frequency; otherwise an array of shape (n_tx,) with one frequency per transmit.

  • initial_times (ndarray) – The times in seconds when the A/D converter starts sampling of shape (n_tx,). This is the time between the first element firing and the first recorded sample.

  • t0_delays (ndarray) – The transmit delays in seconds for each element of shape (n_tx, n_el). This is the time at which each element fires, shifted such that the first element fires at t=0.

  • tx_apodizations (ndarray) – The apodization values that were applied to each element during transmit of shape (n_tx, n_el). This is a value between -1 and 1 that indicates how much each element contributed to the transmit beam, with 0 meaning no contribution and 1 meaning full contribution. Negative values indicate that the element was fired with opposite polarity.

  • focus_distances (ndarray) –

    The transmit focus distances in meters of shape (n_tx,). This is the distance from the transmit origin on the transducer to where the beam comes to focus. The sign and magnitude encode the transmit type:

    • positive finite: focused transmit; the beam focuses at this distance in front of the array.

    • negative finite: diverging transmit; the (virtual) source lies this distance behind the array.

    • infinite (np.inf): plane wave. This is the preferred, canonical value for plane waves in zea. 0.0 is also accepted as a plane-wave marker (e.g. raw Verasonics data stores 0), but new data should use np.inf.

    See zea.Parameters.find_transmits() for how these values are used to classify transmits as "focused", "diverging" or "plane".

  • transmit_origins (ndarray) – The transmit origins of the transmit beams in meters of shape (n_tx, 3). This is the (x, y, z) position from which the beam is transmitted.

  • polar_angles (ndarray) – Polar angle theta of each transmit beam: the angle from the +z axis (physics convention). Signed in 2D, positive toward +x. In radians, of shape (n_tx,). See Angle and radius names.

  • time_to_next_transmit (ndarray | None) – The time in s between subsequent transmit events. Shape is either (n_frames, n_tx) or flat (n_frames * n_tx - 1,).

  • azimuth_angles (ndarray | None) – Azimuth angle phi of each transmit beam: the rotation around the z axis from +x (physics convention), zero for 2D imaging. Not the ultrasound “azimuth” (lateral) direction. In radians, of shape (n_tx,). See Angle and radius names.

  • rx_aperture_indices (ndarray | None) – Which probe element each receive channel of the channel data corresponds to, of shape (n_tx, n_rx) and integer dtype. Needed only when the receive aperture is a subset of the probe, such as a sliding window or a multiplexed front-end, since the mapping is otherwise not recoverable from the file. Omit it when every element receives on every transmit, where the mapping is the identity.

  • sound_speed (ndarray | float | None) – The speed of sound in meters per second.

  • tgc_gain_curve (ndarray | None) – The time-gain-compensation that was applied to every sample in the raw_data of shape (n_ax,). Divide by this curve to undo the TGC.

  • waveforms_one_way (ndarray | None) – One-way waveforms of shape (n_tx, .) as simulated by the Verasonics system. This is the waveform after being filtered by the transducer bandwidth once.

  • waveforms_two_way (ndarray | None) – Two-way waveforms of shape (n_tx, .) as simulated by the Verasonics system. This is the waveform after being filtered by the transducer bandwidth twice.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'azimuth_angles': {'description': 'Azimuth angle phi of each transmit beam: the rotation around the z axis from +x (physics convention), zero for 2D imaging. Not the ultrasound "azimuth" (lateral) direction.', 'unit': 'rad'}, 'center_frequency': {'description': 'Center frequency of the transmit pulse.', 'unit': 'Hz'}, 'demodulation_frequency': {'description': 'Demodulation frequency.', 'unit': 'Hz'}, 'focus_distances': {'description': 'Transmit focus distances. Positive = focused, negative = diverging (virtual source behind the array), ``np.inf`` = plane wave (preferred; ``0`` is also accepted).', 'unit': 'm'}, 'initial_times': {'description': 'A/D converter start times per transmit.', 'unit': 's'}, 'polar_angles': {'description': 'Polar angle theta of each transmit beam: the angle from the +z axis (physics convention). Signed in 2D, positive toward +x.', 'unit': 'rad'}, 'rx_aperture_indices': {'description': 'Probe element index for each receive channel of the channel data, shape (n_tx, n_rx). Required to interpret the channel axis when the receive aperture is a subset of the probe. Omit it when every element receives, where the mapping is the identity.', 'rare': True, 'unit': '–'}, 'sampling_frequency': {'description': 'Sampling frequency.', 'unit': 'Hz'}, 'sound_speed': {'description': 'Speed of sound.', 'unit': 'm/s'}, 't0_delays': {'description': 'Transmit delays per element.', 'unit': 's'}, 'tgc_gain_curve': {'description': 'Time-gain-compensation curve.', 'rare': True, 'unit': '–'}, 'time_to_next_transmit': {'description': 'Time between transmit events.', 'unit': 's'}, 'transmit_origins': {'description': 'Transmit beam origins (x, y, z).', 'unit': 'm'}, 'tx_apodizations': {'description': 'Transmit apodization per element, in [-1, 1]. 0 = element did not contribute, 1 = full contribution, negative = fired with opposite polarity.', 'unit': '–'}, 'waveforms_one_way': {'description': 'One-way transmit waveforms.', 'rare': True, 'unit': 'V'}, 'waveforms_two_way': {'description': 'Two-way transmit waveforms.', 'rare': True, 'unit': 'V'}}
azimuth_angles: ndarray | None = None
center_frequency: ndarray[Any, dtype[Any]] | float
demodulation_frequency: ndarray[Any, dtype[Any]] | float
focus_distances: ndarray
initial_times: ndarray
property n_el: int

Number of elements.

property n_tx: int

Number of transmits.

polar_angles: ndarray
rx_aperture_indices: ndarray | None = None
sampling_frequency: ndarray | float
sound_speed: ndarray | float | None = None
t0_delays: ndarray
tgc_gain_curve: ndarray | None = None
time_to_next_transmit: ndarray | None = None
transmit_origins: ndarray
tx_apodizations: ndarray
waveforms_one_way: ndarray | None = None
waveforms_two_way: ndarray | None = None
class zea.data.spec.Segmentation(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: BooleanMap

Segmentation data with per-pixel Cartesian coordinates.

Parameters:
  • values (ndarray) – The segmentation values of shape (n_frames, z, x, y, n_labels) for 3D (volumetric) data or (n_frames, z, x, n_labels) for 2D data, with type bool.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres, shape (*spatial_dims, 3) where spatial_dims matches the spatial (non-label) dimensions of values. The leading frame axis may be omitted to broadcast one coordinate grid across all frames.

  • labels (ndarray | None) – The labels corresponding to the segmentation values, where each unique value in the values corresponds to a label in this list of shape (n_labels,) and type str.

Note

To indicate that certain frames have no segmentation, add an explicit "unannotated" entry to labels and set values[..., unannotated_idx] to True for those frames (with all other label channels set to False). This keeps the shape uniform across frames while clearly distinguishing genuinely annotated frames from frames that were not labelled. For example:

labels = np.array(["unannotated", "LV_endo", "LV_myo", "LA"])
values = np.zeros((n_frames, H, W, 4), dtype=bool)
# mark all frames as unannotated by default
values[:, :, :, 0] = True
# for annotated frames, set unannotated channel to False
# and the appropriate label channel to True
values[ed_idx, :, :, 0] = False
values[ed_idx, :, :, 1:] = segmentation_mask  # shape (H, W, 3)
class zea.data.spec.ShearWaveElastographyMap(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: FloatMap

Shear-wave elastography data with per-pixel Cartesian coordinates.

Parameters:
  • values (ndarray) – The shear-wave elastography values in m/s of shape (n_frames, z, x, y) and type float32.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres.

class zea.data.spec.Signal(start_time_offset, *, sampling_frequency=None, timestamps=None)[source]

Bases: Spec

Base class for additional signals with timing metadata.

Parameters:
  • start_time_offset (ndarray | float) – Time offset in seconds between the first transmit event of the ultrasound acquisition and sample 0 of this data. Negative means this data starts before the first transmit event; positive means it starts after.

  • sampling_frequency (ndarray | float | None) – Sampling frequency in Hz for uniformly sampled data.

  • timestamps (ndarray | None) – Explicit sample timestamps in seconds of shape (T,), relative to sample 0. Must start at 0.

Exactly one of sampling_frequency or timestamps must be provided.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'sampling_frequency': {'description': 'Sampling frequency.', 'unit': 'Hz'}, 'start_time_offset': {'description': 'Time offset between the first transmit event of the ultrasound acquisition and sample 0 of this data. Negative means this data starts before the first transmit event; positive means it starts after.', 'unit': 's'}, 'timestamps': {'description': 'Explicit sample timestamps relative to sample 0.', 'unit': 's'}}
sampling_frequency: ndarray | float | None = None
start_time_offset: ndarray | float
timestamps: ndarray | None = None
class zea.data.spec.Signal1D(start_time_offset, samples, *, sampling_frequency=None, timestamps=None)[source]

Bases: Signal

One-dimensional sampled signal with timing metadata.

Parameters:
  • samples (ndarray) – Signal samples of shape (T) and type uint8 or float32 or int16 or complex64.

  • start_time_offset (ndarray | float) – Time offset in seconds between the first transmit event of the ultrasound acquisition and sample 0 of this data.

  • sampling_frequency (ndarray | float | None) – Sampling frequency in Hz for signal samples.

  • timestamps (ndarray | None) – Explicit signal timestamps in seconds of shape (T,), relative to sample 0.

Exactly one of sampling_frequency or timestamps must be provided.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'samples': {'description': 'Signal samples.', 'unit': '–'}, 'sampling_frequency': {'description': 'Sampling frequency.', 'unit': 'Hz'}, 'start_time_offset': {'description': 'Time offset between the first transmit event of the ultrasound acquisition and sample 0 of this data. Negative means this data starts before the first transmit event; positive means it starts after.', 'unit': 's'}, 'timestamps': {'description': 'Explicit sample timestamps relative to sample 0.', 'unit': 's'}}
samples: ndarray
class zea.data.spec.SignalND(start_time_offset, samples, *, sampling_frequency=None, timestamps=None)[source]

Bases: Signal

N-dimensional sampled signal with timing metadata.

Parameters:
  • samples (ndarray) – Signal samples of shape (T, …) and type uint8 or float32 or int16 or complex64.

  • start_time_offset (ndarray | float) – Time offset in seconds between the first transmit event of the ultrasound acquisition and sample 0 of this data.

  • sampling_frequency (ndarray | float | None) – Sampling frequency in Hz for signal samples.

  • timestamps (ndarray | None) – Explicit signal timestamps in seconds of shape (T,), relative to sample 0.

Exactly one of sampling_frequency or timestamps must be provided.

FIELD_METADATA: ClassVar[dict[str, Any]] = {'samples': {'description': 'Signal samples.', 'unit': '–'}, 'sampling_frequency': {'description': 'Sampling frequency.', 'unit': 'Hz'}, 'start_time_offset': {'description': 'Time offset between the first transmit event of the ultrasound acquisition and sample 0 of this data. Negative means this data starts before the first transmit event; positive means it starts after.', 'unit': 's'}, 'timestamps': {'description': 'Explicit sample timestamps relative to sample 0.', 'unit': 's'}}
samples: ndarray
class zea.data.spec.SosMap(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: FloatMap

Speed-of-sound map data with per-pixel Cartesian coordinates.

Parameters:
  • values (ndarray) – The speed-of-sound map values in m/s of shape (n_frames, z, x, y) and type float32.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres, shape (n_frames, z, x, 3) or (n_frames, z, x, y, 3). The leading frame axis may be omitted to broadcast one coordinate grid across all frames.

class zea.data.spec.Spec[source]

Bases: object

Base class for data specifications with schema validation.

Subclasses should define a SCHEMA class variable that specifies the expected dtype and shape for each field. The __post_init__ method will validate that the actual fields match the schema, including checking that dimensions with the same name have consistent sizes across fields.

FIELD_METADATA: ClassVar[dict[str, Any]]
RECEIVE_CHANNEL_FIELDS: ClassVar[tuple[str, ...]] = ('raw_data', 'aligned_data.values')
static create_dataset(group, field_name, value, compression=Blosc(cname='zstd', clevel=7, shuffle=2), chunk_axes=('n_frames',), dim_names=None)[source]

Create a dataset in the given group for the specified field and value, handling string and scalar values appropriately.

compression may be an h5py filter name (e.g. "lzf", "gzip") or a mapping of create_dataset keyword arguments, such as an hdf5plugin filter object (hdf5plugin.Blosc2(...)) or an explicit {"compression": "gzip", "compression_opts": 4}. Reading such a file back requires the corresponding filter to be available (for hdf5plugin filters, import hdf5plugin in the reading process).

When dim_names (the field’s schema "shape" entry, one tuple of dimension names or several alternatives) is provided, the chunk shape is derived from chunk_axes to match common subsampling patterns; see _resolve_chunks().

A lazy value — an h5py.Dataset or any other array-like whose contents are still on disk (see is_lazy_array()) — is copied slab by slab rather than materialised, so the peak memory is one slab instead of the whole array. A lazy string array is the exception and is read whole: zea never defers strings (they are channel labels and names, see zea.data.file._load_group_dict()), so the read is bounded by construction.

Return type:

None

classmethod fields()[source]

Return the names of all fields.

Return type:

tuple[str, ...]

classmethod get_dtype(field_name)[source]

Get the dtype of a field.

Return type:

Union[Tuple[type, ...], type]

classmethod optional_fields()[source]

Return the names of fields that have a default value.

Return type:

tuple[str, ...]

classmethod required_fields()[source]

Return the names of fields that have no default value.

Return type:

tuple[str, ...]

store_in_group(group, compression=Blosc(cname='zstd', clevel=7, shuffle=2), chunk_axes=('n_frames',), warn_missing_optional_fields=True)[source]

Store the data in the given group (e.g. hdf5 group).

Return type:

None

to_dict()[source]

Return this spec as a nested dictionary based on SCHEMA fields.

Nested specs are converted recursively.

Return type:

dict[str, Any]

warn_missing_optional_fields()[source]

Warn about optional fields that were not provided.

Fields flagged as "rare" in FIELD_METADATA are skipped: they are almost never set, so warning about them on every write is just noise.

class zea.data.spec.StrainPercentageMap(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: FloatMap

Strain map data with per-pixel Cartesian coordinates.

Parameters:
  • values (ndarray) – The strain values in % of shape (n_frames, z, x, y) and type float32.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres.

class zea.data.spec.Subject(id=None, type=None, age=None, sex=None, weight=None, genetic_strain=None, fat_percentage=None, bmi=None)[source]

Bases: Spec

Subject metadata associated with the study.

Parameters:
  • id (str | None) – Subject ID.

  • type (str | None) – Subject type, e.g. human, phantom, animal.

  • age (uint8 | None) – Subject age in years.

  • sex (str | None) – Subject sex.

  • weight (float32 | None) – Subject weight in kg.

  • genetic_strain (str | None) – Genetic strain of an animal subject, e.g. C57BL/6N.

  • fat_percentage (float32 | None) – Subject fat percentage.

  • bmi (float32 | None) – Subject body mass index in kg/m².

FIELD_METADATA: ClassVar[dict[str, Any]] = {'age': {'description': 'Subject age in years.', 'rare': True, 'unit': '–'}, 'bmi': {'description': 'Subject body mass index.', 'rare': True, 'unit': 'kg/m²'}, 'fat_percentage': {'description': 'Subject fat percentage.', 'rare': True, 'unit': '%'}, 'genetic_strain': {'description': 'Genetic strain (inbred line) of an animal subject, e.g. C57BL/6N.', 'rare': True, 'unit': '–'}, 'id': {'description': 'Subject ID. Needed for subject-wise splits.', 'unit': '–'}, 'sex': {'description': 'Subject sex.', 'rare': True, 'unit': '–'}, 'type': {'description': 'Subject type, e.g. human, phantom, animal.', 'unit': '–'}, 'weight': {'description': 'Subject weight.', 'rare': True, 'unit': 'kg'}}
age: uint8 | None = None
bmi: float32 | None = None
fat_percentage: float32 | None = None
genetic_strain: str | None = None
id: str | None = None
sex: str | None = None
type: str | None = None
weight: float32 | None = None
class zea.data.spec.TissueDopplerMap(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: FloatMap

Tissue Doppler data with per-pixel Cartesian coordinates.

Parameters:
  • values (ndarray) – The tissue Doppler values in m/s of shape (n_frames, z, x, y) and type float32.

  • coordinates (ndarray | None) – Per-pixel Cartesian positions in metres.

class zea.data.spec.TrackSpec(data=None, scan=None, label=None, transmit_only=False)[source]

Bases: Spec

A single acquisition track with its own data and scan parameters.

Used inside a multi-track FileSpec where different transmit sequences coexist in the same acquisition. The track_schedule on FileSpec specifies the global ordering of transmits across all tracks.

For multi-track files a human-readable label is required on every track so that users can identify which track is which (e.g. "focused" vs "planewave"). Further information can be provided in the description field of the parent FileSpec, if necessary. Single-track files may omit the label.

A track must carry at least one of data or scan. data may be left as None to describe a transmit-only track (one that records the transmit sequence via scan but stores no recorded data), but only when scan is provided and transmit_only=True is explicitly passed.

A transmit-only track is useful when we want to store information about a transmit event without any corresponding receive data, for example a shear wave push pulse or therapeutic ultrasound.

Parameters:
  • data (DataSpec | dict | None) – The data for this track. May be None for a transmit-only track (e.g. to store a shear wave push pulse), but only if scan is provided and transmit_only=True.

  • scan (ScanSpec | dict | None) – The scan parameters for this track. Required when raw_data is present in data, and required when data is None.

  • label (str | None) – Short human-readable name for this track (e.g. "focused" or "planewave"). Required when the parent FileSpec contains more than one track.

  • transmit_only (bool) – Must be explicitly set to True to construct a transmit-only track (data=None with scan provided).

FIELD_METADATA: ClassVar[dict[str, Any]] = {'data': {'description': 'Recorded data for this track; may be omitted for a transmit-only track.', 'unit': '–'}, 'label': {'description': 'Short human-readable track name.', 'rare': True, 'unit': '–'}, 'scan': {'description': 'Scan acquisition parameters for this track; required when raw_data is present in data, or when data is omitted.', 'unit': '–'}, 'transmit_only': {'description': 'Whether this track records only the transmit sequence with no corresponding receive data (e.g. a shear wave push pulse or therapeutic ultrasound).', 'rare': True, 'unit': '–'}}
data: DataSpec | dict | None = None
label: str | None = None
scan: ScanSpec | dict | None = None
store_in_group(group, compression=Blosc(cname='zstd', clevel=7, shuffle=2), chunk_axes=('n_frames',), warn_missing_optional_fields=True)[source]

Store data, scan, and label in the HDF5 group.

Return type:

None

transmit_only: bool = False
class zea.data.spec.UnsignedIntMap(values, coordinates=None, timestamps=None, start_time_offset=None, labels=None, description=None, unit=None, min=None, max=None)[source]

Bases: Map

Map data with uint8 pixel values and per-pixel Cartesian coordinates.

zea.data.spec.check_dtype(value, expected_dtype)[source]

Check if the dtype of a value matches the expected dtype, allowing for compatible types.

Works for numpy arrays, numpy scalars, and Python native types.

Return type:

None

zea.data.spec.check_track_rules(*, has_data, has_scan, transmit_only, has_raw)[source]

Raise InvalidZeaFileError if a track breaks one of the format’s rules.

Return type:

None

zea.data.spec.dim_names_for_key(key, ndim)[source]

Resolve a path into a zea file to one dimension name per axis of its array.

Lets a reader ask what does this axis mean — most usefully, which axis (if any) holds frames — without opening a file. The path is the same one zea.File.__getitem__() takes: "data/raw_data", "data/image/values", or the group "data/image", which resolves to the group’s values field. Dots and slashes are interchangeable and a tracks/track_N/ prefix is stripped.

Parameters:
  • key (str) – Path to a data array within the file.

  • ndim (int) – Rank of the array actually stored there, used to pick between the alternative shapes a field may declare (Image.values is 2-D or 3-D plus frames, say).

Return type:

tuple[str | None, ...] | None

Returns:

One name per axis, None for axes the spec gives no name (a literal size, such as the trailing 3 of coordinates). None instead of a tuple when the spec cannot say: the path is not part of the spec, no declared shape has this rank, or the matching shape uses a "..." wildcard, which leaves the meaning of the absorbed axes unknown.

Example

>>> from zea.data.spec import dim_names_for_key
>>> dim_names_for_key("data/raw_data", 5)
('n_frames', 'n_tx', 'n_ax', 'n_el', 'n_ch')
>>> dim_names_for_key("data/image", 3)
('n_frames', 'z', 'x')
>>> dim_names_for_key("probe/probe_geometry", 2)
('n_el', None)
>>> dim_names_for_key("custom/my_array", 3) is None
True
zea.data.spec.find_matched_shape(value, expected_shapes)[source]

Find the first expected shape specification that matches the shape of the value.

Return type:

tuple | None

zea.data.spec.is_array_like(value)[source]

Whether value is an n-dimensional array the spec can describe and store.

A numpy.ndarray, but also any object providing _ARRAY_ATTRIBUTES without holding its contents in memory — an h5py.Dataset, a zea.data.file.ChunkedDataset, and anything else that reads like one. Such a lazy array is validated from its metadata and copied slab by slab (see iter_slabs()), so a file can be rewritten without ever fitting in RAM.

Strings and numpy scalars are excluded: they carry a dtype and a shape of their own but are values, not arrays.

Return type:

bool

zea.data.spec.is_lazy_array(value)[source]

Whether value is an array whose contents are not (yet) in memory.

See is_array_like(). Reading one costs IO, so the spec only ever touches a lazy array’s metadata, and writing one goes through iter_slabs().

Anything that is not a numpy.ndarray keeps its contents elsewhere by definition; an ndarray does so only when it maps a file (see _maps_a_file()).

Return type:

bool

zea.data.spec.iter_slabs(array, max_bytes=None, chunks=None, split_axes=True)[source]

Iterate over array in slabs of at most max_bytes, as (selection, values).

The selections tile the array, so writing every values to dataset[selection] reproduces it exactly, and reducing them one by one reduces the whole array — all with only one slab in memory at a time. Works the same for a lazy array (each slab is a read) and for a numpy.ndarray (each slab is a view), so callers do not need to branch on where the data lives.

Parameters:
  • array (Any) – Any array-like (see is_array_like()).

  • max_bytes (int | None) – Memory budget for one slab, uncompressed, covering everything a slab holds at once — including the source buffer where the array converts on read (see _read_itemsize()). Read from MAX_SLAB_BYTES when not given, so that setting the module constant takes effect everywhere.

  • chunks (tuple[int, ...] | None) – The destination chunk shape, when copying into an HDF5 dataset; slab boundaries are aligned to it.

  • split_axes (bool) – Whether a slab may cover only part of an outer index when a single index exceeds max_bytes. Pass False when the slabs are reduced along an inner axis, which needs each outer index whole.

Yields:

tuple – (selection, values), where selection indexes array and values is the numpy.ndarray it selects.

zea.data.spec.match_shape(value, expected_shape)[source]

Check if the shape of a value matches the expected shape specification.

Return type:

bool

zea.data.spec.strip_track_prefix(key)[source]

Strip a leading tracks/track_N/ off a path into a zea file.

Turns a fully qualified path into the single-track shorthand zea.File.__getitem__() also accepts, so tracks/track_0/data/raw_data and data/raw_data can be treated alike. Paths without the prefix are returned unchanged.

Return type:

str

zea.data.spec.value_shape(value)[source]

Return the shape tuple for arrays (lazy ones included) and scalar values.

Return type:

tuple