183 lines
7.9 KiB
Matlab
183 lines
7.9 KiB
Matlab
function plotODG2withAnalysis(od_imgs, scan_parameter_values, g2_results, analysis_results, options, varargin)
|
|
%% plotODG2withAnalysis
|
|
% Author: Karthik
|
|
% Date: 2025-09-30
|
|
% Version: 1.0
|
|
%
|
|
% Description:
|
|
% For each scan parameter value, produces one or more compact figures.
|
|
% Each row contains:
|
|
% - Col 1: OD image
|
|
% - Col 2: g² correlation matrix
|
|
% Overlays from analysis (boundary, ellipse, centroid, anisotropy) can be
|
|
% optionally toggled on/off.
|
|
%
|
|
% Inputs:
|
|
% od_imgs : cell array of OD images
|
|
% scan_parameter_values: vector/array of scan parameters (one per image)
|
|
% g2_results : struct with fields
|
|
% - g2_matrices{k}
|
|
% - dx_phys{k}, dy_phys{k}
|
|
% analysis_results : struct with fields
|
|
% - boundary_coords{k}
|
|
% - ellipse_params{k}
|
|
% - peak_centroid{k}
|
|
% - anisotropy_vals(k)
|
|
% - roi_params{k} (optional)
|
|
% options : struct with imaging calibration
|
|
% - pixel_size (in meters)
|
|
% - magnification (unitless)
|
|
% varargin : name-value pairs
|
|
% - 'FontName', 'FontSize', 'SkipLivePlot', 'SkipSaveFigures',
|
|
% 'SaveDirectory', 'ShowOverlays', 'RepsPerPage'
|
|
%
|
|
% Notes:
|
|
% Requires conductCorrelationAnalysis and analyzeG2Structures outputs.
|
|
|
|
% --- Parse optional name-value pairs ---
|
|
p = inputParser;
|
|
addParameter(p, 'FontName', 'Arial', @ischar);
|
|
addParameter(p, 'FontSize', 12, @isnumeric);
|
|
addParameter(p, 'SkipLivePlot', false, @islogical);
|
|
addParameter(p, 'SkipSaveFigures', true, @islogical);
|
|
addParameter(p, 'SaveDirectory', pwd, @ischar);
|
|
addParameter(p, 'ShowOverlays', true, @islogical);
|
|
addParameter(p, 'RepsPerPage', 10, @isnumeric); % pagination
|
|
parse(p, varargin{:});
|
|
opts = p.Results;
|
|
|
|
% --- Setup save directory if needed ---
|
|
if ~opts.SkipSaveFigures
|
|
saveFolder = fullfile(opts.SaveDirectory, 'Results', 'SavedFigures', 'OD_G2_withAnalysis');
|
|
if ~exist(saveFolder, 'dir')
|
|
mkdir(saveFolder);
|
|
end
|
|
end
|
|
|
|
% --- Group by parameter value ---
|
|
param_vals = scan_parameter_values(:);
|
|
unique_params = unique(param_vals, 'rows');
|
|
N_params = size(unique_params, 1);
|
|
|
|
for pIdx = 1:N_params
|
|
matches = ismember(param_vals, unique_params(pIdx, :), 'rows');
|
|
idx_list = find(matches);
|
|
N_reps = numel(idx_list);
|
|
|
|
% --- Pagination over repetitions ---
|
|
numPages = ceil(N_reps / opts.RepsPerPage);
|
|
for pageIdx = 1:numPages
|
|
repStart = (pageIdx-1)*opts.RepsPerPage + 1;
|
|
repEnd = min(pageIdx*opts.RepsPerPage, N_reps);
|
|
repSubset = idx_list(repStart:repEnd);
|
|
N_rows = numel(repSubset);
|
|
|
|
% --- Create compact figure ---
|
|
if ~opts.SkipLivePlot
|
|
fig = figure('Color', 'w', 'Position', [100 100 400 800]);
|
|
figure(fig); % ensure visible
|
|
else
|
|
fig = figure('Color', 'w', 'Position', [100 100 400 800], 'Visible','off'); % invisible for direct save
|
|
end
|
|
|
|
t = tiledlayout(fig, N_rows, 2, 'TileSpacing', 'compact', 'Padding', 'compact');
|
|
title(t, sprintf('Scan parameter: %s | Page %d/%d', ...
|
|
mat2str(unique_params(pIdx, :)), pageIdx, numPages), ...
|
|
'FontSize', opts.FontSize + 2, 'FontWeight', 'bold', 'FontName', opts.FontName);
|
|
|
|
for r = 1:N_rows
|
|
k = repSubset(r);
|
|
|
|
% --- OD image ---
|
|
nexttile;
|
|
[M, N] = size(od_imgs{k});
|
|
x_phys = ((1:N) - ceil(N/2)) * (options.pixel_size / options.magnification * 1e6); % µm
|
|
y_phys = ((1:M) - ceil(M/2)) * (options.pixel_size / options.magnification * 1e6); % µm
|
|
imagesc(x_phys, y_phys, od_imgs{k});
|
|
axis image;
|
|
set(gca, 'YDir', 'normal', 'FontName', opts.FontName, 'FontSize', 14);
|
|
colormap(gca, Colormaps.inferno());
|
|
xlabel('x (\mum)');
|
|
ylabel('y (\mum)');
|
|
|
|
% --- g² correlation matrix ---
|
|
nexttile;
|
|
dx = g2_results.dx_phys{k};
|
|
dy = g2_results.dy_phys{k};
|
|
g2_matrix = g2_results.g2_matrices{k};
|
|
imagesc(dx, dy, g2_matrix);
|
|
axis image;
|
|
set(gca, 'YDir', 'normal', 'FontName', opts.FontName, 'FontSize', 14);
|
|
colormap(gca, Colormaps.coolwarm()); colorbar;
|
|
xlabel('\Deltax (\mum)'); ylabel('\Deltay (\mum)');
|
|
hold on;
|
|
|
|
% --- Optional overlays ---
|
|
if opts.ShowOverlays
|
|
boundary = analysis_results.boundary_coords{k};
|
|
ellipse = analysis_results.ellipse_params{k};
|
|
centroid = analysis_results.peak_centroid{k};
|
|
anisotropy = analysis_results.anisotropy_vals(k);
|
|
theta = analysis_results.ellipse_params{k}(5);
|
|
|
|
% ROI rectangle (rotated)
|
|
if isfield(analysis_results, 'roi_params')
|
|
roi = analysis_results.roi_params{k};
|
|
if ~isempty(roi) && all(~isnan(roi))
|
|
x0 = roi(1); y0 = roi(2);
|
|
w = roi(3); h = roi(4);
|
|
roi_theta = roi(5);
|
|
corners = [ -w/2, -h/2; w/2, -h/2; w/2, h/2; -w/2, h/2];
|
|
R = [cos(roi_theta), -sin(roi_theta); sin(roi_theta), cos(roi_theta)];
|
|
corners_rot = (R*corners')' + [x0, y0];
|
|
corners_rot = [corners_rot; corners_rot(1,:)];
|
|
plot(corners_rot(:,1), corners_rot(:,2), 'r--', 'LineWidth',1.5);
|
|
end
|
|
end
|
|
|
|
if all(~isnan(boundary(:)))
|
|
plot(boundary(:, 1), boundary(:, 2), 'g-', 'LineWidth', 2);
|
|
end
|
|
if all(~isnan(centroid))
|
|
plot(centroid(1), centroid(2), 'mo', 'MarkerSize', 8, 'LineWidth', 2);
|
|
x_c = centroid(1); y_c = centroid(2);
|
|
else
|
|
x_c = NaN; y_c = NaN;
|
|
end
|
|
if all(~isnan(ellipse)) && ~isnan(anisotropy) && anisotropy ~= 0
|
|
a = ellipse(3);
|
|
b = ellipse(4);
|
|
tEllipse = linspace(0, 2*pi, 200);
|
|
ellipse_x = x_c + a*cos(tEllipse)*cos(theta) - b*sin(tEllipse)*sin(theta);
|
|
ellipse_y = y_c + a*cos(tEllipse)*sin(theta) + b*sin(tEllipse)*cos(theta);
|
|
|
|
if anisotropy > 1.0
|
|
plot(ellipse_x, ellipse_y, 'y--', 'LineWidth', 2);
|
|
else
|
|
plot(ellipse_x, ellipse_y, 'y-', 'LineWidth', 2);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if ~opts.SkipLivePlot
|
|
drawnow; % render figure
|
|
end
|
|
|
|
% --- Save figure ---
|
|
if ~opts.SkipSaveFigures
|
|
saveFileName = sprintf('OD_G2_analysis_param_%03d_page_%02d.png', pIdx, pageIdx);
|
|
Plotter.saveFigure(fig, ...
|
|
'SaveFileName', saveFileName, ...
|
|
'SaveDirectory', saveFolder, ...
|
|
'SkipSaveFigures', opts.SkipSaveFigures);
|
|
end
|
|
|
|
% --- Close invisible figure to free memory ---
|
|
if opts.SkipLivePlot
|
|
close(fig);
|
|
end
|
|
end
|
|
end
|
|
end
|