Ultrasound Image Formation Plugin

The Ultrasound Image Formation Plugin (USImageFormation) provides algorithms, stream interfaces, and data structures for the acquisition, recording, and processing of ultrasound data in low-level use cases.

Introduction

The Ultrasound Image Formation Plugin is an extension to the ImFusion SDK designed to facilitate working with low-level ultrasound systems. It provides tools and functionalities for:

  • Acquisition Control: Programming acquisition sequences of ultrasound systems with low-level programming capabilities and low-level data access.

  • Acquisition: Acquisition of per-element raw channel data.

  • Raw Data Access: Access and process raw channel data for advanced signal processing and research purposes.

  • Real-Time Processing: Perform live processing of ultrasound data up to final B-Mode images for immediate feedback and visualization.

  • Offline Processing: Load and process recorded data (from any stage) for post-acquisition studies.

  • Access to intermediate data: Perform bespoke processing within the normal pipeline, or to create additional outputs.

Usage

The functionality of the USImageFormation Plugin is accessible in the ImFusion Suite, the C++ SDK, and the Python API.

ImFusion Suite

The USImageFormation Plugin is integrated into the ImFusion Suite, allowing users to access its features through the graphical user interface. See the User documentation.

Python

The USImageFormation Plugin can be used in Python together with the ImFusion Python API. It can be used to process recorded ultrasound data, or to configure and control an input stream, record sequences from it, and then process the data. Live visualization of the data is not currently supported from Python.

See the Python example USImgFormationPlugin/python-examples/processing_recorded_data.ipynb for a complete example of how to use the USImageFormation Plugin in Python to process recorded data.

import imfusion as imf
import imfusion.ultrasound_image_formation as usi
# Load recorded RF ultrasound channel data from an imfusion file
[rf_channel_data] = imf.load("simus_logo.imf")

# Process the RF channel data using the USImageFormation Plugin
filtered = usi.filter_channel_data(rf_channel_data)
iqdemod = usi.iq_demodulation(filtered)
beamformed = usi.beamforming(iqdemod)
envelope = usi.envelope_detection(beamformed, reference_amplitude=100000.0, dynamic_range=45.0)
scanconverted = imf.execute_algorithm('USExp.ScanConversion2', [envelope])[0]

C++ SDK

The USImageFormation Plugin is also available in the ImFusion C++ SDK, allowing developers to integrate ultrasound image formation capabilities into their applications. See the C++ SDK documentation for more details on how to use the plugin in C++ applications.

API Reference

class imfusion.ultrasound_image_formation.AcquisitionSequence(self: AcquisitionSequence)

Bases: pybind11_object

Collection of frame acquisition parametrizations that form a sequence. This is the configuration used to program the ultrasound system. If there are multiple FrameAcquisitions, the order of execution of their individual events can be defined, if desired.

property frame_acquisitions

List of FrameAcquisitions in the sequence

class imfusion.ultrasound_image_formation.BeamformingRois(self: BeamformingRois)

Bases: DataComponentBase

Regions of interest for beamforming, one per event. Scanline ROIs are lines (two points); ultrafast ROIs are polygons.

__getitem__(self: BeamformingRois, index: int) list[ndarray[numpy.float64[2, 1]]]

Get the ROI at the given index.

add(self: BeamformingRois, roi: list[ndarray[numpy.float64[2, 1]]]) None

Add a new ROI to the list.

roi(self: BeamformingRois, index: int) list[ndarray[numpy.float64[2, 1]]]

Get the ROI at the given index.

property size

Number of ROIs.

class imfusion.ultrasound_image_formation.ChannelDataLayout(*args, **kwargs)

Bases: DataComponentBase

Layout of ultrasound channel data in a 3D image.

Function overload documentation:

__init__(self: ChannelDataLayout) None

Default layout (slow time, fast time, channels)

__init__(self: ChannelDataLayout, arg0: Axis, arg1: Axis, arg2: Axis) None

Custom layout with semantics for the first three axis in data

class Axis(self: Axis, value: int)

Bases: pybind11_object

Members:

CHANNELS : The axis with the individual channels of the ultrasound data.

FAST_TIME : The axis of “depth-wise” data points from the same channel and the same pulse echo event.

SLOW_TIME : The axis for the individual pulse echo events.

CHANNELS = <Axis.CHANNELS: 0>
FAST_TIME = <Axis.FAST_TIME: 1>
SLOW_TIME = <Axis.SLOW_TIME: 2>
property name
property value
axis_index(self: ChannelDataLayout, axis: Axis) int

Get the index the axis with the given semantics

axis_semantics(self: ChannelDataLayout, index: int) Axis

Get the semantics of the axis at the given index

property channels_axis_index

Get the index of the channels axis

property fast_time_axis_index

Get the index of the fast time axis

property slow_time_axis_index

Get the index of the slow time axis

class imfusion.ultrasound_image_formation.FilterType(self: FilterType, value: int)

Bases: pybind11_object

Members:

LOWPASS : Lowpass filter

HIGHPASS : Highpass filter

BANDPASS : Bandpass filter

BANDPASS = <FilterType.BANDPASS: 2>
HIGHPASS = <FilterType.HIGHPASS: 1>
LOWPASS = <FilterType.LOWPASS: 0>
property name
property value
class imfusion.ultrasound_image_formation.FrameAcquisition(*args, **kwargs)

Bases: DataComponentBase

Metadata for the sequence of pulse echo events that are recorded in channel data and form the basis for an image, e.g. x scanlines covering the region of interest.

Function overload documentation:

__init__(self: FrameAcquisition) None
__init__(self: FrameAcquisition, arg0: Transducer, arg1: FrameParameters) None
__init__(self: FrameAcquisition, arg0: Transducer, arg1: list[PulseEchoEvent]) None
property events

The list of PulseEchoEvents in the sequence

property transducer

Transducer used for exection of the sequence

class imfusion.ultrasound_image_formation.FrameParameters(self: FrameParameters)

Bases: pybind11_object

high-level parameters for sequence creation

class DivergingWaveParameters(self: DivergingWaveParameters)

Bases: pybind11_object

high-level parameters for diverging wave sequence creation

property number_apertures

Number of apertures to use for diverging wave imaging. The apertures are evenly spaced on the transducer surface.

property number_events_per_aperture

Number of diverging wave events per aperture. For each aperture, the diverging wave angles are evenly spaced.

property steering_angle_range

Range of diverging wave angles ([rad])

property virtual_source_distance

Virtual source distance ([mm])

class FocusedParameters(self: FocusedParameters)

Bases: pybind11_object

high-level parameters for focused sequence creation

property focal_depth

Focal depth ([mm])

property number_focused_beams_total

Number of focused beams. They are evenly spaced on the transducer surface.

property steering_angle

Steering ([rad])

class PlaneWaveParameters(self: PlaneWaveParameters)

Bases: pybind11_object

high-level parameters for plane wave sequence creation

property number_apertures

Number of apertures to use for plane wave imaging. The apertures are evenly spaced on the transducer surface.

property number_events_per_aperture

Number of plane wave events per aperture. For each aperture, the plane wave angles are evenly spaced.

property plane_angle_range

Range of plane wave angles ([rad])

property diverging_wave

Diverging wave imaging parameters

property end_depth

Desired imaging depth in mm

property event_type

Type of events in this FrameAcquisition

property focused

Focused imaging parameters

property max_receive_aperture

desired receive aperture size (number of elements)

property max_transmit_aperture

desired transmit aperture size (number of elements)

property plane_wave

Plane wave imaging parameters

property pulse_frequency

Frequency of the transmit pulse in Hertz

property pulse_length

Transmit pulse length, expressed in cycles (is usually a multiple of 0.5)

property receive_sampling_frequency

Rate at which the channel data is sampled in Hertz

property speed_of_sound

Speed of sound to assume for delay calculations in mm/s

class imfusion.ultrasound_image_formation.PulseEchoEvent(self: PulseEchoEvent)

Bases: DataComponentBase

Describes one ultrasound pulse echo event. Metadata for ultrasound channel data.

class Receive

Bases: pybind11_object

Channel data reception configuration

property aperture_first

first index of the transducer elements used for recording channel data.

property aperture_last

last index of the transducer elements used for recording channel data

property element_to_channel_mapping

The element to (ADC) channel muxing settings for the recieving aperture

property end_time

Receive end time (relative to time-zero) in [s])

property sampling_frequency

Rate at which the channel data is sampled in Hertz

property start_time

Receive start time (relative to time-zero) in [s])

class Transmit

Bases: pybind11_object

Transmit pulse configuration

calculate_delays(self: Transmit, arg0: Transducer) list[float]

Returns the transmit delays (in [s]) to apply to the transmitting aperture

property aperture_first

first index of the transducer elements used for the transmission

property aperture_last

last index of the transducer elements used for the transmission

property event_type

Transmit pulse type

property pulse_frequency

Frequency of the transmit pulse in Hertz

property pulse_length

Transmit pulse length, expressed in cycles (is usually a multiple of 0.5)

property speed_of_sound

Speed of sound to assume for delay calculations in mm/s

property time_zero_point

Point on the transducer that marks the start of the receive time when the exciting wave passes through it

property wave_fiducial

Plane normal. For diverging wave: Virtual source.

Type:

The point defining the wavefront shape. For focused

Type:

Focal point. For plane wave

property wave_start

Center of transmitting aperture.

Type:

Start point of the wave. Used to determine the region for which to beamform. For focused

Type:

scanline start. For plane wave and diverging wave

static create_diverging_wave(transducer: Transducer, wave_start: ndarray[numpy.float64[3, 1]], virtual_source: ndarray[numpy.float64[3, 1]], max_transmit_aperture: int, max_receive_aperture: int) PulseEchoEvent

Create a PulseEchoEvent for a plane wave emission. Fills only aperture and transmit wave points.

static create_focused(transducer: Transducer, beam_start: ndarray[numpy.float64[3, 1]], focal_point: ndarray[numpy.float64[3, 1]], max_transmit_aperture: int, max_receive_aperture: int) PulseEchoEvent

Create a PulseEchoEvent for a focused emission. Fills only aperture and transmit wave points.

static create_plane_wave(transducer: Transducer, wave_start: ndarray[numpy.float64[3, 1]], plane_wave_angle: float, max_transmit_aperture: int, max_receive_aperture: int) PulseEchoEvent

Create a PulseEchoEvent for a plane wave emission. Fills only aperture and transmit wave points.

property receive

Channel data reception configuration

property transmit

Transmit pulse configuration

class imfusion.ultrasound_image_formation.SimulatedChannelDataStream(self: SimulatedChannelDataStream)

Bases: ImageStream

Testing / debugging stream of channel data, containing the echo of one scatterer. The FrameAcquisition, Transducer, and echo, transmit, and noise amplitudes are configurable.

class PhantomType(self: PhantomType, value: int)

Bases: pybind11_object

Members:

SINGLE_SCATTERER : One scatterer at the origin

GRID_5MM : Multiple scatterers in a grid with 5mm spacing

GRID_5MM = <PhantomType.GRID_5MM: 1>
SINGLE_SCATTERER = <PhantomType.SINGLE_SCATTERER: 0>
property name
property value
get_next_acquisition(self: SimulatedChannelDataStream) list[tuple[SharedImage, DataComponentList]]
Returns the next image that would have been emitted on the stream synchronously, together with its associated components.

The image will not be emitted on the stream anymore, so if mixed with streaming it changes the order of emitted images. This is useful for testing consumers of channel data.

property acquisition_sequence

acquisition sequence for the stream

property echo_amplitude

Amplitude of the echo

property noise_amplitude

Amplitude of the noise

property phantom_origin

Origin of the phantom in mm, relative to the transducer origin

property phantom_type

Phantom type for the stream

property target_frame_rate

Target frame rate for the stream

property transmit_amplitude

Amplitude of the transmit pulse

class imfusion.ultrasound_image_formation.Transducer

Bases: DataComponentBase

Low level transducer information, used for programming US firings and channel data processing.

static create_convex(number_elements: int, pitch: float, radiusCurvature: float) Transducer

Creates a convex transducer with the given number of elements, their pitch and the radius of curvature (both in mm).

static create_linear(number_elements: int, pitch: float) Transducer

Creates a linear transducer with the given number of elements and element pitch (in mm).

property element_positions

Positions of the transducer element centers, relative to the probe surface center.

property is_convex
property is_linear
property num_elements

Number of elements in the transducer.

property pitch

Element pitch in mm.

property radius_curvature

Radius of curvature of the transducer in mm, if it is convex.

class imfusion.ultrasound_image_formation.WavefrontShape(self: WavefrontShape, value: int)

Bases: pybind11_object

Members:

FOCUSED : Focused wavefront shape

PLANE_WAVE : Plane wavefront shape

DIVERGING_WAVE : Diverging wavefront shape

DIVERGING_WAVE = <WavefrontShape.DIVERGING_WAVE: 2>
FOCUSED = <WavefrontShape.FOCUSED: 0>
PLANE_WAVE = <WavefrontShape.PLANE_WAVE: 1>
property name
property value
imfusion.ultrasound_image_formation.beamforming(channel_data: SharedImageSet, *, f_number: float = 1.0, coherent_compounding: bool = True, output_size: ndarray[numpy.int32[2, 1]] = array([512, 512], dtype=int32), output_value_scaling: float = 1.0) SharedImageSet

Perform beamforming (and optionally coherent compounding) on ultrasound channel data. The SharedImageSet must contain a FrameAcquisition data component. If no ChannelDataLayout data component is present, the default layout is assumed (channels, fast time, slow time).

Parameters:
  • channel_data (SharedImageSet) – The channel data to beamform.

  • f_number (float) – The receive F-number to use in beamforming.

  • coherent_compounding (bool) – Whether to perform coherent compounding during beamforming.

  • output_size (vec2i) – Desired output size in x and y direction. Overridden in x-direction for focused imaging.

  • output_value_scaling (float) – Scaling factor for the output values. Can be used to avoid saturation for integer output types.

Returns:

The beamformed channel data as SharedImageSet.

imfusion.ultrasound_image_formation.envelope_detection(channel_data: SharedImageSet, *, sampling_frequency: float = 100.0, demodulation_frequency: float = 3.5, decimation_factor: int = 1, log_compression: bool = True, dynamic_range: float = 50.0, reference_amplitude: float = 1.0, normalize_envelope: bool = True) SharedImageSet

Perform envelope detection and (optionally) log compression on an ultrasound image given in pre-scan form. The SharedImageSet must contain a FrameAcquisition data component. If no ChannelDataLayout data component is present, the default layout is assumed (channels, fast time, slow time).

Parameters:
  • channel_data (SharedImageSet) – The channel data to process.

  • sampling_frequency (float) – Sampling frequency of the input image in y-direction. Ignored if the input is complex data.

  • demodulation_frequency (float) – Frequency of the signal to demodulate, usually the center frequency of the ultrasound signal. Ignored if the input is complex data.

  • decimation_factor (int) – Decimation factor to apply while demodulating. Ignored if the input is complex data.

  • log_compression (bool) – Whether to apply log compression to the envelope. If false the envelope is returned as IQ data.

  • dynamic_range (float) – Dynamic range of the log-compressed image. Only relevant if log_compression is true.

  • reference_amplitude (float) – The reference amplitude for log compression. At this amplitude lies the 0 dB point. Only relevant if log_compression is true.

  • normalize_envelope (bool) – Whether to normalize the envelope to the range [0, 255]. If false, the envelope is in the range [-dynamic_range, 0].

Returns:

The envelope-detected channel data as SharedImageSet.

imfusion.ultrasound_image_formation.filter_channel_data(channel_data: SharedImageSet, *, filter_type: FilterType = FilterType.BANDPASS, cutoff_frequency_lower: float | None = None, cutoff_frequency_upper: float | None = None, filter_length: int = 51) SharedImageSet

Filters channel data in the fast-time domain using a lowpass, highpass, or bandpass filter. The SharedImageSet must contain a FrameAcquisition data component. If no ChannelDataLayout data component is present, the default layout is assumed (channels, fast time, slow time).

Parameters:
  • channel_data (SharedImageSet) – The channel data to filter.

  • filter_type (FilterType) – The type of filter to apply.

  • cutoff_frequency_lower (float, optional) – The lower cutoff frequency in MHz. If not given, the frequency is determined from the FrameAcquisition. Relevant for lowpass and bandpass filters.

  • cutoff_frequency_upper (float, optional) – The upper cutoff frequency in MHz. If not given, the frequency is determined from the FrameAcquisition. Relevant for highpass and bandpass filters.

  • filter_length (int) – The length of the filter kernel.

Returns:

The filtered channel data as SharedImageSet.

imfusion.ultrasound_image_formation.get_pulse_echo_sequence(image_set: SharedImageSet, which: int = -1) FrameAcquisition

Shortcut to get FrameAcquisition from a SharedImageSet. If the image set does not contain a FrameAcquisition, None is returned.

imfusion.ultrasound_image_formation.iq_demodulation(channel_data: SharedImageSet, *, sampling_frequency: float | None = None, demodulation_frequency: float | None = None, decimation_factor: int = 1) SharedImageSet

Perform IQ demodulation in the fast-time axis of ultrasound channel data or y-axis of general RF data. The SharedImageSet may contain a FrameAcquisition data component. If it is present, the sampling frequency and demodulation frequency are determined from it. If no ChannelDataLayout data component is present, the default layout is assumed (channels, fast time, slow time).

Parameters:
  • channel_data (SharedImageSet) – The channel data to demodulate.

  • sampling_frequency (float, optional) – The sampling frequency of the input image in y-direction. Determined automatically for channel data.

  • demodulation_frequency (float, optional) – The frequency of the signal to demodulate, usually the center frequency of the ultrasound signal. Determined automatically for channel data.

  • decimation_factor (int) – The decimation factor to apply while demodulating.

Returns:

The demodulated channel data as SharedImageSet.

imfusion.ultrasound_image_formation.is_channel_data(image_set: SharedImageSet, which: int = -1) bool

Returns true if image set is a valid representation of the concept ChannelData, i.e. has FrameAcquisition as elementwise DataComponent, and has modality ULTRASOUND

imfusion.ultrasound_image_formation.log_compression(input_data: SharedImageSet, *, dynamic_range: float = 50.0, reference_amplitude: float = 1.0, normalize_envelope: bool = True) SharedImageSet

Apply ultrasound-style log compression to pre-scan amplitude or IQ data. Each input slice must have one channel (scalar instantaneous amplitude) or two channels (interleaved I/Q). Two- and three-dimensional images and image sets are supported.

Parameters:
  • input_data (SharedImageSet) – Ultrasound image or volume data to compress.

  • dynamic_range (float) – Dynamic range of the log-compressed image in dB.

  • reference_amplitude (float) – Reference amplitude for log compression; the 0 dB point lies at this amplitude.

  • normalize_envelope (bool) – If true, output is uint8 in [0, 255] (with mask handling as in the C++ algorithm). If false, output is float in [-dynamic_range, 0] dB.

Returns:

The log-compressed data as a single-channel SharedImageSet.

imfusion.ultrasound_image_formation.permute_channel_data(in_image: MemImage, input_layout: ChannelDataLayout, output_layout: ChannelDataLayout) MemImage

Permute the channel data layout of a MemImage. CPU only, should not be used for performance-critical code.