148 lines
5.6 KiB
Matlab
148 lines
5.6 KiB
Matlab
function plotMultiplePCAResults(pcaResults, scan_parameter_values, scan_reference_values, varargin)
|
|
%% plotMultiplePCAResults
|
|
% Author: Karthik
|
|
% Date: 2025-09-12
|
|
% Version: 1.0
|
|
%
|
|
% Description:
|
|
% Plots PCA results for multiple PCs.
|
|
%
|
|
% Inputs:
|
|
% pcaResults - struct returned by computePCAfromImages
|
|
% scan_parameter_values, scan_reference_values
|
|
% varargin - name-value pairs (same as plotG2 plus 'FigNumRange','MaxPCToPlot')
|
|
%
|
|
% Notes:
|
|
% Optional notes, references.
|
|
|
|
% --- Parse name-value pairs ---
|
|
p = inputParser;
|
|
addParameter(p, 'XLabel', '', @(x) ischar(x) || isstring(x));
|
|
addParameter(p, 'FontName', 'Arial', @ischar);
|
|
addParameter(p, 'FontSize', 14, @isnumeric);
|
|
addParameter(p, 'Colormap', @Colormaps.coolwarm);
|
|
addParameter(p, 'SkipSaveFigures', false, @islogical);
|
|
addParameter(p, 'SaveDirectory', pwd, @ischar);
|
|
addParameter(p, 'FigNumRange', [], @(x) isnumeric(x) && all(x>0));
|
|
addParameter(p, 'MaxPCToPlot', 1, @(x) isnumeric(x) && isscalar(x) && x>=1);
|
|
parse(p, varargin{:});
|
|
opts = p.Results;
|
|
|
|
Nx = pcaResults.Nx;
|
|
Ny = pcaResults.Ny;
|
|
coeff = pcaResults.coeff;
|
|
score = pcaResults.score;
|
|
explained = pcaResults.explained;
|
|
|
|
raw_scan_param_vals = scan_parameter_values;
|
|
unique_scan_param_vals = scan_reference_values;
|
|
numGroups = numel(unique_scan_param_vals);
|
|
|
|
% --- Figure numbering setup ---
|
|
if isempty(opts.FigNumRange)
|
|
figCount = 1;
|
|
figNums = [];
|
|
else
|
|
figNums = opts.FigNumRange;
|
|
figCount = 1;
|
|
end
|
|
|
|
figPos = [100 100 950 750];
|
|
|
|
%% --- Precompute score norms and group by scan parameter ---
|
|
numPCsToPlot = min(opts.MaxPCToPlot, size(coeff,2));
|
|
scoreNorms = sqrt(sum(score(:,1:numPCsToPlot).^2, 2));
|
|
|
|
groupedNorms = arrayfun(@(g) scoreNorms(raw_scan_param_vals == g), unique_scan_param_vals, 'UniformOutput', false);
|
|
|
|
% Mean and SEM per group
|
|
meanNorms = cellfun(@mean, groupedNorms);
|
|
semNorms = cellfun(@(x) std(x)/sqrt(numel(x)), groupedNorms);
|
|
|
|
% Cumulants (up to 4th order) per group
|
|
kappas = cell2mat(cellfun(@(x) Calculator.computeCumulants(x(:),4), groupedNorms, 'UniformOutput', false));
|
|
|
|
|
|
%% --- Figure 1: PC images ---
|
|
if ~isempty(figNums)
|
|
fig = figure(figNums(figCount)); clf;
|
|
else
|
|
fig = figure; clf;
|
|
end
|
|
set(fig, 'Color', 'w', 'Position', figPos);
|
|
nRows = ceil(sqrt(numPCsToPlot));
|
|
nCols = ceil(numPCsToPlot/nRows);
|
|
tLayout = tiledlayout(nRows,nCols,'TileSpacing','compact','Padding','compact');
|
|
|
|
for pc = 1:numPCsToPlot
|
|
nexttile;
|
|
pc_image = reshape(coeff(:,pc), Nx, Ny);
|
|
imagesc(pc_image); axis image off;
|
|
colormap(opts.Colormap());
|
|
title(sprintf('PC%d (%.2f%%)', pc, explained(pc)), ...
|
|
'FontName', opts.FontName, 'FontSize', opts.FontSize);
|
|
end
|
|
sgtitle(sprintf('Principal Component Images (1-%d)', numPCsToPlot), ...
|
|
'FontName', opts.FontName, 'FontSize', opts.FontSize+2);
|
|
set(gca, 'FontName', opts.FontName, 'FontSize', opts.FontSize);
|
|
|
|
if ~opts.SkipSaveFigures
|
|
Plotter.saveFigure(fig, 'SaveFileName', sprintf('PC1to%d_Images.fig', numPCsToPlot), ...
|
|
'SaveDirectory', opts.SaveDirectory);
|
|
end
|
|
figCount = figCount + 1;
|
|
|
|
%% --- Figure 2: Mean ± SEM of score norms ---
|
|
if ~isempty(figNums)
|
|
fig = figure(figNums(figCount)); clf;
|
|
else
|
|
fig = figure; clf;
|
|
end
|
|
set(fig, 'Color', 'w', 'Position', figPos);
|
|
|
|
errorbar(unique_scan_param_vals, meanNorms, semNorms, '--o', 'LineWidth', 2);
|
|
|
|
xlabel(opts.XLabel, 'FontName', opts.FontName, 'FontSize', opts.FontSize);
|
|
ylabel(sprintf('‖Scores(1:%d)‖ ± SEM', numPCsToPlot), 'FontName', opts.FontName, 'FontSize', opts.FontSize);
|
|
title('Mean ± SEM of Score Norms', 'FontName', opts.FontName, 'FontSize', opts.FontSize+2);
|
|
set(gca, 'FontName', opts.FontName, 'FontSize', opts.FontSize);
|
|
grid on;
|
|
|
|
if ~opts.SkipSaveFigures
|
|
Plotter.saveFigure(fig, 'SaveFileName', sprintf('PC1to%d_Norm_MeanSEM.fig', numPCsToPlot), ...
|
|
'SaveDirectory', opts.SaveDirectory);
|
|
end
|
|
figCount = figCount + 1;
|
|
|
|
%% --- Figure 3: Cumulants of score norms ---
|
|
if ~isempty(figNums)
|
|
fig = figure(figNums(figCount)); clf;
|
|
else
|
|
fig = figure; clf;
|
|
end
|
|
set(fig,'Color','w','Position',[100 100 950 750]);
|
|
t = tiledlayout(2,2,'TileSpacing','Compact','Padding','Compact');
|
|
title(t, sprintf('Cumulants of Score Norms (1-%d PCs)', numPCsToPlot), ...
|
|
'FontName', opts.FontName, 'FontSize', opts.FontSize+4);
|
|
|
|
cumulLabels = {'\kappa_1','\kappa_2','\kappa_3','\kappa_4'};
|
|
cumulTitles = {'Mean','Variance','Skewness','Binder Cumulant'};
|
|
|
|
for k = 1:4
|
|
ax = nexttile; hold(ax,'on');
|
|
plot(ax, unique_scan_param_vals, kappas(:, k), '-o', ...
|
|
'Color', [0.2 0.4 0.7], 'LineWidth', 2, 'MarkerSize', 8, ...
|
|
'MarkerFaceColor', [0.2 0.4 0.7]);
|
|
ylabel(ax, cumulLabels{k}, 'FontName', opts.FontName, 'FontSize', opts.FontSize);
|
|
xlabel(ax, opts.XLabel, 'FontName', opts.FontName, 'FontSize', opts.FontSize);
|
|
title(ax, cumulTitles{k}, 'FontName', opts.FontName, 'FontSize', opts.FontSize+2);
|
|
grid(ax,'on'); set(ax,'FontName',opts.FontName,'FontSize',opts.FontSize);
|
|
end
|
|
set(gca, 'FontName', opts.FontName, 'FontSize', opts.FontSize);
|
|
if ~opts.SkipSaveFigures
|
|
Plotter.saveFigure(fig, 'SaveFileName', sprintf('PC1to%d_Norm_Cumulants.fig', numPCsToPlot), ...
|
|
'SaveDirectory', opts.SaveDirectory);
|
|
end
|
|
|
|
end
|