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_objectCollection 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:
DataComponentBaseRegions 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:
DataComponentBaseLayout 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_objectMembers:
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_objectMembers:
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:
DataComponentBaseMetadata 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_objecthigh-level parameters for sequence creation
- class DivergingWaveParameters(self: DivergingWaveParameters)
Bases:
pybind11_objecthigh-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_objecthigh-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_objecthigh-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:
DataComponentBaseDescribes one ultrasound pulse echo event. Metadata for ultrasound channel data.
- class Receive
Bases:
pybind11_objectChannel 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_objectTransmit 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:
ImageStreamTesting / 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_objectMembers:
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:
DataComponentBaseLow 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_objectMembers:
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
uint8in [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.