confusius.io¶
io ¶
Loading and saving utilities for fUSI data.
Modules:
-
autc–Utilities for loading and converting AUTC DAT files.
-
echoframe–Utilities for loading and converting EchoFrame DAT files.
-
loadsave–Generic file loading and saving dispatcher.
-
nifti–Utilities for loading and saving NIfTI files.
-
scan–Utilities for loading Iconeus SCAN files.
-
utils–Miscellaneous I/O utility functions.
Classes:
-
AUTCDAT–Beamformed IQ data stored in AUTC DAT format.
-
AUTCDATsLoader–Load a beamformed IQ acquisition from a set of AUTC DAT files.
-
EchoFrameMetadata–Metadata extracted from an EchoFrame MAT file.
Functions:
-
check_path–Resolve full path and check its type.
-
convert_autc_dats_to_zarr–Convert AUTC DAT files to Zarr format compatible with Xarray.
-
convert_echoframe_dat_to_zarr–Convert an EchoFrame DAT file to Zarr format compatible with Xarray.
-
load–Load a fUSI DataArray from file, dispatching by extension.
-
load_echoframe_dat–Load an EchoFrame DAT file containing beamformed IQ data.
-
load_echoframe_metadata–Load acquisition metadata from an EchoFrame MAT file.
-
load_nifti–Load a NIfTI file as a lazy Xarray DataArray.
-
load_scan–Load an Iconeus SCAN file as a lazy Xarray DataArray.
-
save–Save a fUSI DataArray to file, dispatching by extension.
-
save_nifti–Save an Xarray DataArray to NIfTI format.
AUTCDAT ¶
Beamformed IQ data stored in AUTC DAT format.
Parameters:
-
(path¶str or Path) –Path to the AUTC DAT file.
-
(n_header_items¶int, default:10) –Number of header items to read from each block.
-
(header_dtype¶dtype_like, default:numpy.int32) –Data type used for header fields.
-
(data_dtype¶dtype_like, default:numpy.complex64) –Data type used for data fields.
Attributes:
-
path(Path) –Resolved path to the AUTC DAT file.
-
shape(tuple[int, int, int, int]) –Shape of the data in the AUTC DAT file in the format
(blocks, x, z, frames). -
n_blocks(int) –Number of frame blocks in the AUTC DAT file.
-
n_frames_per_block(int) –Number of frames per block in the AUTC DAT file.
-
acquisition_block_indices(ndarray) –Array of acquisition block indices contained in the AUTC DAT file.
AUTCDATsLoader ¶
Load a beamformed IQ acquisition from a set of AUTC DAT files.
Parameters:
-
(root¶str or Path) –Path to the root directory containing the AUTC DAT files.
-
(pattern¶str, default:"bf*part*.dat") –Glob pattern used to search for AUTC DAT files inside
root. -
(show_progress¶bool, default:True) –Whether to show progress during file indexing. If
False, no progress bars are displayed. -
(progress¶Progress, default:None) –External
rich.progress.Progressinstance to add tasks to. If provided andshow_progressisTrue, a task will be added to thisrich.progress.Progressinstance instead of creating a new progress bar withrich.progress.track. -
(track_kwargs¶dict, default:None) –Additional keyword arguments to pass to
rich.progress.trackif using internal progress tracking (only used ifshow_progressisTrueandprogressisNone).
Attributes:
EchoFrameMetadata ¶
Bases: TypedDict
Metadata extracted from an EchoFrame MAT file.
Attributes:
-
lateral_coords(ndarray) –Lateral coordinates in millimeters, cropped if the sequence uses ROI cropping.
-
axial_coords(ndarray) –Axial (depth) coordinates in millimeters, cropped if the sequence uses ROI cropping.
-
transmit_frequency(float) –Central frequency of the ultrasound probe in hertz.
-
probe_n_elements(int) –Number of probe transducer elements.
-
probe_pitch(float) –Inter-element pitch of the probe in millimeters.
-
speed_of_sound(float) –Speed of sound in meters per second.
-
plane_wave_angles(ndarray) –Angles at which tilted plane waves are emitted in degrees.
-
compound_sampling_frequency(float) –Sampling frequency of the compounded frames in hertz.
-
pulse_repetition_frequency(float) –Single plane wave pulse repetition frequency in hertz.
-
beamforming_method(str) –Beamforming method used (e.g.
"DAS").
check_path ¶
check_path(
path: Path | str | Any,
label: str = "path",
type: Literal["file", "dir", None] = None,
) -> Path
Resolve full path and check its type.
Parameters:
-
(path¶str or Path) –Path to check validity.
-
(label¶str, default:"path") –Name of the variable passed to
check_path, used in the error message. -
(type¶(file, dir), default:"file") –Type of path to check for. If
"file", checks that the path is a file. If"dir", checks that the path is a directory. If not provided, no type check is performed, meaning the path may not exist.
Returns:
-
Path–If successful, the path resolved to its full path.
Raises:
-
TypeError–If
pathcannot be cast to pathlib.Path. -
ValueError–If type is not
Noneand the path is not of the correct type.
convert_autc_dats_to_zarr ¶
convert_autc_dats_to_zarr(
dats_root: str | Path,
output_path: str | Path,
dats_pattern: str = "bf*part*.dat",
frames_per_chunk: int | None = None,
frames_per_shard: int | None = None,
batch_size: int = 100,
overwrite: bool = False,
zarr_kwargs: dict[str, Any] | None = None,
lateral_coords: ArrayLike | None = None,
axial_coords: ArrayLike | None = None,
transmit_frequency: float | None = None,
probe_n_elements: int | None = None,
probe_pitch: float | None = None,
sound_velocity: float | None = None,
plane_wave_angles: ArrayLike | None = None,
compound_sampling_frequency: float | None = None,
pulse_repetition_frequency: float | None = None,
beamforming_method: str | None = None,
skip_first_blocks: int = 0,
skip_last_blocks: int = 0,
block_times: ArrayLike | None = None,
show_progress: bool = True,
progress: Optional[Progress] = None,
track_kwargs: dict[str, Any] | None = None,
) -> Group
Convert AUTC DAT files to Zarr format compatible with Xarray.
Beamformed IQ data is converted to a Zarr group with an iq array of shape
(time, z, y, x) chunked along the first dimension. Coordinates are stored as
separate Zarr arrays following Xarray conventions, allowing the data to be opened
directly with xarray.open_zarr().
Parameters:
-
(dats_root¶str or Path) –Path to the directory containing AUTC DAT files.
-
(output_path¶str or Path) –Path where the Zarr group will be saved.
-
(dats_pattern¶str, default:"bf*part*.dat") –Glob pattern used to search for AUTC DAT files inside
dats_root. -
(frames_per_chunk¶int, default:None) –Number of frames to include in each Zarr chunk. If not provided, defaults to the number of frames per block in the AUTC DAT files.
-
(frames_per_shard¶int, default:None) –Number of frames to include in each shard. If provided, enables Zarr sharding to reduce the number of files on disk. Must be a multiple of
frames_per_chunk. If not provided, sharding is disabled. -
(batch_size¶int, default:100) –Number of blocks to process in each batch.
-
(overwrite¶bool, default:False) –Whether to overwrite existing Zarr group at the output path.
-
(zarr_kwargs¶dict, default:None) –Additional keyword arguments to pass to
zarr.create_arrayfor the main data array. -
(lateral_coords¶array_like, default:None) –Lateral coordinates in millimeters in the probe-relative coordinate system, with the origin at the center of the probe face. These define the x-axis positions. If not provided, voxel indices are stored instead and a warning is emitted.
-
(axial_coords¶array_like, default:None) –Axial (depth) coordinates in millimeters in the probe-relative coordinate system, with the origin at the center of the probe face. These define the y-axis positions. If not provided, voxel indices are stored instead and a warning is emitted.
-
(transmit_frequency¶float, default:None) –Central frequency of the ultrasound probe in hertz.
-
(probe_n_elements¶int, default:None) –Number of probe transducers.
-
(probe_pitch¶float, default:None) –Inter-element pitch of the probe in millimeters.
-
(sound_velocity¶float, default:None) –Speed of sound in meters per second.
-
(plane_wave_angles¶array_like, default:None) –Angles at which tilted plane waves are emitted in degrees.
-
(compound_sampling_frequency¶float, default:None) –Sampling frequency of the compounded frames in hertz.
-
(pulse_repetition_frequency¶float, default:None) –Pulse repetition frequency in hertz.
-
(beamforming_method¶str, default:None) –Beamforming method used (e.g.
"DAS"). -
(skip_first_blocks¶int, default:0) –Number of blocks to skip from the beginning of the acquisition. This is useful when the first blocks are known to be corrupted or unusable.
-
(skip_last_blocks¶int, default:0) –Number of blocks to skip from the end of the acquisition. This is useful when the last blocks are known to be corrupted or unusable.
-
(block_times¶(n_blocks_after_skip,) array_like, default:None) –Start time of each IQ block in seconds, for the retained blocks only. If provided, individual volume times will be computed and stored as a time coordinate. Requires
compound_sampling_frequencyto be provided. If not provided, time coordinate will be computed based oncompound_sampling_frequencyor set to frame indices. -
(show_progress¶bool, default:True) –Whether to show progress during conversion. If
False, no progress bars are displayed. -
(progress¶Progress, default:None) –External
rich.progress.Progressinstance to add tasks to. If provided andshow_progressisTrue, a task will be added to thisrich.progress.Progressinstance instead of creating a new progress bar withrich.progress.track. -
(track_kwargs¶dict, default:None) –Additional keyword arguments to pass to
rich.progress.trackif using internal progress tracking (only used ifshow_progressisTrueandprogressisNone).
Returns:
-
Group–The created Zarr group containing the
iqdata array and coordinate arrays. Can be opened directly withxarray.open_zarr().
Notes
The output Zarr group follows Xarray conventions and can be opened with::
import xarray as xr
ds = xr.open_zarr("output.zarr")
iq = ds["iq"]
Metadata attributes (e.g., transmit_frequency, sound_velocity) are stored
on the iq DataArray (accessible via iq.attrs), consistent with how
reduction functions return DataArrays with attributes.
The group contains:
iq: The main data array with dimensions(time, z, y, x).time: Time coordinate array.z: Elevation coordinate array (always[0.0]mm for 2D data).y: Axial (depth) coordinate array in probe-relative mm.x: Lateral coordinate array in probe-relative mm.
Spatial coordinates (z, y, x) follow the ConfUSIus probe-relative
coordinate system: physical distances in millimeters along each voxel axis, with the
origin at the center of the probe face. Unlike EchoFrame data (where coordinates are
embedded in the metadata file), AUTC data carries no spatial calibration, so
lateral_coords and axial_coords must be supplied by the caller. Omitting
them produces physically meaningless voxel-index coordinates.
convert_echoframe_dat_to_zarr ¶
convert_echoframe_dat_to_zarr(
dat_path: str | Path,
meta_path: str | Path,
output_path: str | Path,
dat_dtype: DTypeLike = complex64,
header_dtype: DTypeLike = uint64,
n_header_items: int = 5,
volumes_per_chunk: int | None = None,
volumes_per_shard: int | None = None,
batch_size: int = 100,
overwrite: bool = False,
zarr_kwargs: dict[str, Any] | None = None,
skip_first_blocks: int = 0,
skip_last_blocks: int = 0,
block_times: ArrayLike | None = None,
show_progress: bool = True,
progress: Progress | None = None,
track_kwargs: dict[str, Any] | None = None,
) -> Group
Convert an EchoFrame DAT file to Zarr format compatible with Xarray.
Beamformed IQ data is converted to a Zarr group with an iq array of shape
(time, z, y, x) chunked along the first dimension. Coordinates are stored as
separate Zarr arrays following Xarray conventions, allowing the data to be opened
directly with xarray.open_zarr().
Parameters:
-
(dat_path¶str or Path) –Path to the EchoFrame DAT file containing beamformed IQ data.
-
(meta_path¶str or Path) –Path to the EchoFrame sequence parameter file (MAT v7.3 / HDF5 format).
-
(output_path¶str or Path) –Path where the Zarr group will be saved.
-
(dat_dtype¶dtype_like, default:numpy.complex64) –Data type of the beamformed IQ data in the DAT file.
-
(header_dtype¶dtype_like, default:numpy.uint64) –Data type of the DAT file header.
-
(n_header_items¶int, default:5) –Number of items in the DAT file header.
-
(volumes_per_chunk¶int, default:None) –Number of volumes to include in each Zarr chunk. If not provided, defaults to the number of volumes per block from the raw file.
-
(volumes_per_shard¶int, default:None) –Number of volumes to include in each shard. If provided, enables Zarr v3 sharding to reduce the number of files on disk. Must be a multiple of
volumes_per_chunk. If not provided, sharding is disabled. -
(batch_size¶int, default:100) –Number of blocks to process in each batch.
-
(overwrite¶bool, default:False) –Whether to overwrite existing Zarr group at the output path.
-
(zarr_kwargs¶dict, default:None) –Additional keyword arguments to pass to
zarr.create_arrayfor the main data array. -
(skip_first_blocks¶int, default:0) –Number of blocks to skip from the beginning of the acquisition. This is useful when the first blocks are known to be corrupted or unusable.
-
(skip_last_blocks¶int, default:0) –Number of blocks to skip from the end of the acquisition. This is useful when the last blocks are known to be corrupted or unusable.
-
(block_times¶(n_blocks_after_skip,) array_like, default:None) –Start time of each IQ block in seconds, for the retained blocks only. If provided, individual volume times will be computed and stored as a time coordinate. Requires
compound_sampling_frequencyto be provided. If not provided, time coordinate will be computed based oncompound_sampling_frequencyor set to frame indices. -
(show_progress¶bool, default:True) –Whether to show progress during conversion. If
False, no progress bars are displayed. -
(progress¶Progress, default:None) –External
rich.progress.Progressinstance to add tasks to. If provided andshow_progressisTrue, a task will be added to thisrich.progress.Progressinstance instead of creating a new progress bar withrich.progress.track. -
(track_kwargs¶dict, default:None) –Additional keyword arguments to pass to
rich.progress.trackif using internal progress tracking (only used ifshow_progressisTrueandprogressisNone).
Returns:
-
Group–The created Zarr group containing the
iqdata array and coordinate arrays. Can be opened directly withxarray.open_zarr().
Notes
The output Zarr group follows Xarray conventions and can be opened with::
import xarray as xr
ds = xr.open_zarr("output.zarr")
iq = ds["iq"]
Metadata attributes (e.g., transmit_frequency, sound_velocity) are stored
on the iq DataArray (accessible via iq.attrs), consistent with how
reduction functions return DataArrays with attributes.
The group contains:
iq: The main data array with dimensions(time, z, y, x).time: Time coordinate array.z: Elevation coordinate array (always[0]for 2D data).y: Axial (depth) coordinate array (from metadata).x: Lateral coordinate array (from metadata).
load ¶
Load a fUSI DataArray from file, dispatching by extension.
Supported formats:
- NIfTI (
.nii,.nii.gz): loaded viaload_nifti. - SCAN (
.scan): loaded viaload_scan. - Zarr (
.zarr): opened viaxarray.open_zarrand a single variable is extracted. For loading the full dataset, usexarray.open_zarrdirectly.
Parameters:
-
(path¶str or Path) –Path to the file to load.
-
(variable¶str, default:None) –Zarr only. Name of the variable to extract as a DataArray. If not provided, the first variable in the dataset is returned.
-
(**kwargs¶Any, default:{}) –Additional keyword arguments forwarded to the underlying loader.
Returns:
-
DataArray–The loaded data.
Raises:
-
ValueError–If the file extension is not supported.
load_echoframe_dat ¶
load_echoframe_dat(
dat_path: str | Path,
meta_path: str | Path,
dat_dtype: DTypeLike = complex64,
header_dtype: DTypeLike = uint64,
n_header_items: int = 5,
) -> memmap
Load an EchoFrame DAT file containing beamformed IQ data.
EchoFrame spatial dimensions
EchoFrame stores data with (x, y, z) spatial ordering corresponding to
(lateral, elevation, axial) dimensions, which is different from the (z, y,
x) ordering used in ConfUSIus that corresponds to (elevation, axial, lateral).
The returned array maintains the EchoFrame ordering to avoid confusion, but
users should be aware of this when processing the data.
Parameters:
-
(dat_path¶str or Path) –Path to the EchoFrame DAT file containing beamformed IQ data.
-
(meta_path¶str or Path) –Path to the EchoFrame sequence parameter file (MAT v7.3 / HDF5 format).
-
(dat_dtype¶dtype_like, default:numpy.complex64) –Data type of the beamformed IQ data in the DAT file.
-
(header_dtype¶dtype_like, default:numpy.uint64) –Data type of the DAT file header.
-
(n_header_items¶int, default:5) –Number of items in the DAT file header.
Returns:
-
(blocks, volumes, x, y, z) numpy.memmap–Memory-mapped array containing the beamformed IQ data, where
blocksis the number of acquisitions blocks,volumesis the number of volumes per block,xis the lateral dimension,yis the elevation dimension, andzis the axial dimension.
load_echoframe_metadata ¶
load_echoframe_metadata(
meta_path: str | Path,
) -> EchoFrameMetadata
Load acquisition metadata from an EchoFrame MAT file.
Parameters:
Returns:
-
EchoFrameMATMetadata–Dictionary containing the extracted metadata fields.
Raises:
-
FileNotFoundError–If
meta_pathdoes not exist or is not a file.
load_nifti ¶
Load a NIfTI file as a lazy Xarray DataArray.
Loads NIfTI files using nibabel's proxy arrays for memory-efficient access, wrapping
the data in Dask arrays for chunked, parallel processing. The data is transposed to
ConfUSIus conventions with dimensions (time, z, y, x).
A BIDS-style JSON sidecar file (same name, .json extension) is loaded
automatically when present.
Parameters:
-
(path¶str or Path) –Path to the NIfTI file (
.niior.nii.gz). -
(chunks¶int or tuple[int, ...] or str or None, default:"auto") –How to chunk the array. Must be one of the following forms:
- A blocksize like
1000. - A blockshape like
(1000, 1000). - Explicit sizes of all blocks along all dimensions like
((1000, 1000, 500), (400, 400)). - A size in bytes, like
"100 MiB"which will choose a uniform block-like shape. - The word
"auto"to let Dask choose chunk sizes based on heuristics. Seedask.array.normalize_chunksfor more details on how chunk sizes are determined. -1orNoneas a blocksize indicate the size of the corresponding dimension.
- A blocksize like
Returns:
-
DataArray–Lazy DataArray with dimensions in ConfUSIus order. Data is wrapped in a Dask array for out-of-core computation.
Examples:
>>> import confusius as cf
>>> da = cf.io.load_nifti("brain.nii.gz")
>>> print(da.dims)
("time", "z", "y", "x")
Notes
Physical-to-world affines are stored in da.attrs["affines"], a dict keyed by
affine name. Each value is a 4×4 affine in ConfUSIus (z, y, x) convention that
maps physical coordinates (as stored in da.coords) to world-space
coordinates. Apply as da.attrs["affines"]["physical_to_sform"] @ np.array([pz, py,
px, 1.0]) to get [wz, wy, wx, 1], where pz, py, px come from
da.coords["z"], da.coords["y"], da.coords["x"] respectively.
Unlike the NIfTI affine (which maps voxel indices to world space), the
physical_to_* affines are invariant to any slicing or downsampling because they
operate on physical positions, not grid indices.
Affine selection follows NIfTI conventions:
- If
sform_code > 0: sform is used as the primary affine; a"physical_to_sform"entry is written. Whenqform_code > 0as well, a"physical_to_qform"entry is also stored as secondary. - Else, if only
qform_code > 0: qform is used as the primary affine; only"physical_to_qform"is written. - If both codes are zero: a warning is emitted, coordinates are built from
pixdimonly (origin 0, step = voxel size), and no"affines"entry is stored inda.attrs.
The raw integer form codes are stored as da.attrs["qform_code"] and
da.attrs["sform_code"] (only when > 0) so that a save/load roundtrip can
reproduce the original NIfTI header codes.
Voxel dimensions are stored in their native header units as a voxdim
attribute on each spatial coordinate array, consistent with the units
attribute of that coordinate.
load_scan ¶
Load an Iconeus SCAN file as a lazy Xarray DataArray.
SCAN files (.scan) are HDF5 files produced by IcoScan/NeuroScan. They contain
power Doppler data and spatial/temporal metadata for 2D, 3D, or 3D+t fUSI volumes.
The returned DataArray wraps an open h5py file handle via a Dask array. The
file remains open while the Dask graph is un-computed. Call .compute() before
closing the file, or keep the returned DataArray in scope to prevent the handle from
being garbage-collected.
Parameters:
-
(path¶str or Path) –Path to the SCAN file (
.scan). -
(chunks¶int or tuple[int, ...] or str or None, default:"auto") –Dask chunk specification passed to
dask.array.from_array. Accepted forms:- A blocksize like
1000. - A blockshape like
(1000, 1000). - Explicit sizes of all blocks like
((1000, 1000, 500), (400, 400)). - A size in bytes like
"100 MiB". "auto"to let Dask choose based on heuristics.-1orNonefor the full dimension size (no chunking).
- A blocksize like
Returns:
-
DataArray–Lazy DataArray with dimensions and coordinates:
2Dscan→(time, z, y, x).3Dscan→(pose, z, y, x).4Dscan→(time, pose, z, y, x).
All spatial coordinates are in millimeters. The
timecoordinate is in seconds. For4Dscan, apose_timenon-dimension coordinate of shape(time, pose)stores the actual per-pose acquisition timestamps.
Raises:
-
ValueError–If
pathdoes not exist or is not a file, or if theacquisitionModestored in the file is not one of"2Dscan","3Dscan", or"4Dscan".
Notes
The physical_to_lab affine stored in da.attrs["affines"] maps ConfUSIus physical
coordinates (z, y, x) to Iconeus lab coordinates (mm). Apply as
da.attrs["affines"]["physical_to_lab"] @ np.array([z, y, x, 1.0]). For multi-pose
files the shape is (npose, 4, 4); index with da.coords["pose"].values after
isel.
Provenance attributes are stored in da.attrs: scan_mode, subject, session,
scan, project, date, neuroscan_version, machine_sn.
save ¶
Save a fUSI DataArray to file, dispatching by extension.
Supported formats:
- NIfTI (
.nii,.nii.gz): saved viasave_nifti. - Zarr (
.zarr): saved viaxarray.DataArray.to_zarr.
Parameters:
-
(data_array¶DataArray) –DataArray to save.
-
(path¶str or Path) –Output path. The extension determines the format.
-
(**kwargs¶Any, default:{}) –Additional keyword arguments forwarded to the underlying saver.
Raises:
-
ValueError–If the file extension is not supported.
save_nifti ¶
save_nifti(
data_array: DataArray,
path: str | Path,
nifti_version: NiftiVersion = 1,
*,
physical_to_qform: NDArray[float64] | None = None,
physical_to_sform: NDArray[float64] | None = None,
qform_code: int | None = None,
sform_code: int | None = None,
) -> None
Save an Xarray DataArray to NIfTI format.
Saves the DataArray to a NIfTI file and always writes a BIDS-style JSON sidecar
alongside it. The data is transposed to NIfTI convention (x, y, z, time) before
saving.
Parameters:
-
(data_array¶DataArray) –DataArray to save.
-
(path¶str or Path) –Output path for the NIfTI file, with
.niior.nii.gzextension. If.nii.gzis used, the file will be saved in compressed format. -
(nifti_version¶(1, 2), default:1) –NIfTI format version to use. Version 2 is a simple extension to support larger files and arrays with dimension sizes greater than 32,767.
-
(physical_to_qform¶(4, 4) numpy.ndarray, default:None) –Affine mapping physical coordinates (as stored in the DataArray coordinates) to the NIfTI qform space, in ConfUSIus
(z, y, x)convention. When provided, takes precedence overdata_array.attrs["affines"]["physical_to_qform"]. When not provided, the value fromattrs["affines"]is used if present, otherwise a diagonal affine derived from voxel spacing is written. -
(physical_to_sform¶(4, 4) numpy.ndarray, default:None) –Affine mapping physical coordinates (as stored in the DataArray coordinates) to the NIfTI sform space, in ConfUSIus
(z, y, x)convention. When provided, takes precedence overdata_array.attrs["affines"]["physical_to_sform"]. When not provided, the value fromattrs["affines"]is used if present; if neither is available, no sform is written. -
(qform_code¶int, default:None) –NIfTI qform code to write. When provided, takes precedence over
data_array.attrs["qform_code"]. When not provided, the value fromattrs["qform_code"]is used if present; otherwise defaults to1. -
(sform_code¶int, default:None) –NIfTI sform code to write. When provided, takes precedence over
data_array.attrs["sform_code"]. When not provided, the value fromattrs["sform_code"]is used if present; otherwise defaults to1when a sform affine is available, or0when no sform affine is written.
Examples: