zea.beamform.admire¶

Aperture Domain Model Image REconstruction (ADMIRE).

ADMIRE is a model-based beamformer that suppresses off-axis and multipath (reverberation) clutter. Time-delayed channel data is split into short axial windows, each window is taken to the frequency domain, and at every frequency the aperture-domain signal (one complex value per element) is fitted with a linear model of the wavefronts that point scatterers would produce across the aperture. Scatterers inside a small region of interest (ROI) around the window center are kept; everything explained by scatterers outside the ROI is clutter and is discarded. The model is fitted with elastic-net regularized least squares, solved with cyclic coordinate descent.

The implementation is split in two parts:

  • generate_admire_models() precomputes the models with NumPy. They depend only on the imaging geometry (axial sampling, sound speed, center frequency, element pitch and sub-aperture size), so they are computed once and reused.

  • apply_admire() fits the models to channel data and reconstructs the decluttered channel data with Keras ops, so it runs (and JIT compiles) on every backend.

The beamformer is usually used through zea.ops.ADMIRE, which handles the data layout of a zea pipeline.

Note

The reference code and its default settings target focused, walked-aperture scans. Compounded plane-wave data works too, but may need retuned settings. Part of ADMIRE’s contrast gain over DAS acts as a stretch of the dynamic range, to which the gCNR (zea.metrics.gcnr()) is insensitive.

Important

This is a zea implementation of ADMIRE. For the original MATLAB, C and CUDA code of the Vanderbilt BEAM Lab, see VU-BEAM-Lab/ADMIRE.

Note

The model generation, its calibration constants and the model application are ported from the reference code, Copyright 2020 Christopher Khan, Kazuyuki Dei, Siegfried Schlunk and Brett Byram. The coordinate descent solver is ported from ccd_double_precision.c, Copyright 2020 Christopher Khan. Both are licensed under the Apache License 2.0; see the reference repository’s NOTICE file. The ICA is the FOBI code (ica.m) from Shlens’ tutorial, which the reference includes.

Changes from the reference: the code is translated to NumPy (model generation) and Keras ops (model fitting); all lines, windows and frequencies are fitted in one batched solve; IQ data is supported in addition to RF data; the phase of the ICA eigenvectors is fixed so the models are reproducible across platforms; and the wavenumber calibration table is matched to the nearest listed center frequency instead of exactly.

References

B. Byram, K. Dei, J. Tierney, and D. Dumont, “A Model and Regularization Scheme for Ultrasonic Beamforming Clutter Reduction,” IEEE Transactions on Ultrasonics, Ferroelectrics, and Frequency Control, vol. 62, no. 11, pp. 1913–1927, 2015. doi.org/10.1109/TUFFC.2015.007004

K. Dei, S. Schlunk, and B. Byram, “Computationally Efficient Implementation of Aperture Domain Model Image Reconstruction,” IEEE Transactions on Ultrasonics, Ferroelectrics, and Frequency Control, vol. 66, no. 10, pp. 1546–1559, 2019. doi.org/10.1109/TUFFC.2019.2924824

C. Khan, K. Dei, S. Schlunk, K. Ozgun, and B. Byram, “A Real-Time, GPU-Based Implementation of Aperture Domain Model Image REconstruction,” IEEE Transactions on Ultrasonics, Ferroelectrics, and Frequency Control, vol. 68, no. 6, pp. 2101–2116, 2021. doi.org/10.1109/TUFFC.2021.3056334

C. Khan and B. Byram, “GENRE (GPU Elastic-Net REgression): A CUDA-Accelerated Package for Massively Parallel Linear Regression with Elastic-Net Regularization,” Journal of Open Source Software, vol. 5, no. 54, p. 2644, 2020. doi.org/10.21105/joss.02644

B. Byram and M. Jakovljevic, “Ultrasonic Multipath and Beamforming Clutter Reduction: A Chirp Model Approach,” IEEE Transactions on Ultrasonics, Ferroelectrics, and Frequency Control, vol. 61, no. 3, pp. 428–440, 2014. doi.org/10.1109/TUFFC.2014.2928

J. Shlens, “A Tutorial on Independent Component Analysis,” arXiv preprint, 2014. arXiv:1404.2986

J.-F. Cardoso, “Source Separation Using Higher Order Moments,” in International Conference on Acoustics, Speech, and Signal Processing (ICASSP), pp. 2109–2112, 1989. doi.org/10.1109/ICASSP.1989.266878

Module Attributes

REFERENCE_WAVENUMBER_CALIBRATION

Wavenumber calibration values of the reference implementation, by transducer center frequency (Hz).

DEFAULT_WAVENUMBER_CALIBRATION

Calibration values the reference implementation uses for any other center frequency.

Functions

apply_admire(channel_data, models[, ...])

Remove clutter from time-delayed channel data with ADMIRE.

elastic_net_ccd(X, y, row_mask, alpha, ...)

Batched elastic-net regression with cyclic coordinate descent.

generate_admire_models(depths, sound_speed, ...)

Precompute the ADMIRE models for an imaging geometry.

Classes

ADMIREConfig([bandwidth, alpha, ...])

Settings of the ADMIRE model space and model fit.

ADMIREModels(models, roi_mask, ...[, ...])

Precomputed ADMIRE models, as made by generate_admire_models().

class zea.beamform.admire.ADMIREConfig(bandwidth=0.6, alpha=0.9, lambda_scaling_factor=0.0189, max_iterations=100000, tolerance=0.1, ica=True, min_num_elements=16, pulse_multiplier=1.0, frequency_band_scaling=1.2, wavenumber_calibration='reference', cal_shift=7.75e-06, distance_offset_shift=3.85e-05, win_tune=1.0, ellipsoid_constant_1=0.0, ellipsoid_constant_2=np.float64(0.0005000000000002221), lateral_limit_offset=0.001, roi_x=(-0.5, 0.0179, 0.5), roi_z=(-0.5, 0.143, 0.5), roi_distance_offset_spacing=0.0485, roi_distance_offset_limits=(-0.0008, 0.0004), outer_x=(-1.0, 1.4228, 1.0), outer_z=(0.0, 0.0, 0.7114, 1.0, 0.0, 0.05), outer_z_offset=0.0, outer_distance_offset_spacing=0.1211, outer_distance_offset_limits=(-0.008, 0.0032), predictor_chunk_size=32768, max_cache_bytes=1073741824)[source]¶

Bases: object

Settings of the ADMIRE model space and model fit.

The defaults are those of the reference implementation. Most users only touch the fit settings (alpha, lambda_scaling_factor) and the aperture settings; the model-space scaling factors and calibration offsets are empirical and best left alone.

Lateral and axial model-space positions are given as multiples of the lateral resolution res_lat (estimated per window and frequency) and of the axial resolution res_axl = 2 * res_lat. Ranges are (min, spacing, max).

Parameters:
  • bandwidth (float) – Fractional bandwidth of the transmitted pulse. Sets the STFT window length and the fitted frequency band.

  • alpha (float) – Elastic-net mixing parameter in [0, 1]: 1 is the lasso, 0 is ridge regression.

  • lambda_scaling_factor (float) – The regularization strength of each fit is lambda_scaling_factor * rms(y).

  • max_iterations (int) – Maximum number of coordinate descent sweeps.

  • tolerance (float) – Coordinate descent stops once the largest change of a (standardized) coefficient within a sweep, squared and divided by the number of observations, falls below this value.

  • ica (bool) – Replace each of the ROI and outer models by its independent components (FOBI), which shrinks each to (at most) as many predictors as there are elements. This is what makes ADMIRE tractable on a GPU; False uses the full models, which can hold hundreds of thousands of predictors.

  • min_num_elements (int) – Smallest sub-aperture that aperture growth may select.

  • pulse_multiplier (float) – Scales the STFT window length (one pulse full-width at half-maximum by default).

  • frequency_band_scaling (float) – The fitted band is f0 +- 0.5 * frequency_band_scaling * bandwidth * f0.

  • wavenumber_calibration (str | tuple | None) – Per-frequency wavenumber scaling. "reference" looks the values up by center frequency like the reference implementation; a tuple gives them explicitly; None disables calibration.

  • cal_shift (float) – Calibration depth offset in meters.

  • distance_offset_shift (float) – Calibration distance offset in meters.

  • win_tune (float) – Scales the half pulse length in the window amplitude model.

  • ellipsoid_constant_1 (float) – Pads the ROI acceptance ellipse, in meters.

  • ellipsoid_constant_2 (float) – Pads the ellipse that the outer model excludes, in meters.

  • lateral_limit_offset (float) – Extends the outer model laterally beyond the sub-aperture, in meters.

  • roi_x (tuple) – ROI lateral positions, in units of res_lat.

  • roi_z (tuple) – ROI depth positions around the window center, in units of res_axl.

  • roi_distance_offset_spacing (float) – Spacing of the ROI distance offsets, in wavelengths.

  • roi_distance_offset_limits (tuple) – Min and max ROI distance offsets in meters.

  • outer_x (tuple) – Outer-model lateral positions; min and max are multiples of the lateral limit, the spacing is in units of res_lat.

  • outer_z (tuple) – Outer-model depth positions as (min_z_center, min_res_axl, spacing_res_axl, max_z_center, max_res_axl, max_z_center_extra); the minimum is min_z_center * z_c + min_res_axl * res_axl + outer_z_offset and the maximum (max_z_center + max_z_center_extra) * z_c + max_res_axl * res_axl.

  • outer_z_offset (float) – Constant added to the minimum outer-model depth, in meters.

  • outer_distance_offset_spacing (float) – Spacing of the outer distance offsets, in wavelengths.

  • outer_distance_offset_limits (tuple) – Min and max outer distance offsets in meters.

  • predictor_chunk_size (int) – Number of predictors generated at once, which bounds the memory use of model generation.

  • max_cache_bytes (int) – Models up to this size are kept in memory between the two passes of the ICA; larger ones are generated twice.

alpha: float = 0.9¶
bandwidth: float = 0.6¶
cal_shift: float = 7.75e-06¶
distance_offset_shift: float = 3.85e-05¶
ellipsoid_constant_1: float = 0.0¶
ellipsoid_constant_2: float = np.float64(0.0005000000000002221)¶
frequency_band_scaling: float = 1.2¶
ica: bool = True¶
lambda_scaling_factor: float = 0.0189¶
lateral_limit_offset: float = 0.001¶
max_cache_bytes: int = 1073741824¶
max_iterations: int = 100000¶
min_num_elements: int = 16¶
outer_distance_offset_limits: tuple = (-0.008, 0.0032)¶
outer_distance_offset_spacing: float = 0.1211¶
outer_x: tuple = (-1.0, 1.4228, 1.0)¶
outer_z: tuple = (0.0, 0.0, 0.7114, 1.0, 0.0, 0.05)¶
outer_z_offset: float = 0.0¶
predictor_chunk_size: int = 32768¶
pulse_multiplier: float = 1.0¶
replace(**changes)[source]¶

Return a copy with some settings changed.

Return type:

ADMIREConfig

roi_distance_offset_limits: tuple = (-0.0008, 0.0004)¶
roi_distance_offset_spacing: float = 0.0485¶
roi_x: tuple = (-0.5, 0.0179, 0.5)¶
roi_z: tuple = (-0.5, 0.143, 0.5)¶
tolerance: float = 0.1¶
wavenumber_calibration: str | tuple | None = 'reference'¶
win_tune: float = 1.0¶
class zea.beamform.admire.ADMIREModels(models, roi_mask, aperture_mask, window_starts, window_length, fft_length, frequency_bins, frequencies, element_positions, analytic, config=<factory>, depths=None, sound_speed=None, center_frequency=None, f_number=None)[source]¶

Bases: object

Precomputed ADMIRE models, as made by generate_admire_models().

There is one model per STFT window and selected frequency. Models are zero padded to a common number of rows (elements) and columns (predictors), which leaves the fit unchanged: padded columns get zero coefficients and padded rows carry no data.

Parameters:
  • models (ndarray) – Complex models of shape (n_windows, n_freqs, n_elements, n_predictors), with unit-norm columns.

  • roi_mask (ndarray) – Boolean mask of shape (n_windows, n_freqs, n_predictors), true for the ROI predictors used to reconstruct the signal.

  • aperture_mask (ndarray) – Boolean mask of shape (n_windows, n_elements) with the elements that aperture growth keeps in each window.

  • window_starts (ndarray) – Axial sample index where each window starts.

  • window_length (int) – Number of axial samples per window.

  • fft_length (int) – Zero-padded DFT length of a window.

  • frequency_bins (ndarray) – DFT bin of each selected frequency.

  • frequencies (ndarray) – Physical frequency of each selected bin in Hz.

  • element_positions (ndarray) – Lateral element positions of the sub-aperture, relative to its center, in meters.

  • analytic (bool) – Whether the models are made for analytic (IQ) data, where only the band around the center frequency is present, or for real RF data, where negative frequencies mirror the positive ones.

  • config (ADMIREConfig) – Settings used to generate the models.

  • depths (ndarray | None) – Depths (m) the models were generated for.

  • sound_speed (float | None) – Speed of sound (m/s) the models were generated for.

  • center_frequency (float | None) – Center frequency (Hz) the models were generated for.

  • f_number (float | None) – F-number of aperture growth the models were generated for.

analytic: bool¶
aperture_mask: ndarray¶
center_frequency: float | None = None¶
config: ADMIREConfig¶
depths: ndarray | None = None¶
element_positions: ndarray¶
f_number: float | None = None¶
fft_length: int¶
frequencies: ndarray¶
frequency_bins: ndarray¶
models: ndarray¶
property n_elements: int¶

Number of elements in the sub-aperture.

property n_windows: int¶

Number of STFT windows.

roi_mask: ndarray¶
sound_speed: float | None = None¶
window_length: int¶
window_starts: ndarray¶
zea.beamform.admire.DEFAULT_WAVENUMBER_CALIBRATION = (1.135, 0.995, 0.925, 0.905)¶

Calibration values the reference implementation uses for any other center frequency.

zea.beamform.admire.REFERENCE_WAVENUMBER_CALIBRATION = {1818200: (1.32, 0.995, 0.835, 0.81), 2083300: (1.32, 1.0, 0.845, 0.825), 2500000: (1.315, 0.995, 0.835, 0.81), 3000000: (1.31, 0.995, 0.835, 0.805), 3125000: (1.305, 0.985, 0.825, 0.79), 3500000: (1.29, 0.99, 0.835, 0.815), 3600000: (1.315, 1.01, 0.855, 0.815), 4000000: (1.29, 0.99, 0.845, 0.82), 4500000: (1.325, 1.025, 0.87, 0.825), 5000000: (1.29, 0.995, 0.85, 0.835), 5208000: (1.145, 0.995, 0.895, 0.865), 5500000: (1.28, 0.995, 0.855, 0.845), 6500000: (1.31, 1.04, 0.89, 0.84), 7500000: (1.275, 0.975, 0.835, 0.82), 7800000: (1.295, 1.0, 0.855, 0.825), 7813000: (1.295, 1.0, 0.855, 0.825)}¶

Wavenumber calibration values of the reference implementation, by transducer center frequency (Hz). Entry i scales the wavenumber of the i-th selected frequency of every STFT window.

zea.beamform.admire.apply_admire(channel_data, models, window_batch_size=None)[source]¶

Remove clutter from time-delayed channel data with ADMIRE.

Port of apply_ADMIRE_models_CPU.m: each STFT window is taken to the frequency domain, the models are fitted at every selected frequency, the signal is rebuilt from the ROI predictors only and taken back to the time domain. Frequencies outside the fitted band are removed. Samples that are not covered by a window (at the end of the axial range) are passed through unchanged.

Parameters:
  • channel_data (Tensor) – Delayed channel data of shape (n_z, n_lines, n_elements, n_ch): for every image line, the sub-aperture centered on that line. n_ch is 1 for RF data and 2 for IQ data, matching models.analytic.

  • models (ADMIREModels) – Models from generate_admire_models().

  • window_batch_size (int | None) – Number of STFT windows fitted at once, which bounds memory use. Defaults to all windows at once.

Returns:

Decluttered channel data with the shape of channel_data.

Return type:

Tensor

zea.beamform.admire.elastic_net_ccd(X, y, row_mask, alpha, lambda_scaling_factor, tolerance, max_iterations)[source]¶

Batched elastic-net regression with cyclic coordinate descent.

Port of ccd_double_precision.c. For every problem it minimizes

\[\frac{1}{2N} \lVert \tilde{y} - X \beta \rVert_2^2 + \tilde{\lambda} \left( \alpha \lVert \beta \rVert_1 + \frac{1 - \alpha}{2} \lVert \beta \rVert_2^2 \right),\]

with \(\tilde{y} = y / \sigma_y\) and \(\tilde{\lambda} = \lambda / \sigma_y\), where \(\lambda\) is lambda_scaling_factor times the RMS of \(y\), and returns \(\sigma_y \beta\). The columns of X must have unit norm (or be zero). Each problem stops after the first sweep in which the largest change of its coefficients falls below tolerance, as in the reference; the loop runs until every problem has stopped.

Parameters:
  • X (Tensor) – Design matrices of shape (..., N, P).

  • y (Tensor) – Observations of shape (..., B, N): B right-hand sides share each design matrix.

  • row_mask (Tensor) – Mask of shape (..., N) with the rows that hold observations. Masked-out rows of X and y must be zero.

  • alpha (float) – Elastic-net mixing parameter.

  • lambda_scaling_factor (float) – Regularization strength relative to the RMS of y.

  • tolerance (float) – Convergence tolerance.

  • max_iterations (int) – Maximum number of sweeps over all coefficients.

Returns:

Coefficients of shape (..., B, P).

Return type:

Tensor

zea.beamform.admire.generate_admire_models(depths, sound_speed, center_frequency, pitch, n_elements, f_number=2.0, analytic=True, start_depth=None, end_depth=None, config=None, verbose=False, n_workers=None)[source]¶

Precompute the ADMIRE models for an imaging geometry.

Port of ADMIRE_models_generation_main.m and the functions it calls. The channel data that the models are applied to must be time-delayed (focused at every depth) and sampled at the uniformly spaced depths.

Generation is done once per geometry, on the CPU, and takes from seconds to minutes: deep windows have outer models with hundreds of thousands of predictors. The result is cached on disk (see zea.internal.cache).

Parameters:
  • depths (array-like) – Uniformly spaced depths (m) of the axial samples of the delayed channel data, i.e. the z-axis of the beamforming grid.

  • sound_speed (float) – Speed of sound in m/s.

  • center_frequency (float) – Transmit center frequency in Hz.

  • pitch (float) – Element pitch in meters.

  • n_elements (int) – Number of elements in the sub-aperture that is fitted for each image line.

  • f_number (float) – F-number of aperture growth; the sub-aperture is limited to depth / f_number (but at least config.min_num_elements elements). 0 disables aperture growth.

  • analytic (bool) – True for analytic (IQ) data, False for real RF data.

  • start_depth (float | None) – Only windows starting at or below this depth are processed. Defaults to the first depth.

  • end_depth (float | None) – Only windows ending at or above this depth are processed. Defaults to the last depth.

  • config (ADMIREConfig | None) – Model and fit settings. Defaults to the reference settings.

  • verbose (bool) – Show a progress bar.

  • n_workers (int | None) – Number of processes that generate windows in parallel. Defaults to one. Does not affect the result (up to floating-point rounding) or its cache key.

Returns:

The models of every STFT window and selected frequency.

Return type:

ADMIREModels