Skip to content

Update to v1.0.1 #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function display_3D_scan(grid_, options)
function as_3D_scan(grid_, options)
% Display a 3D colormap render of a (:, :, :) grid.
% The density is relative to the highest and lowest numbers.
% Higher density means higher opacity.
Expand All @@ -8,7 +8,7 @@ function display_3D_scan(grid_, options)

% --- Optional arguments---

% Specify figure to display. "0" means don't specify
% Specify figure to display. "0" means create new figure.
options.figure_number (1, 1) {mustBeGreaterThanOrEqual(options.figure_number, 0)} ...
= 0

Expand Down Expand Up @@ -68,7 +68,7 @@ function display_3D_scan(grid_, options)
xlabel('X-axis');
ylabel('Y-axis');
zlabel('Z-axis');
title('3D Scan Density Visualization');
title('3D Scan');
view(3); % Set the view to 3D
axis tight; % Fit the axes to the data
grid on; % Turn on the grid
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function [get_signals] = rectangular(window_length),
get_signals = @(signals) ...
merit.utility.reshape2d(@(signals) signals(1:window_length, :)...
merit.process.reshape2d(@(signals) signals(1:window_length, :)...
, signals);
end
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function [points] = imaging_domain(domain, varargin)
function [points] = get_points(domain, varargin)
if numel(varargin) < 1
ndim = ndims(domain);
else
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion +merit/+domain/hemisphere.m
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
end

% use area and axes to get the set of points in the imaging domain only
points = merit.beamform.imaging_domain(area_, axes_{:});
points = merit.domain.get_points(area_, axes_{:});
end

function mustBeNumericOrRealVectorOrEmpty(a)
Expand Down
6 changes: 3 additions & 3 deletions +merit/+example_scripts/create_ummid_render.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,21 @@
number_antennas = size(scan_data, 3); % The number of antenna locations.
starting_antenna_angle = deg2rad(-130);

antenna_locations = merit.domain.create_circumference(...
antenna_locations = merit.domain.circumference(...
ant_phase_rad, ...
number_antennas, ...
starting_antenna_angle...
);

%% Calculate delays
c_0 = 299792458; % Vaccuum speed, taken from "merit.beamform.get_delays.m"
c_0 = 299792458; % Vaccuum speed, taken from "merit.get_delay.m"
%{
The relative permittivity was measured by calculating the speed for every
s11 scan in "gen-three/clean". Then dividing the mean of that by...
the speed of a vaccuum to get relative permittivity.
%}
relative_permittivity = 1.0932;
delays_temp = merit.beamform.get_delays([1:number_antennas; 1:number_antennas]', antenna_locations, relative_permittivity=relative_permittivity);
delays_temp = merit.get_delay([1:number_antennas; 1:number_antennas]', antenna_locations, relative_permittivity=relative_permittivity);

%{
Apply extra time delay for monostatic. Constant taken from T. Reimer's measurements.
Expand Down
30 changes: 0 additions & 30 deletions +merit/+example_scripts/image_B0.m

This file was deleted.

34 changes: 0 additions & 34 deletions +merit/+example_scripts/image_B10E.m

This file was deleted.

2 changes: 1 addition & 1 deletion +merit/+example_scripts/measure_performance.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

[points, ~] = merit.domain.hemisphere(7e-2, pixel_dim=50);

delays = merit.beamform.get_delays(channel_names, antenna_locations, relative_permittivity=8);
delays = merit.get_delay(channel_names, antenna_locations, relative_permittivity=8);
loaded_delays = delays(points);
end

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
% A basic guide to loading and visualising the sample data;

% Load example data
load_example_data()
%% Load example data
% Details of the breast phantoms used to collect the sample data
% are given in "Microwave Breast Imaging: experimental
% tumour phantoms for the evaluation of new breast cancer diagnosis
% systems", 2018 Biomed. Phys. Eng. Express 4 025036.
% The antenna locations, frequency points and scattered signals
% are given in the "example_data/" folder:

% frequencies.csv: the frequency points in Hertz;
frequencies = dlmread('example_data/frequencies.csv');
% antenna_locations.csv: the antenna locations in metres;
antenna_locations = dlmread('example_data/antenna_locations.csv');
% channel_names.csv: the descriptions of the channels in the scattered data;
channel_names = dlmread('example_data/channel_names.csv');

% Select the signal data from a range of different scans.
ph = "B0"; % Choose breast phantom from the following: {'B0','B10E','B15E','B20E','B30E'}.
pl = 3; % Choose tumour from list of 1 to 22.
[scan1, scan2] = load_example_scan(ph, pl);

% Perform rotation subtraction
signals = scan1-scan2;

%% Plot the acquired scans.
figure()
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions +merit/+metrics/G_GSS.m → +merit/+metric/G_GSS.m
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
function [f] = G_GSS(imgs, points, axes_),
%merit.beamform.un_imaging_domain(img, points, axes_)
window_size = 15;
nPoints = size(points, 1);

inds = (1:nPoints)';
grid_ = merit.beamform.un_imaging_domain(inds, points, axes_{:});
% There is/was never an un_imaging_domain.m, so this is broken.
grid_ = merit.un_imaging_domain(inds, points, axes_{:});
if isa(imgs, 'single')
grid_ = single(grid_);
end
Expand Down
File renamed without changes.
File renamed without changes.
10 changes: 6 additions & 4 deletions +merit/+process/delay.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,28 @@
padding = @nan;
end

[signals, delays] = merit.process.expand2(signals, delays);

if isreal(signals)
%% Time domain
if nargin == 2
%% time domain, delay in samples
validateattributes(delays, {'numeric'}, {'integer'});
signals_ = merit.utility.reshape2d(@delay_sample, signals, delays);
signals_ = merit.process.reshape2d(@delay_sample, signals, delays);
elseif nargin >= 3 & numel(axis_) == size(signals, 1)
%% Time axis provided
validateattributes(axis_, {'numeric'},...
{'vector', 'increasing', 'real'});
if ~merit.utility.linearlysampled(axis_)
if ~merit.process.linearlysampled(axis_)
error('merit:process:delay', 'Time axis needs to be linearly sampled');
end
dt = diff(axis_(1:2));
signals_ = merit.utility.reshape2d(@delay_sample, signals, round(delays./dt));
signals_ = merit.process.reshape2d(@delay_sample, signals, round(delays./dt));
elseif nargin == 3 & isa(axis_, 'function_handle')
% Padding provided
padding = axis_;
validateattributes(delays, {'numeric'}, {'integer'});
signals_ = merit.utility.reshape2d(@delay_sample, signals, delays);
signals_ = merit.process.reshape2d(@delay_sample, signals, delays);
end
elseif ~isreal(signals) && nargin == 3
%% Frequency domain
Expand Down
2 changes: 1 addition & 1 deletion +merit/+utility/expand.m → +merit/+process/expand.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
for c = 1:size(sizes, 2)
u_sizes = unique(sizes(:, c));
if numel(u_sizes) ~= 1 && u_sizes(1) ~= 1
error('merit:utility:expand', 'Dimensions need to be the same or one for all inputs.');
error('Dimensions need to be the same or one for all inputs.');
end
end

Expand Down
21 changes: 21 additions & 0 deletions +merit/+process/expand2.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function [varargout] = expand2(varargin)
dims = cellfun(@ndims, varargin);
sizes = ones(numel(varargin), max(dims));
for v = 1:numel(varargin)
sizes(v, 1:dims(v)) = size(varargin{v});
end

for c = 2:size(sizes, 2)
u_sizes = unique(sizes(:, c));
if numel(u_sizes) ~= 1 && u_sizes(1) ~= 1
error('merit:utility:expand', 'Dimensions need to be the same or one for all inputs.');
end
end

varargout = varargin(1:nargout);
repeats = max(sizes)./sizes;
repeats(:, 1) = 1;
for v = 1:numel(varargout)
varargout{v} = repmat(varargout{v}, repeats(v, :));
end
end
8 changes: 4 additions & 4 deletions +merit/+process/fd2td.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
validateattributes(time_axis, {'numeric'},...
{'vector', 'increasing', 'real'});

if ~merit.utility.linearlysampled(time_axis)
if ~merit.process.linearlysampled(time_axis)
error('merit:process:fd2td', 'Time axis needs to be linearly sampled');
end
if ~merit.utility.linearlysampled(frequency_axis)
if ~merit.process.linearlysampled(frequency_axis)
error('merit:process:fd2td', 'Frequency axis needs to be linearly sampled');
end

%% Accommodate trailing dimensions
signals_ = merit.utility.reshape2d(@fd2td_, signals);
signals_ = merit.process.reshape2d(@fd2td_, signals);

function [signals_] = fd2td_(signals)
time_axis = time_axis(time_axis >= 0);
Expand All @@ -40,7 +40,7 @@
w = exp(-1j*2*pi*dt*df);
a = exp(1j*2*pi*min(time_axis(:))*df);

iczt = @(z) merit.utility.under(@(z) czt(z, m, w, a), @conj, @conj, z);
iczt = @(z) merit.process.under(@(z) czt(z, m, w, a), @conj, @conj, z);

% Phase compensation
phase = exp(1j*2*pi*min(frequency_axis(:)).*time_axis(:));
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions +merit/+utility/reshape2d.m → +merit/+process/reshape2d.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
for v = 2:numel(varargin)
size_ = size(varargin{v});
if ~isequal(size_(2:end), original_size(2:end)),
error('merit:utility:reshape2d', 'Input arrays must have the same trailing dimension sizes');
error('Input arrays must have the same trailing dimension sizes');
end
end

flatten = @(a) reshape(a, size(a, 1), []);
restore = @(a) reshape(a, [size(a, 1), original_size(2:end)]);

result = merit.utility.under(f, flatten, restore, varargin{:});
result = merit.process.under(f, flatten, restore, varargin{:});
end
6 changes: 3 additions & 3 deletions +merit/+process/td2fd.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
validateattributes(frequency_axis, {'numeric'},...
{'vector', 'increasing', 'real'});

if ~merit.utility.linearlysampled(time_axis)
if ~merit.process.linearlysampled(time_axis)
error('merit:process:td2fd', 'Time axis needs to be linearly sampled');
end
if ~merit.utility.linearlysampled(frequency_axis)
if ~merit.process.linearlysampled(frequency_axis)
error('merit:process:td2fd', 'Frequency axis needs to be linearly sampled');
end

%% Accommodate trailing dimensions
signals_ = merit.utility.reshape2d(@td2fd_, signals);
signals_ = merit.process.reshape2d(@td2fd_, signals);

function [signals_] = td2fd_(signals)
dt = diff(time_axis(1:2));
Expand Down
4 changes: 2 additions & 2 deletions +merit/+process/txrx2ind.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
if ~exist('rx', 'var')
rx = tx;
else
[tx, rx] = merit.utility.expand(tx, rx);
[tx, rx] = merit.process.expand(tx, rx);
end

nChannels = size(channels, 1);

inds = merit.utility.under(@get_inds, @(a) a(:), @(a) reshape(a, size(tx)), tx, rx);
inds = merit.process.under(@get_inds, @(a) a(:), @(a) reshape(a, size(tx)), tx, rx);

function [inds] = get_inds(tx, rx)
s = [nChannels, numel(tx)];
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions +merit/+test/+from_list/+beamform/test_beamform.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
[pulse_td, pulse_fd] = DG(3e9, 1/3e9, time_axis, frequencies);
signals = single(merit.process.shape(data, pulse_fd, frequencies, time_axis));

delay_func = merit.beamform.get_delays(channels, antenna_locations, relative_permittivity=8);
delay_func = merit.get_delay(channels, antenna_locations, relative_permittivity=8);

img = merit.beamform(signals, time_axis, points, delay_func, merit.beamformers.DAS, window= merit.beamform.windows.rectangular(150));
img = merit.beamform(signals, time_axis, points, delay_func, merit.beamformer.DAS, window=merit.domain.windows.rectangular(150));
[~, i] = max(img);
[t, r, z] = cart2pol(points(i, 1), points(i, 2), points(i, 3));

Expand All @@ -40,9 +40,9 @@
data = single(data(F, :));
frequencies = frequencies(F);

delay_func = merit.beamform.get_delays(channels, antenna_locations, relative_permittivity=8);
delay_func = merit.get_delay(channels, antenna_locations, relative_permittivity=8);

img = abs(merit.beamform(data, frequencies, points, delay_func, merit.beamformers.DAS));
img = abs(merit.beamform(data, frequencies, points, delay_func, merit.beamformer.DAS));
[~, i] = max(img);
[t, r, z] = cart2pol(points(i, 1), points(i, 2), points(i, 3));
testCase.verifyLessThan(abs(rad2deg(t)-location(1)), 9);
Expand Down
Loading