Contents
The Generalized Beamformer: All Transmit Sequence Types
This example demonstrates the Generalized Beamformer (GB) from the UltraSound ToolBox (USTB). A single beamforming equation handles four fundamentally different transmit sequences: plane wave, diverging wave, single-element (STA), and focused imaging. Only the transmit delay model and apodization parameters change between them.
The results correspond to Figure 5 in: Rindal et al., "The Generalized Beamformer in the UltraSound ToolBox", Ultrasonics, 2026.
by Ole Marius Hoel Rindal olemarius@olemarius.net
clear all; close all; if strcmp(tools.headless_publish_figure_visible(), 'on') set(groot, 'DefaultFigureVisible', 'on'); end
Dataset definitions
All four datasets were acquired on a Verasonics Vantage 256 using a Philips L7-4 linear array (128 elements, 0.298 mm pitch, ~5.2 MHz center frequency) and a CIRS 054GS phantom. The received channel data were sampled at 20.8 MHz (4x center frequency).
url = tools.zenodo_dataset_files_base();
all_filenames{1} = 'L7_CPWC_TheGB.uff'; selected_tx(1) = 1; tag{1} = 'PW'; tag_title{1} = 'Plane Wave';
all_filenames{2} = 'L7_DW_TheGB.uff'; selected_tx(2) = 1; tag{2} = 'DW'; tag_title{2} = 'Diverging Wave';
all_filenames{3} = 'L7_STA_TheGB.uff'; selected_tx(3) = 32; tag{3} = 'STA'; tag_title{3} = 'Single Element (STA)';
all_filenames{4} = 'L7_FI_TheGB.uff'; selected_tx(4) = 20; tag{4} = 'FI'; tag_title{4} = 'Focused';
dynamic_range = 60;
Download and beamform all four transmit types
Each dataset is beamformed using the GB in USTB (midprocess.das). The only difference between the four is the transmit apodization and delay model configuration. A constant f-number expanding receive aperture with a Hamming window is used throughout.
for f = 1:length(all_filenames)
filename = all_filenames{f};
tools.download(filename, url, data_path);
channel_data = uff.read_object([data_path filesep filename], '/channel_data');
channel_data.N_frames = 1;
if contains(filename, 'DW') || contains(filename, 'FI')
for seq = 1:channel_data.N_waves
channel_data.sequence(seq).sound_speed = channel_data.sound_speed;
end
end
scan = uff.linear_scan();
scan.x_axis = linspace(channel_data.probe.x(1), channel_data.probe.x(end), 512).';
scan.z_axis = linspace(3e-3, 50e-3, 512).';
UFF: reading channel_data [uff.channel_data] UFF: reading sequence [uff.wave] [====================] 100% Warning: You just deleted all frames except frames 1 to 1, I hope you meant to!
Set up the Generalized Beamformer
mid = midprocess.das();
mid.dimension = dimension.receive;
mid.channel_data = channel_data;
mid.scan = scan;
if contains(filename, 'FI')
MLA = scan.N_x_axis / channel_data.N_waves;
mid.spherical_transmit_delay_model = spherical_transmit_delay_model.hybrid;
mid.pw_margin = 2/1000;
mid.transmit_apodization.window = uff.window.tukey25;
mid.transmit_apodization.f_number = 2.5;
mid.transmit_apodization.MLA = MLA;
mid.transmit_apodization.MLA_overlap = MLA;
mid.transmit_apodization.minimum_aperture = [2.5e-03 2.5e-03];
else
mid.transmit_apodization.window = uff.window.none;
mid.transmit_apodization.f_number = 1.7;
end
mid.receive_apodization.window = uff.window.hamming;
mid.receive_apodization.f_number = 1.7;
fprintf('\n=== Beamforming: %s (%d transmits) ===\n', tag_title{f}, channel_data.N_waves);
b_data_single_tx = mid.go();
b_data = uff.beamformed_data(b_data_single_tx);
b_data.data = reshape(b_data.data, size(b_data.data,1), 1, 1, size(b_data.data,3));
=== Beamforming: Plane Wave (11 transmits) === USTB MEX C beamformer...Completed in 0.91 seconds.
Single transmit image
Showing a single transmit event before coherent compounding. This illustrates the raw contribution of one transmit to the final image.
tools.publish_beamformed_snap(b_data, ... sprintf('%s - Single Transmit', tag_title{f}), dynamic_range, 'log', selected_tx(f));
Index exceeds the number of array elements. Index must not exceed 1.
Error in uff.beamformed_data/plot (line 124)
data=h.data(:,indeces(1),indeces(2),indeces(3));
^^^^^^^^^^
Error in tools.publish_beamformed_snap (line 13)
b_obj.plot(fh, varargin{:});
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in TheGB_all_transmit_sequences (line 90)
tools.publish_beamformed_snap(b_data, ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Coherent compounding
All transmit events are coherently summed to produce the final high-quality image. The GB handles this identically for all four transmit types.
cc = postprocess.coherent_compounding();
cc.input = b_data_single_tx;
b_data_CC = cc.go();
if contains(filename, 'FI')
tx_comp = sum(mid.transmit_apodization.data, 2);
b_data_CC.data = b_data_CC.data .* (1./tx_comp);
end
tools.publish_beamformed_snap(b_data_CC, ...
sprintf('%s - Compounded (%d Tx)', tag_title{f}, channel_data.N_waves), ...
dynamic_range, 'log');
img_single{f} = b_data;
img_compound{f} = b_data_CC;
n_tx(f) = channel_data.N_waves;
end
Summary: All compounded images
The four compounded images are shown side by side. Despite using fundamentally different transmit wavefronts (plane, diverging, single element, focused), the Generalized Beamformer produces comparable image quality for all — demonstrating the unified nature of the approach.
f_all = figure('Position', [100 100 1200 350]); for i = 1:4 img_compound{i}.plot(subplot(1,4,i), ... sprintf('%s (%d Tx)', tag{i}, n_tx(i)), dynamic_range); end set(f_all, 'Color', 'w'); tools.publish_snap_now_figure(f_all);
Acquisition parameters
The table below summarizes the key acquisition parameters for each transmit sequence type.
fprintf('\n=== Acquisition Parameters ===\n'); fprintf('%-12s %8s %12s %8s\n', 'Type', 'N_Tx', 'fs (MHz)', 'Elements'); fprintf('%s\n', repmat('-', 1, 50)); for i = 1:4 fprintf('%-12s %8d %12.4f %8d\n', tag{i}, n_tx(i), 20.8333, 128); end fprintf('\nAll sequences use f#=1.7 receive, Hamming window, 60 dB dynamic range.\n');