<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="bbPress/1.0.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>k-Wave User Forum &#187; Topic: Artifacts in Plane Wave Simulations using kWaveArray</title>
		<link>http://www.k-wave.org/forum/topic/artifacts-in-plane-wave-simulations-using-kwavearray</link>
		<description>Support for the k-Wave MATLAB toolbox</description>
		<language>en-US</language>
		<pubDate>Sun, 31 May 2026 15:19:23 +0000</pubDate>
		<generator>http://bbpress.org/?v=1.0.2</generator>
		<textInput>
			<title><![CDATA[Search]]></title>
			<description><![CDATA[Search all topics from these forums.]]></description>
			<name>q</name>
			<link>http://www.k-wave.org/forum/search.php</link>
		</textInput>
		<atom:link href="http://www.k-wave.org/forum/rss/topic/artifacts-in-plane-wave-simulations-using-kwavearray" rel="self" type="application/rss+xml" />

		<item>
			<title>Bradley Treeby on "Artifacts in Plane Wave Simulations using kWaveArray"</title>
			<link>http://www.k-wave.org/forum/topic/artifacts-in-plane-wave-simulations-using-kwavearray#post-9011</link>
			<pubDate>Wed, 24 Jan 2024 11:17:15 +0000</pubDate>
			<dc:creator>Bradley Treeby</dc:creator>
			<guid isPermaLink="false">9011@http://www.k-wave.org/forum/</guid>
			<description>&#60;p&#62;I haven't run your simulation, but the effects you're describing is what I would expect to happen given the way sources are modelled in k-Wave. Depending on the transducer design, you also see this in experimental measurements. One simple way to remove the transmitted wave from the receive data would be to run two simulations, one in a homogeneous medium, and then one with the medium properties you are trying to image, and subtract the RF data of the first from the second.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>nikunj101 on "Artifacts in Plane Wave Simulations using kWaveArray"</title>
			<link>http://www.k-wave.org/forum/topic/artifacts-in-plane-wave-simulations-using-kwavearray#post-8987</link>
			<pubDate>Wed, 13 Dec 2023 19:10:16 +0000</pubDate>
			<dc:creator>nikunj101</dc:creator>
			<guid isPermaLink="false">8987@http://www.k-wave.org/forum/</guid>
			<description>&#60;p&#62;Hi,&#60;/p&#62;
&#60;p&#62;I am currently working on simulating RFData generated by plane wave emissions from a linear array transducer. In this process, I am encountering several artifacts in my simulations, particularly when recombining sensor data using kWaveArray. The primary issue involves the inadequate cancellation of signals from adjacent elements, especially noticeable when the transmit angle deviates from zero. This results in unwanted signals appearing in the simulated RFData.&#60;/p&#62;
&#60;p&#62;Additionally, I observe an edge effect. The edges of my simulated array produce spherical wave patterns that propagate across the array, creating an X-like artifact in the RFData. While similar phenomena occur in practical scenarios with linear arrays, the inherent directionality of actual transducer elements usually reduces the intensity of this artifact. In my simulation using kWave, even though the spherical sources are non-directional, I expect the line elements implemented via kWaveArray to exhibit some directionality, so I'm surprised I'm seeing as strong an artifact as I am.&#60;/p&#62;
&#60;p&#62;I have tried applying a roll-off apodization along the array edges to mitigate this issue, but I am seeking alternative solutions. Could you suggest other methods to reduce the edge effect artifact? Additionally, how might I address the interference artifact arising from neighboring elements?&#60;/p&#62;
&#60;p&#62;Here is a minimal working example of my code using a homogenous medium. You can adjust the transmit angle by changing the TXangle parameter in the first section:&#60;/p&#62;
&#60;p&#62;&#60;code&#62;&#60;/code&#62;`&#60;br /&#62;
% Coherent Plane Wave Compounding Simulation Using K-Wave&#60;br /&#62;
%&#60;br /&#62;
% This script demonstrates how to setup a linear array transducer using the&#60;br /&#62;
% kWaveArray class for coherent plane wave compounding in ultrasound imaging.&#60;br /&#62;
% It involves creating a simulation grid, defining a medium with point targets,&#60;br /&#62;
% initializing a transducer array, generating a focused source, simulating wave&#60;br /&#62;
% propagation, and collecting sensor data.&#60;br /&#62;
%&#60;br /&#62;
% Author: Nikunj Khetan&#60;br /&#62;
% Last Update: 21st November 2023&#60;/p&#62;
&#60;p&#62;clearvars;&#60;br /&#62;
% close all&#60;/p&#62;
&#60;p&#62;%% DEFINE LITERALS - Setting up parameters for the simulation&#60;/p&#62;
&#60;p&#62;% Selection of K-Wave code execution model&#60;br /&#62;
model = 1;  % Options: 1 - MATLAB CPU, 2 - MATLAB GPU, 3 - C++ code, 4 - CUDA code&#60;br /&#62;
USE_STATISTICS = true;      % set to true to compute the rms or peak beam patterns, set to false to compute the harmonic beam patterns&#60;/p&#62;
&#60;p&#62;% Medium parameters&#60;br /&#62;
c0 = 1540;        % Sound speed in the medium [m/s]&#60;br /&#62;
rho0 = 1020;      % Density of the medium [kg/m^3]&#60;/p&#62;
&#60;p&#62;% Source parameters&#60;br /&#62;
source_f0 = (250/48)*1e6;         % Frequency of the ultrasound source [Hz]&#60;br /&#62;
source_amp = 1e6;          % Amplitude of the ultrasound source [Pa]&#60;br /&#62;
source_cycles = 3;         % Number of cycles in the tone burst signal&#60;br /&#62;
numEl = 128;               % Number of elements in the transducer array&#60;br /&#62;
element_width = 2.3e-4;    % Width of each transducer element [m]&#60;br /&#62;
element_pitch = 2.3e-4;    % Pitch - distance between the centers of adjacent elements [m]&#60;br /&#62;
RF_fs = source_f0*4;       % Sampling Frequency of final RFData&#60;/p&#62;
&#60;p&#62;% Define transmission angles for plane wave compounding&#60;br /&#62;
na = 1;  % Number of angles for transmission&#60;br /&#62;
TXangle = 10*pi/180;&#60;/p&#62;
&#60;p&#62;% Grid parameters&#60;br /&#62;
grid_size_x = 40e-3;  % Grid size in x-direction [m]&#60;br /&#62;
grid_size_y = 10e-3;  % Grid size in y-direction [m]&#60;/p&#62;
&#60;p&#62;% Computational parameters&#60;br /&#62;
ppw = 4;             % Points per wavelength&#60;br /&#62;
t_end = round(grid_size_y/c0,6);        % Simulation duration [s]&#60;br /&#62;
cfl = 0.5;            % Courant-Friedrichs-Lewy (CFL) number for stability&#60;/p&#62;
&#60;p&#62;%% GRID - Creating the computational grid&#60;/p&#62;
&#60;p&#62;% Calculate grid spacing based on PPW and source frequency&#60;br /&#62;
dx = c0 / (ppw * source_f0);  % Grid spacing [m]&#60;br /&#62;
dy = dx;&#60;/p&#62;
&#60;p&#62;% Compute grid size&#60;br /&#62;
Nx = roundEven(grid_size_x / dx);  % Number of grid points in x-direction&#60;br /&#62;
Ny = roundEven(grid_size_y / dy);  % Number of grid points in y-direction&#60;/p&#62;
&#60;p&#62;% Create the computational grid&#60;br /&#62;
kgrid = kWaveGrid(Nx, dx, Ny, dy);&#60;/p&#62;
&#60;p&#62;% Create the time array&#60;br /&#62;
kgrid.makeTime(c0, cfl, t_end);&#60;br /&#62;
dsFactor = (1/kgrid.dt)/RF_fs;&#60;/p&#62;
&#60;p&#62;%% SOURCE - Initializing the transducer array and source signal&#60;/p&#62;
&#60;p&#62;[karray, ElemPos] = initArray(kgrid, numEl, element_pitch, element_width);&#60;/p&#62;
&#60;p&#62;% Create source signal using a tone burst&#60;br /&#62;
source_sig = source_amp .* toneBurst(1/kgrid.dt, source_f0, source_cycles);&#60;/p&#62;
&#60;p&#62;%% MEDIUM - Defining the medium properties &#60;/p&#62;
&#60;p&#62;medium.sound_speed = c0 * ones([Nx, Ny]);   % sound speed [m/s]&#60;br /&#62;
medium.density = rho0 * ones([Nx, Ny]);      % density [kg/m3]&#60;/p&#62;
&#60;p&#62;%% SENSOR - Setting up the sensor mask and properties&#60;/p&#62;
&#60;p&#62;% Assign binary mask from karray to the sensor mask&#60;br /&#62;
sensor.mask = karray.getArrayBinaryMask(kgrid);&#60;/p&#62;
&#60;p&#62;% set the record mode such that only the rms and peak values are stored&#60;br /&#62;
sensor.record = {'p'};&#60;/p&#62;
&#60;p&#62;% Define frequency response of the sensor&#60;br /&#62;
sensor.frequency_response = [source_f0, 100];&#60;/p&#62;
&#60;p&#62;%% SIMULATION - Running the simulation for different transmission angles&#60;/p&#62;
&#60;p&#62;% Preallocate arrays for time delays and RF data&#60;br /&#62;
time_delays = zeros(na, numEl);&#60;/p&#62;
&#60;p&#62;% Simulation input options&#60;br /&#62;
input_args = {'PMLSize', 'auto', 'PMLInside', false, 'PlotPML', false, 'DisplayMask', 'off'};&#60;br /&#62;
RFData = zeros(numEl, kgrid.Nt, na);&#60;/p&#62;
&#60;p&#62;% Loop over each angle for plane wave compounding&#60;br /&#62;
for i = 1:na&#60;br /&#62;
    [source, time_delays(i, :)] = genSource(kgrid, source_f0, source_cycles, source_amp, TXangle(i), karray, ElemPos, c0);&#60;/p&#62;
&#60;p&#62;    sensor_data = runSim(kgrid, medium, source, sensor, input_args, model,source_amp);&#60;/p&#62;
&#60;p&#62;    RFData(:, :, i) = karray.combineSensorData(kgrid, sensor_data.p);&#60;br /&#62;
end&#60;/p&#62;
&#60;p&#62;% Rearrange RF data dimensions for further processing&#60;br /&#62;
RFData = downsample(flip(permute(RFData, [2, 1, 3]),2),dsFactor);&#60;/p&#62;
&#60;p&#62;figure&#60;br /&#62;
colormap gray&#60;br /&#62;
imagesc(log10(abs(RFData(:,:,1))))&#60;/p&#62;
&#60;p&#62;%% HELPER FUNCTIONS&#60;br /&#62;
function [karray, ElemPos] = initArray(kgrid, element_num, element_pitch, element_width)&#60;br /&#62;
    % Initializes the transducer array.&#60;br /&#62;
    % Args:&#60;br /&#62;
    %   kgrid: The k-Wave grid object.&#60;br /&#62;
    %   element_num: Number of elements in the array.&#60;br /&#62;
    %   element_pitch: Distance between the centers of adjacent elements.&#60;br /&#62;
    %   element_width: Width of each element.&#60;br /&#62;
    % Returns:&#60;br /&#62;
    %   karray: The k-Wave array object.&#60;br /&#62;
    %   ElemPos: The positions of the elements in the array.&#60;/p&#62;
&#60;p&#62;    % Create empty kWaveArray object with specified BLI tolerance and upsampling rate&#60;br /&#62;
    karray = kWaveArray('BLITolerance', 0.05, 'UpsamplingRate', 10);&#60;/p&#62;
&#60;p&#62;    % Calculate the center position for the first element&#60;br /&#62;
    L = element_num * element_pitch / 2;&#60;br /&#62;
    ElemPos = -(L - element_pitch / 2) + (0:element_num - 1) * element_pitch;&#60;/p&#62;
&#60;p&#62;    % Add rectangular elements to the array&#60;br /&#62;
    for ind = 1:element_num&#60;br /&#62;
        % Set element position&#60;br /&#62;
        x_pos = ElemPos(ind);&#60;/p&#62;
&#60;p&#62;        % Define start and end points of the element&#60;br /&#62;
        start_point = [x_pos - element_width / 2, kgrid.y_vec(1)];&#60;br /&#62;
        end_point = [x_pos + element_width / 2, kgrid.y_vec(1)];&#60;/p&#62;
&#60;p&#62;        % Add line element to the array&#60;br /&#62;
        karray.addLineElement(start_point, end_point);&#60;br /&#62;
    end&#60;br /&#62;
end&#60;/p&#62;
&#60;p&#62;function [source, time_delays] = genSource(kgrid, source_f0, source_cycles, source_amp, theta, karray, ElemPos, c0)&#60;br /&#62;
    % Generates the source signal with time delays for each transducer element.&#60;br /&#62;
    % Args:&#60;br /&#62;
    %   kgrid: The k-Wave grid object.&#60;br /&#62;
    %   source_f0: Frequency of the source.&#60;br /&#62;
    %   source_cycles: Number of cycles in the tone burst signal.&#60;br /&#62;
    %   source_amp: Amplitude of the source.&#60;br /&#62;
    %   theta: Steering angle of the plane wave.&#60;br /&#62;
    %   karray: The k-Wave array object.&#60;br /&#62;
    %   ElemPos: The positions of the elements in the array.&#60;br /&#62;
    %   c0: Speed of sound.&#60;br /&#62;
    % Returns:&#60;br /&#62;
    %   source: The source object containing the mask and signals.&#60;br /&#62;
    %   time_delays: Time delays applied to each element for focusing.&#60;/p&#62;
&#60;p&#62;    % Calculate time delays for each element based on steering angle&#60;br /&#62;
    time_delays = ElemPos * sin(theta) / c0;&#60;br /&#62;
    time_delays = time_delays - min(time_delays);&#60;/p&#62;
&#60;p&#62;    % Create time-varying source signals for each physical element&#60;br /&#62;
    source_sig = source_amp .* toneBurst(1/kgrid.dt, source_f0, source_cycles, 'SignalOffset', round(time_delays / kgrid.dt));&#60;/p&#62;
&#60;p&#62;    % Assign binary mask for the source&#60;br /&#62;
    source.p_mask = karray.getArrayBinaryMask(kgrid);&#60;/p&#62;
&#60;p&#62;    % Assign source signals to the source object&#60;br /&#62;
    source.p = karray.getDistributedSourceSignal(kgrid, source_sig);&#60;br /&#62;
end&#60;/p&#62;
&#60;p&#62;function [sensor_data] = runSim(kgrid, medium, source, sensor, input_args, model, source_amp)&#60;br /&#62;
    % Runs the simulation based on the selected model (CPU or GPU).&#60;br /&#62;
    % Args:&#60;br /&#62;
    %   kgrid: The k-Wave grid object.&#60;br /&#62;
    %   medium: The medium in which waves propagate.&#60;br /&#62;
    %   source: The source object containing the ultrasound signal.&#60;br /&#62;
    %   sensor: The sensor object to record the pressure.&#60;br /&#62;
    %   input_args: Additional input arguments for the simulation.&#60;br /&#62;
    %   model: The selected model for running the simulation.&#60;br /&#62;
    % Returns:&#60;br /&#62;
    %   sensor_data: The recorded sensor data from the simulation.&#60;/p&#62;
&#60;p&#62;    % Run the simulation based on the chosen model&#60;br /&#62;
    switch model&#60;br /&#62;
        case 1&#60;br /&#62;
            % MATLAB CPU&#60;br /&#62;
            sensor_data = kspaceFirstOrder2D(kgrid, medium, source, sensor, ...&#60;br /&#62;
                input_args{:}, ...&#60;br /&#62;
                'DataCast', 'single', ...&#60;br /&#62;
                'PlotScale', [-1, 1] * source_amp);&#60;/p&#62;
&#60;p&#62;        case 2&#60;br /&#62;
            % MATLAB GPU&#60;br /&#62;
            sensor_data = kspaceFirstOrder2D(kgrid, medium, source, sensor, ...&#60;br /&#62;
                input_args{:}, ...&#60;br /&#62;
                'DataCast', 'gpuArray-single', ...&#60;br /&#62;
                'PlotScale', [-1, 1] * source_amp);&#60;/p&#62;
&#60;p&#62;        case 3&#60;br /&#62;
            % C++ code&#60;br /&#62;
            sensor_data = kspaceFirstOrder2DC(kgrid, medium, source, sensor, input_args{:});&#60;/p&#62;
&#60;p&#62;        case 4&#60;br /&#62;
            % C++/CUDA GPU&#60;br /&#62;
            sensor_data = kspaceFirstOrder2DG(kgrid, medium, source, sensor, input_args{:});&#60;br /&#62;
    end&#60;br /&#62;
end&#60;br /&#62;
&#60;code&#62;&#60;/code&#62;`
&#60;/p&#62;</description>
		</item>

	</channel>
</rss>
