Calculations/Data-Analyzer/+Scripts/BECToDropletsToStripes/plotAnalysisResults.m

440 lines
18 KiB
Matlab

%% --- User chooses which dataset to load ---
datasetIdx = 1; % <-- change this to 1, 2, 3, ...
datasetName = sprintf('Dataset_%d', datasetIdx);
% --- Base directory selection ---
useLocalBaseDir = true; % <-- set true to use script location, false to use manual path
if useLocalBaseDir
% Use folder where this script is located
thisScriptPath = mfilename('fullpath');
[thisScriptDir, ~, ~] = fileparts(thisScriptPath);
baseDir = fullfile(thisScriptDir, 'Results');
else
% Use manually specified folder
baseDir = 'E:\Results - Experiment\202508\BECToDropletsToStripes\';
end
% --- Build paths ---
dataFile = fullfile(baseDir, 'SavedData', [datasetName '.mat']);
figSaveDir = fullfile(baseDir, 'SavedFigures', datasetName);
% --- Load dataset ---
data = load(dataFile);
% --- Ensure figure folder exists ---
if ~exist(figSaveDir, 'dir')
mkdir(figSaveDir);
end
% --- Access dataset struct dynamically ---
datasetStruct = data.(datasetName);
compiled_results = datasetStruct.results;
scan_parameter_values = datasetStruct.scan_parameter_values;
scan_reference_values = datasetStruct.scan_reference_values;
% --- Load options used during analysis ---
options = datasetStruct.options;
options.font = 'Bahnschrift'; % override if needed
options.skipSaveFigures = false; % override if needed
%% ------------------ 1. Mean ± Std Plots ------------------
% Plot Radial Spectral Contrast
Plotter.plotMeanWithSE(scan_parameter_values, compiled_results.spectral_analysis_results.radial_spectral_contrast, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', 'Radial Spectral Contrast', ...
'FigNum', 1, ...
'FontName', options.font, ...
'SaveFileName', 'RadialSpectralContrast.fig', ...
'SaveDirectory', figSaveDir, ... % save figures inside dataset-specific folder
'SkipSaveFigures', options.skipSaveFigures);
% Plot Angular Spectral Weight
Plotter.plotMeanWithSE(scan_parameter_values, compiled_results.spectral_analysis_results.angular_spectral_weight, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', 'Angular Spectral Weight', ...
'FigNum', 2, ...
'FontName', options.font, ...
'SaveFileName', 'AngularSpectralWeight.fig', ...
'SaveDirectory', figSaveDir, ...
'SkipSaveFigures', options.skipSaveFigures);
% Plot Peak Offset Angular Correlation
Plotter.plotMeanWithSE(scan_parameter_values, compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', '$\mathrm{max}[g^{(2)}_{[50,70]}(\delta\theta)]$', ...
'FigNum', 3, ...
'YLim', [0 1], ...
'FontName', options.font, ...
'SaveFileName', 'PeakOffsetAngularCorrelation.fig', ...
'SaveDirectory', figSaveDir, ...
'SkipSaveFigures', options.skipSaveFigures);
%% ------------------ 2. g²(θ) across transition ------------------
Plotter.plotG2MeanCurves(compiled_results.full_g2_results.g2_mean, ...
compiled_results.full_g2_results.g2_error, ...
compiled_results.full_g2_results.theta_values, ...
scan_reference_values, ...
options.scanParameterUnits, ...
'Title', options.titleString, ...
'XLabel', '$\delta\theta / \pi$', ...
'YLabel', '$g^{(2)}(\delta\theta)$', ...
'FigNum', 4, ...
'FontName', options.font, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'G2ThetaAcrossTransition.fig', ...
'SaveDirectory', figSaveDir, ...
'Colormap', @Colormaps.coolwarm);
%% ------------------ 3. Features of g²(θ) across transition ------------------
g2_analysis_results = Analyzer.analyzeAutocorrelation(compiled_results.full_g2_results);
Plotter.plotG2Curves(compiled_results.full_g2_results, ...
'Title', options.titleString, ...
'XLabel', '\delta\theta / \pi', ...
'YLabel', 'g^{(2)}(\delta\theta)', ...
'HighlightEvery', 10, ... % highlight every 10th repetition
'FontName', options.font, ...
'FigNum', 5, ...
'TileTitlePrefix', '\alpha', ... % user-defined tile prefix
'TileTitleSuffix', '^\circ', ... % user-defined suffix (e.g., Gauss symbol)...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'G2Curves.fig', ...
'SaveDirectory', figSaveDir);
Plotter.plotG2PDF(compiled_results.full_g2_results, pi/2, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'g^{(2)}(\delta\theta)', ...
'FontName', options.font, ...
'FontSize', 16, ...
'FigNum', 6, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'G2PDF_pi6.fig', ...
'SaveDirectory', figSaveDir, ...
'NumberOfBins', 20, ...
'NormalizeHistogram', true, ...
'DataRange', [0 1.0], ...
'Colormap', @Colormaps.coolwarm, ...
'ColorScale', 'log', ...
'XLim', [min(scan_reference_values) max(scan_reference_values)]);
Plotter.plotG2Features(g2_analysis_results, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'FontName', options.font, ...
'FigNum', 7, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'G2Features.fig', ...
'SaveDirectory', figSaveDir);
Plotter.plotG2Cumulants(g2_analysis_results, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'FontName', options.font, ...
'FigNum', 8, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'G2Cumulants.fig', ...
'SaveDirectory', figSaveDir);
%% ------------------ 4. PDF of max g² across transition ------------------
Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, ...
scan_reference_values, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', '$\mathrm{max}[g^{(2)}_{[50,70]}(\delta\theta)]$', ...
'FigNum', 9, ...
'FontName', options.font, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'PDF_MaxG2AcrossTransition.fig', ...
'SaveDirectory', figSaveDir, ...
'NumberOfBins', 20, ...
'NormalizeHistogram', true, ...
'DataRange', [0 1.5], ...
'Colormap', @Colormaps.coolwarm, ...
'XLim', [min(scan_reference_values) max(scan_reference_values)]);
%% ------------------ 5. Cumulants across transition ------------------
Plotter.plotCumulants(scan_reference_values, ...
{compiled_results.custom_g_results.mean_max_g2, compiled_results.custom_g_results.var_max_g2, compiled_results.custom_g_results.skew_max_g2_angle, compiled_results.custom_g_results.fourth_order_cumulant_max_g2}, ...
'Title', 'Cumulants of Peak Offset Angular Correlation', ...
'XLabel', '\alpha (degrees)', ...
'FigNum', 10, ...
'FontName', options.font, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'CumulantOfPeakOffsetAngularCorrelation.fig', ...
'SaveDirectory', figSaveDir);
%% ------------------ 6. PCA ------------------
Plotter.plotSinglePCAResults(compiled_results.pca_results, scan_parameter_values, scan_reference_values, ...
'FigNumRange', [11,12,13,14,15,16], ...
'XLabel', '\alpha (degrees)', ...
'FontName', options.font, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveDirectory', figSaveDir);
Plotter.plotMultiplePCAResults(compiled_results.pca_results, scan_parameter_values, scan_reference_values, ...
'MaxPCToPlot', 2, ...
'XLabel', '\alpha (degrees)', ...
'FigNumRange', [17,18,19], ...
'FontName', options.font, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveDirectory', figSaveDir);
%% ------------------ 7. Plot of all Angular Spectral Distribution Curves ------------------
Plotter.plotSpectralCurves( ...
results_all{1}.results.spectral_analysis_results.S_theta_norm_all, ...
results_all{1}.results.spectral_analysis_results.theta_vals/pi, ... % correct θ values
results_all{1}.scan_reference_values, ... % correct scan params
'Title', options.titleString, ...
'XLabel', '\theta / \pi', ...
'YLabel', 'S(\theta)', ...
'HighlightEvery', 10, ... % highlight every 10th repetition
'FontName', options.font, ...
'FigNum', 20, ...
'TileTitlePrefix', '\alpha', ... % user-defined tile prefix
'TileTitleSuffix', '^\circ', ... % user-defined suffix (e.g., degrees symbol)
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SpectralCurves.fig', ...
'SaveDirectory', figSaveDir);
%% ------------------ 8. Plot of all Angular Spectral Distribution Curves shifted ------------------
results = Plotter.plotSpectralCurvesRecentered( ...
results_all{1}.results.spectral_analysis_results.S_theta_norm_all, ...
results_all{1}.results.spectral_analysis_results.theta_vals/pi, ... % correct θ values
results_all{1}.scan_reference_values, ... % correct scan params
'Title', options.titleString, ...
'XLabel', '\theta / \pi', ...
'YLabel', 'S(\theta)', ...
'HighlightEvery', 10, ... % highlight every 10th repetition
'FontName', options.font, ...
'FigNum', 21, ...
'TileTitlePrefix', '\alpha', ... % user-defined tile prefix
'TileTitleSuffix', '^\circ', ... % user-defined suffix (e.g., degrees symbol)
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SpectralCurves.fig', ...
'SaveDirectory', figSaveDir);
%% ------------------ 9. Plot cumulants from shifted Angular Spectral Distribution Curves ------------------
Plotter.plotSpectralDistributionCumulants(results, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'FontName', options.font, ...
'FontSize', 14, ...
'FigNum', 22, ...
'SkipSaveFigures', false, ...
'SaveFileName', 'SpectralCumulants.fig');
%% ------------------ 10. Fit shifted Angular Spectral Distribution Curves ------------------
fitResults = Analyzer.fitTwoGaussianCurves(...
results_all{1}.results.spectral_analysis_results.S_theta_norm_all, ...
results_all{1}.results.spectral_analysis_results.theta_vals, ...
'MaxTheta', pi/2, ...
'DeviationLimit', 1.00);
%% ------------------ 11. Plot fit parameters - position ------------------
Plotter.plotFitParameterPDF(fitResults, results_all{1}.scan_reference_values, 'mu2', ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak position (\theta, rad)', ...
'FontName', options.font, ...
'FontSize', 16, ...
'FigNum', 23, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionPDF.fig', ...
'PlotType', 'histogram', ...
'NumberOfBins', 20, ...
'NormalizeHistogram', true, ...
'Colormap', @Colormaps.coolwarm, ...
'XLim', [min(results_all{1}.scan_reference_values), max(results_all{1}.scan_reference_values)]);
%% ------------------ 12. Plot fit parameters - width ------------------
Plotter.plotFitParameterPDF(fitResults, results_all{1}.scan_reference_values, 'sigma2', ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FontName', options.font, ...
'FontSize', 16, ...
'FigNum', 24, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthPDF.fig', ...
'PlotType', 'histogram', ...
'NumberOfBins', 20, ...
'NormalizeHistogram', true, ...
'Colormap', @Colormaps.coolwarm, ...
'XLim', [min(results_all{1}.scan_reference_values), max(results_all{1}.scan_reference_values)]);
%% ------------------ 13. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------
S_theta_all = results_all{1}.results.spectral_analysis_results.S_theta_norm_all;
theta_vals = results_all{1}.results.spectral_analysis_results.theta_vals;
scanValues = results_all{1}.scan_reference_values;
N_params = numel(scanValues);
N_total = numel(S_theta_all);
N_reps = N_total / N_params;
theta_min = deg2rad(0);
theta_max = deg2rad(90);
% --- Shift curves so first peak is at start ---
S_theta_all_shifted = cell(size(S_theta_all));
for k = 1:N_total
curve = S_theta_all{k};
idx_range = find(theta_vals >= theta_min & theta_vals <= theta_max);
if isempty(idx_range)
[~, peak_idx] = max(curve);
else
[~, local_max_idx] = max(curve(idx_range));
peak_idx = idx_range(local_max_idx);
end
S_theta_all_shifted{k} = curve(peak_idx:end);
end
% --- Pad shorter curves with NaN to match lengths ---
Npoints_shifted = max(cellfun(@numel, S_theta_all_shifted));
for k = 1:N_total
len = numel(S_theta_all_shifted{k});
if len < Npoints_shifted
S_theta_all_shifted{k} = [S_theta_all_shifted{k}, nan(1, Npoints_shifted-len)];
end
end
% --- Compute mean curves per scan parameter ---
meanCurves = cell(1, N_params);
for i = 1:N_params
curves = zeros(N_reps, Npoints_shifted);
for r = 1:N_reps
idx = (r-1)*N_params + i; % interleaved indexing
curves(r,:) = S_theta_all_shifted{idx};
end
meanCurves{i} = nanmean(curves,1); % mean over repetitions
end
% --- Fit two-Gaussian model to mean curves ---
fitResultsMean = Analyzer.fitTwoGaussianCurves(meanCurves, theta_vals(1:Npoints_shifted)-theta_vals(1), ...
'MaxTheta', pi/2, ...
'DeviationLimit', 1.0);
% --- Scatter plot of secondary peak position (mu2) vs scan parameter ---
mu2_vals = nan(1, N_params);
sigma2_vals = nan(1, N_params);
for i = 1:N_params
if fitResultsMean(i).isValid
mu2_vals(i) = fitResultsMean(i).pFit(4); % secondary peak position
sigma2_vals(i) = fitResultsMean(i).pFit(5); % secondary peak width
end
end
% Secondary peak position
plotSecondaryPeakScatter(fitResultsMean, results_all{1}.scan_reference_values, 'mu2', ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak position (\theta, rad)', ...
'FigNum', 23, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionScatter.fig');
% Secondary peak width
plotSecondaryPeakScatter(fitResultsMean, results_all{1}.scan_reference_values, 'sigma2', ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FigNum', 24, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthScatter.fig');
function plotSecondaryPeakScatter(fitResultsMean, scanValues, parameterName, varargin)
%% plotSecondaryPeakScatter
% Author: Karthik
% Date: 2025-10-06
% Version: 1.0
%
% Description:
% Scatter plot of secondary peak fit parameters (mu2 or sigma2) vs scan parameter
% in the same style as plotMeanWithSE.
% --- Parse optional inputs ---
p = inputParser;
addParameter(p, 'Title', '', @(x) ischar(x) || isstring(x));
addParameter(p, 'XLabel', '', @(x) ischar(x) || isstring(x));
addParameter(p, 'YLabel', '', @(x) ischar(x) || isstring(x));
addParameter(p, 'FigNum', [], @(x) isempty(x) || isscalar(x));
addParameter(p, 'FontName', 'Arial', @ischar);
addParameter(p, 'FontSize', 14, @isnumeric);
addParameter(p, 'YLim', [], @(x) isempty(x) || isnumeric(x));
addParameter(p, 'SkipSaveFigures', false, @islogical);
addParameter(p, 'SaveFileName', 'secondary_peak_scatter.fig', @ischar);
addParameter(p, 'SaveDirectory', pwd, @ischar);
parse(p, varargin{:});
opts = p.Results;
% --- Extract parameter values ---
N_params = numel(fitResultsMean);
paramVals = nan(1, N_params);
for i = 1:N_params
if fitResultsMean(i).isValid
switch parameterName
case 'mu2'
paramVals(i) = fitResultsMean(i).pFit(4);
case 'sigma2'
paramVals(i) = fitResultsMean(i).pFit(5);
otherwise
error('Unknown parameter name: %s', parameterName);
end
end
end
% --- Prepare figure ---
if isempty(opts.FigNum)
fig = figure;
else
fig = figure(opts.FigNum);
clf(fig);
end
set(fig, 'Color', 'w', 'Position', [100 100 950 750]);
% --- Plot as mean ± SE style (SE=0 here) ---
errorbar(scanValues, paramVals, zeros(size(paramVals)), 'o--', ...
'LineWidth', 1.8, 'MarkerSize', 6, 'CapSize', 5);
% --- Axis formatting ---
set(gca, 'FontName', opts.FontName, 'FontSize', opts.FontSize);
if ~isempty(opts.YLim)
ylim(opts.YLim);
end
xlabel(opts.XLabel, 'Interpreter', 'tex', 'FontName', opts.FontName, 'FontSize', opts.FontSize);
ylabel(opts.YLabel, 'Interpreter', 'tex', 'FontName', opts.FontName, 'FontSize', opts.FontSize);
title(opts.Title, 'FontName', opts.FontName, 'FontSize', opts.FontSize + 2, 'FontWeight', 'bold');
grid on;
% --- Save figure ---
if ~opts.SkipSaveFigures
if ~exist(opts.SaveDirectory, 'dir'), mkdir(opts.SaveDirectory); end
savefig(fig, fullfile(opts.SaveDirectory, opts.SaveFileName));
end
end
%{
%% ------------------ 14. Average of Spectra Plots ------------------
Plotter.plotAverageSpectra(scan_parameter_values, ...
spectral_analysis_results, ...
'ScanParameterName', scan_parameter, ...
'FigNum', 25, ...
'ColormapPS', Colormaps.coolwarm(), ...
'Font', 'Bahnschrift', ...
'SaveFileName', 'avgSpectra.fig', ...
'SaveDirectory', figSaveDir, ...
'SkipSaveFigures', options.skipSaveFigures);
%}