Minor modifications to scripts.

This commit is contained in:
Karthik 2025-10-17 20:31:33 +02:00
parent dd4145ccd2
commit 602c5e1fdd
8 changed files with 912 additions and 29 deletions

View File

@ -254,7 +254,6 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'sigma2', ...
'YLim', [0, 1.6]); 'YLim', [0, 1.6]);
%% ------------------ 8. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------ %% ------------------ 8. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------
% --- Recenter curves first --- % --- Recenter curves first ---
results = Analyzer.recenterSpectralCurves(spectral_analysis_results.S_theta_norm_all, ... results = Analyzer.recenterSpectralCurves(spectral_analysis_results.S_theta_norm_all, ...
spectral_analysis_results.theta_vals/pi, ... spectral_analysis_results.theta_vals/pi, ...
@ -339,6 +338,98 @@ Plotter.plotMeanWithSE(scan_reference_values, sigma2_vals, ...
'SaveFileName', 'SecondaryPeakWidthMeanWithSEM.fig', ... 'SaveFileName', 'SecondaryPeakWidthMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
%% ------------------ 9. Compare mean of individual fits vs fit of mean ------------------
paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6);
paramNames = {'A2', 'mu2', 'sigma2'};
paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'};
meanOfIndividualFits = struct();
fitOfMeanCurve = struct();
for p = 1:numel(paramNames)
paramName = paramNames{p};
paramLabel = paramLabels{p};
paramIdx = paramMap.(paramName);
% --- Mean of individual fits per scan_reference_values ---
meanVals = nan(size(scan_reference_values)); % already unique
for k = 1:numel(scan_reference_values)
thisAlpha = scan_reference_values(k);
mask = scan_parameter_values == thisAlpha; % pick all repetitions
pvals = arrayfun(@(f) f.pFit(paramIdx), fitResults(mask), 'UniformOutput', true);
meanVals(k) = mean(pvals(~isnan(pvals) & isfinite(pvals)), 'omitnan');
end
meanOfIndividualFits.(paramName) = meanVals;
% --- Fit of mean curve ---
switch paramName
case 'A2'
fitOfMeanCurve.(paramName) = amp2_vals;
case 'mu2'
fitOfMeanCurve.(paramName) = mu2_vals;
case 'sigma2'
fitOfMeanCurve.(paramName) = sigma2_vals;
end
% --- Plot comparison ---
fig = figure('Name', 'Comparison', 'NumberTitle', 'off');
set(fig, 'Color', 'w', 'Position', [100 100 950 750]);
hold on;
plot(scan_reference_values, meanOfIndividualFits.(paramName), 'o-', 'LineWidth', 1.8, ...
'DisplayName', 'Mean of Individual Fits');
plot(scan_reference_values, fitOfMeanCurve.(paramName), 's--', 'LineWidth', 1.8, ...
'DisplayName', 'Fit of Mean Curve');
hold off;
ylim([0, 1.1])
xlabel('\alpha (degrees)', 'FontName', options.font, 'FontSize', 16);
ylabel(paramLabel, 'FontName', options.font, 'FontSize', 16);
title(options.titleString, 'FontName', options.font, 'FontSize', 16);
legend('Location', 'northeast');
grid on;
set(gca, 'FontSize', 14);
if ~options.skipSaveFigures
saveas(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.fig']));
exportgraphics(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.png']), 'Resolution', 300);
end
end
%% ------------------ 10. Save Fit Results ------------------
outputDir = fullfile(options.saveDirectory, 'BECToD_ASDFitData');
if ~exist(outputDir, 'dir')
mkdir(outputDir);
end
% --- Define filenames for each variable ---
file_scanParamVals = fullfile(outputDir, 'scan_parameter_values');
file_scanRefVals = fullfile(outputDir, 'scan_reference_values');
file_fitResults = fullfile(outputDir, 'fitResults.mat');
file_rawCurves = fullfile(outputDir, 'rawCurves.mat');
file_spectralResults = fullfile(outputDir, 'spectral_analysis_results.mat');
file_meanFits = fullfile(outputDir, 'fitOfMeanCurve.mat');
file_indivFits = fullfile(outputDir, 'meanOfIndividualFits.mat');
% --- Save each variable separately ---
save(file_scanParamVals, 'scan_parameter_values', '-v7.3');
save(file_scanRefVals, 'scan_reference_values', '-v7.3');
save(file_fitResults, 'fitResults', '-v7.3');
save(file_rawCurves, 'rawCurves', '-v7.3');
save(file_spectralResults, 'spectral_analysis_results', '-v7.3');
save(file_meanFits, 'fitOfMeanCurve', '-v7.3');
save(file_indivFits, 'meanOfIndividualFits', '-v7.3');
fprintf('\n--- Fit data saved successfully ---\n');
fprintf('scanParamVals: %s\n', file_scanParamVals);
fprintf('scanRefVals: %s\n', file_scanRefVals);
fprintf('fitResults: %s\n', file_fitResults);
fprintf('rawCurves: %s\n', file_rawCurves);
fprintf('spectral_analysis_results:%s\n', file_spectralResults);
fprintf('fitOfMeanCurve: %s\n', file_meanFits);
fprintf('meanOfIndividualFits: %s\n', file_indivFits);
fprintf('----------------------------------\n\n');
%% Inspect individual realizations of a single parameter %% Inspect individual realizations of a single parameter
% --- Recenter curves first --- % --- Recenter curves first ---

View File

@ -122,10 +122,31 @@ Plotter.plotSpectralCurves( ...
'PositionThreshold', 0.5, ... % minimum separation between peaks 'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction 'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
% --- Post-fit diagnostics ---
pFit_all = vertcat(fitResults.pFit); % Ncurves x Nparams
isValid_all = [fitResults.isValid]; % logical vector
% Extract last three parameters (usually secondary peak amplitude, position, width)
pTail = pFit_all(:, end-2:end);
% Count curves where *any* of these last three values are NaN or zero
numWithNaN = sum(any(isnan(pTail), 2));
numWithZero = sum(any(pTail == 0, 2));
% Count of valid fits
numValid = sum(isValid_all);
% Display summary
fprintf('\n--- Fit diagnostics (last 3 params) ---\n');
fprintf('Curves with 1 NaN in last three pFit elements: %d\n', numWithNaN);
fprintf('Curves with 1 zero in last three pFit elements: %d\n', numWithZero);
fprintf('Curves marked as isValid = true: %d\n', numValid);
fprintf('----------------------------------------\n\n');
%% ------------------ Plot Fits on Raw ------------------ %% ------------------ Plot Fits on Raw ------------------
options.skipLivePlot = true; options.skipLivePlot = true;
options.skipSaveFigures = false; options.skipSaveFigures = false;
Plotter.plotTwoModeGaussianFitsOnRaw(fitResults, rawCurves, 4, 6, ... Plotter.plotTwoModeGaussianFitsOnRawRSD(fitResults, rawCurves, 4, 6, ...
'SkipLivePlot', options.skipLivePlot, ... 'SkipLivePlot', options.skipLivePlot, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
@ -140,7 +161,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
'YLabel', 'Secondary peak amplitude', ... 'YLabel', 'Secondary peak amplitude', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 4, ... 'FigNum', 2, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakAmplitudePDF.fig', ... 'SaveFileName', 'SecondaryPeakAmplitudePDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -158,7 +179,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'mu2', ...
'YLabel', 'Secondary peak position (\theta, rad)', ... 'YLabel', 'Secondary peak position (\theta, rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 5, ... 'FigNum', 3, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionPDF.fig', ... 'SaveFileName', 'SecondaryPeakPositionPDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -175,7 +196,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'sigma2', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ... 'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 6, ... 'FigNum', 4, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthPDF.fig', ... 'SaveFileName', 'SecondaryPeakWidthPDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -193,7 +214,7 @@ Plotter.plotSecondaryGaussianRange(fitResults, scan_reference_values, ...
'YLabel', '\mu_2 \pm \sigma_2 (rad)', ... 'YLabel', '\mu_2 \pm \sigma_2 (rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 8, ... 'FigNum', 5, ...
'NumberOfBins', 20, ... 'NumberOfBins', 20, ...
'NormalizeHistogram', true, ... 'NormalizeHistogram', true, ...
'Colormap', @Colormaps.coolwarm, ... 'Colormap', @Colormaps.coolwarm, ...
@ -202,4 +223,159 @@ Plotter.plotSecondaryGaussianRange(fitResults, scan_reference_values, ...
'SaveFileName', 'SecondaryGaussianRange.fig', ... 'SaveFileName', 'SecondaryGaussianRange.fig', ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
%% ------------------ 7. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------
avgData = Analyzer.computeSpectralAverages(spectral_analysis_results.S_k_all, scan_reference_values);
% Extract averaged curves (mean across repetitions)
curves_mean = avgData.curves_mean; % [N_scanValues × N_k_rho]
krho_values = spectral_analysis_results.k_rho_vals;
% ---------- Fit two-Gaussian model to mean curves ----------
[fitResultsMean, ~] = Analyzer.fitTwoGaussianCurvesToRadialSpectralDistribution(...
curves_mean, ...
krho_values, ...
'KRhoRange', [0, 3], ... % truncate curves to 0 <= k_rho <= 3
'AmplitudeRange', [0, 0.3], ... % truncate curves to y >= 0 (all amplitudes)
'ResidualThreshold', 0.15, ... % maximum allowed residual
'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
% ---------- Extract fit parameters ----------
N_params = numel(fitResultsMean);
amp2_vals = nan(1, N_params);
mu2_vals = nan(1, N_params);
sigma2_vals = nan(1, N_params);
for i = 1:N_params
pFit = fitResultsMean(i).pFit;
if all(~isnan(pFit))
amp2_vals(i) = pFit(4);
mu2_vals(i) = pFit(5);
sigma2_vals(i) = pFit(6);
end
end
% ---------- Plot with SEM ----------
Plotter.plotMeanWithSE(scan_reference_values, amp2_vals, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', 'Secondary peak amplitude', ...
'FigNum', 6, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakAmplitudeMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
Plotter.plotMeanWithSE(scan_reference_values, mu2_vals, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', 'Secondary peak position (\theta, rad)', ...
'FigNum', 7, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
Plotter.plotMeanWithSE(scan_reference_values, sigma2_vals, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FigNum', 8, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
%% ------------------ 8. Compare mean of individual fits vs fit of mean ------------------
paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6);
paramNames = {'A2', 'mu2', 'sigma2'};
paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'};
meanOfIndividualFits = struct();
fitOfMeanCurve = struct();
for p = 1:numel(paramNames)
paramName = paramNames{p};
paramLabel = paramLabels{p};
paramIdx = paramMap.(paramName);
% --- Mean of individual fits per scan_reference_values ---
meanVals = nan(size(scan_reference_values)); % already unique
for k = 1:numel(scan_reference_values)
thisAlpha = scan_reference_values(k);
mask = scan_parameter_values == thisAlpha; % pick all repetitions
pvals = arrayfun(@(f) f.pFit(paramIdx), fitResults(mask), 'UniformOutput', true);
meanVals(k) = mean(pvals(~isnan(pvals) & isfinite(pvals)), 'omitnan');
end
meanOfIndividualFits.(paramName) = meanVals;
% --- Fit of mean curve ---
switch paramName
case 'A2'
fitOfMeanCurve.(paramName) = amp2_vals;
case 'mu2'
fitOfMeanCurve.(paramName) = mu2_vals;
case 'sigma2'
fitOfMeanCurve.(paramName) = sigma2_vals;
end
% --- Plot comparison ---
fig = figure('Name', 'Comparison', 'NumberTitle', 'off');
set(fig, 'Color', 'w', 'Position', [100 100 950 750]);
hold on;
plot(scan_reference_values, meanOfIndividualFits.(paramName), 'o-', 'LineWidth', 1.8, ...
'DisplayName', 'Mean of Individual Fits');
plot(scan_reference_values, fitOfMeanCurve.(paramName), 's--', 'LineWidth', 1.8, ...
'DisplayName', 'Fit of Mean Curve');
hold off;
xlabel('\alpha (degrees)', 'FontName', options.font, 'FontSize', 16);
ylabel(paramLabel, 'FontName', options.font, 'FontSize', 16);
title(options.titleString, 'FontName', options.font, 'FontSize', 16);
legend('Location', 'northeast');
grid on;
set(gca, 'FontSize', 14);
if ~options.skipSaveFigures
saveas(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.fig']));
exportgraphics(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.png']), 'Resolution', 300);
end
end
%% ------------------ 9. Save Fit Results ------------------
outputDir = fullfile(options.saveDirectory, 'BECToD_RSDFitData');
if ~exist(outputDir, 'dir')
mkdir(outputDir);
end
% --- Define filenames for each variable ---
file_scanParamVals = fullfile(outputDir, 'scan_parameter_values');
file_scanRefVals = fullfile(outputDir, 'scan_reference_values');
file_fitResults = fullfile(outputDir, 'fitResults.mat');
file_rawCurves = fullfile(outputDir, 'rawCurves.mat');
file_spectralResults = fullfile(outputDir, 'spectral_analysis_results.mat');
file_meanFits = fullfile(outputDir, 'fitOfMeanCurve.mat');
file_indivFits = fullfile(outputDir, 'meanOfIndividualFits.mat');
% --- Save each variable separately ---
save(file_scanParamVals, 'scan_parameter_values', '-v7.3');
save(file_scanRefVals, 'scan_reference_values', '-v7.3');
save(file_fitResults, 'fitResults', '-v7.3');
save(file_rawCurves, 'rawCurves', '-v7.3');
save(file_spectralResults, 'spectral_analysis_results', '-v7.3');
save(file_meanFits, 'fitOfMeanCurve', '-v7.3');
save(file_indivFits, 'meanOfIndividualFits', '-v7.3');
fprintf('\n--- Fit data saved successfully ---\n');
fprintf('scanParamVals: %s\n', file_scanParamVals);
fprintf('scanRefVals: %s\n', file_scanRefVals);
fprintf('fitResults: %s\n', file_fitResults);
fprintf('rawCurves: %s\n', file_rawCurves);
fprintf('spectral_analysis_results:%s\n', file_spectralResults);
fprintf('fitOfMeanCurve: %s\n', file_meanFits);
fprintf('meanOfIndividualFits: %s\n', file_indivFits);
fprintf('----------------------------------\n\n');

View File

@ -340,7 +340,6 @@ Plotter.plotMeanWithSE(scan_reference_values, sigma2_vals, ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
%% ------------------ 9. Compare mean of individual fits vs fit of mean ------------------ %% ------------------ 9. Compare mean of individual fits vs fit of mean ------------------
paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6); paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6);
paramNames = {'A2', 'mu2', 'sigma2'}; paramNames = {'A2', 'mu2', 'sigma2'};
paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'}; paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'};
@ -398,8 +397,8 @@ for p = 1:numel(paramNames)
end end
end end
%% ------------------ 5. Save Fit Results ------------------ %% ------------------ 10. Save Fit Results ------------------
outputDir = fullfile(options.saveDirectory, 'DToS_FitData'); outputDir = fullfile(options.saveDirectory, 'DToS_ASDFitData');
if ~exist(outputDir, 'dir') if ~exist(outputDir, 'dir')
mkdir(outputDir); mkdir(outputDir);
end end

View File

@ -122,10 +122,31 @@ Plotter.plotSpectralCurves( ...
'PositionThreshold', 0.5, ... % minimum separation between peaks 'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction 'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
% --- Post-fit diagnostics ---
pFit_all = vertcat(fitResults.pFit); % Ncurves x Nparams
isValid_all = [fitResults.isValid]; % logical vector
% Extract last three parameters (usually secondary peak amplitude, position, width)
pTail = pFit_all(:, end-2:end);
% Count curves where *any* of these last three values are NaN or zero
numWithNaN = sum(any(isnan(pTail), 2));
numWithZero = sum(any(pTail == 0, 2));
% Count of valid fits
numValid = sum(isValid_all);
% Display summary
fprintf('\n--- Fit diagnostics (last 3 params) ---\n');
fprintf('Curves with 1 NaN in last three pFit elements: %d\n', numWithNaN);
fprintf('Curves with 1 zero in last three pFit elements: %d\n', numWithZero);
fprintf('Curves marked as isValid = true: %d\n', numValid);
fprintf('----------------------------------------\n\n');
%% ------------------ Plot Fits on Raw ------------------ %% ------------------ Plot Fits on Raw ------------------
options.skipLivePlot = true; options.skipLivePlot = true;
options.skipSaveFigures = false; options.skipSaveFigures = false;
Plotter.plotTwoModeGaussianFitsOnRaw(fitResults, rawCurves, 4, 6, ... Plotter.plotTwoModeGaussianFitsOnRawRSD(fitResults, rawCurves, 4, 6, ...
'SkipLivePlot', options.skipLivePlot, ... 'SkipLivePlot', options.skipLivePlot, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
@ -140,7 +161,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
'YLabel', 'Secondary peak amplitude', ... 'YLabel', 'Secondary peak amplitude', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 4, ... 'FigNum', 2, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakAmplitudePDF.fig', ... 'SaveFileName', 'SecondaryPeakAmplitudePDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -158,7 +179,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'mu2', ...
'YLabel', 'Secondary peak position (\theta, rad)', ... 'YLabel', 'Secondary peak position (\theta, rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 5, ... 'FigNum', 3, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionPDF.fig', ... 'SaveFileName', 'SecondaryPeakPositionPDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -175,7 +196,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'sigma2', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ... 'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 6, ... 'FigNum', 4, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthPDF.fig', ... 'SaveFileName', 'SecondaryPeakWidthPDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -193,7 +214,7 @@ Plotter.plotSecondaryGaussianRange(fitResults, scan_reference_values, ...
'YLabel', '\mu_2 \pm \sigma_2 (rad)', ... 'YLabel', '\mu_2 \pm \sigma_2 (rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 8, ... 'FigNum', 5, ...
'NumberOfBins', 20, ... 'NumberOfBins', 20, ...
'NormalizeHistogram', true, ... 'NormalizeHistogram', true, ...
'Colormap', @Colormaps.coolwarm, ... 'Colormap', @Colormaps.coolwarm, ...
@ -202,4 +223,159 @@ Plotter.plotSecondaryGaussianRange(fitResults, scan_reference_values, ...
'SaveFileName', 'SecondaryGaussianRange.fig', ... 'SaveFileName', 'SecondaryGaussianRange.fig', ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
%% ------------------ 7. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------
avgData = Analyzer.computeSpectralAverages(spectral_analysis_results.S_k_all, scan_reference_values);
% Extract averaged curves (mean across repetitions)
curves_mean = avgData.curves_mean; % [N_scanValues × N_k_rho]
krho_values = spectral_analysis_results.k_rho_vals;
% ---------- Fit two-Gaussian model to mean curves ----------
[fitResultsMean, ~] = Analyzer.fitTwoGaussianCurvesToRadialSpectralDistribution(...
curves_mean, ...
krho_values, ...
'KRhoRange', [0, 3], ... % truncate curves to 0 <= k_rho <= 3
'AmplitudeRange', [0, 0.3], ... % truncate curves to y >= 0 (all amplitudes)
'ResidualThreshold', 0.15, ... % maximum allowed residual
'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
% ---------- Extract fit parameters ----------
N_params = numel(fitResultsMean);
amp2_vals = nan(1, N_params);
mu2_vals = nan(1, N_params);
sigma2_vals = nan(1, N_params);
for i = 1:N_params
pFit = fitResultsMean(i).pFit;
if all(~isnan(pFit))
amp2_vals(i) = pFit(4);
mu2_vals(i) = pFit(5);
sigma2_vals(i) = pFit(6);
end
end
% ---------- Plot with SEM ----------
Plotter.plotMeanWithSE(scan_reference_values, amp2_vals, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak amplitude', ...
'FigNum', 6, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakAmplitudeMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
Plotter.plotMeanWithSE(scan_reference_values, mu2_vals, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak position (\theta, rad)', ...
'FigNum', 7, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
Plotter.plotMeanWithSE(scan_reference_values, sigma2_vals, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FigNum', 8, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
%% ------------------ 8. Compare mean of individual fits vs fit of mean ------------------
paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6);
paramNames = {'A2', 'mu2', 'sigma2'};
paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'};
meanOfIndividualFits = struct();
fitOfMeanCurve = struct();
for p = 1:numel(paramNames)
paramName = paramNames{p};
paramLabel = paramLabels{p};
paramIdx = paramMap.(paramName);
% --- Mean of individual fits per scan_reference_values ---
meanVals = nan(size(scan_reference_values)); % already unique
for k = 1:numel(scan_reference_values)
thisAlpha = scan_reference_values(k);
mask = scan_parameter_values == thisAlpha; % pick all repetitions
pvals = arrayfun(@(f) f.pFit(paramIdx), fitResults(mask), 'UniformOutput', true);
meanVals(k) = mean(pvals(~isnan(pvals) & isfinite(pvals)), 'omitnan');
end
meanOfIndividualFits.(paramName) = meanVals;
% --- Fit of mean curve ---
switch paramName
case 'A2'
fitOfMeanCurve.(paramName) = amp2_vals;
case 'mu2'
fitOfMeanCurve.(paramName) = mu2_vals;
case 'sigma2'
fitOfMeanCurve.(paramName) = sigma2_vals;
end
% --- Plot comparison ---
fig = figure('Name', 'Comparison', 'NumberTitle', 'off');
set(fig, 'Color', 'w', 'Position', [100 100 950 750]);
hold on;
plot(scan_reference_values, meanOfIndividualFits.(paramName), 'o-', 'LineWidth', 1.8, ...
'DisplayName', 'Mean of Individual Fits');
plot(scan_reference_values, fitOfMeanCurve.(paramName), 's--', 'LineWidth', 1.8, ...
'DisplayName', 'Fit of Mean Curve');
hold off;
xlabel('\alpha (degrees)', 'FontName', options.font, 'FontSize', 16);
ylabel(paramLabel, 'FontName', options.font, 'FontSize', 16);
title(options.titleString, 'FontName', options.font, 'FontSize', 16);
legend('Location', 'northeast');
grid on;
set(gca, 'FontSize', 14);
if ~options.skipSaveFigures
saveas(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.fig']));
exportgraphics(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.png']), 'Resolution', 300);
end
end
%% ------------------ 9. Save Fit Results ------------------
outputDir = fullfile(options.saveDirectory, 'DToS_RSDFitData');
if ~exist(outputDir, 'dir')
mkdir(outputDir);
end
% --- Define filenames for each variable ---
file_scanParamVals = fullfile(outputDir, 'scan_parameter_values');
file_scanRefVals = fullfile(outputDir, 'scan_reference_values');
file_fitResults = fullfile(outputDir, 'fitResults.mat');
file_rawCurves = fullfile(outputDir, 'rawCurves.mat');
file_spectralResults = fullfile(outputDir, 'spectral_analysis_results.mat');
file_meanFits = fullfile(outputDir, 'fitOfMeanCurve.mat');
file_indivFits = fullfile(outputDir, 'meanOfIndividualFits.mat');
% --- Save each variable separately ---
save(file_scanParamVals, 'scan_parameter_values', '-v7.3');
save(file_scanRefVals, 'scan_reference_values', '-v7.3');
save(file_fitResults, 'fitResults', '-v7.3');
save(file_rawCurves, 'rawCurves', '-v7.3');
save(file_spectralResults, 'spectral_analysis_results', '-v7.3');
save(file_meanFits, 'fitOfMeanCurve', '-v7.3');
save(file_indivFits, 'meanOfIndividualFits', '-v7.3');
fprintf('\n--- Fit data saved successfully ---\n');
fprintf('scanParamVals: %s\n', file_scanParamVals);
fprintf('scanRefVals: %s\n', file_scanRefVals);
fprintf('fitResults: %s\n', file_fitResults);
fprintf('rawCurves: %s\n', file_rawCurves);
fprintf('spectral_analysis_results:%s\n', file_spectralResults);
fprintf('fitOfMeanCurve: %s\n', file_meanFits);
fprintf('meanOfIndividualFits: %s\n', file_indivFits);
fprintf('----------------------------------\n\n');

View File

@ -254,7 +254,6 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'sigma2', ...
'YLim', [0, 1.6]); 'YLim', [0, 1.6]);
%% ------------------ 8. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------ %% ------------------ 8. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------
% --- Recenter curves first --- % --- Recenter curves first ---
results = Analyzer.recenterSpectralCurves(spectral_analysis_results.S_theta_norm_all, ... results = Analyzer.recenterSpectralCurves(spectral_analysis_results.S_theta_norm_all, ...
spectral_analysis_results.theta_vals/pi, ... spectral_analysis_results.theta_vals/pi, ...
@ -339,6 +338,98 @@ Plotter.plotMeanWithSE(scan_reference_values, sigma2_vals, ...
'SaveFileName', 'SecondaryPeakWidthMeanWithSEM.fig', ... 'SaveFileName', 'SecondaryPeakWidthMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
%% ------------------ 9. Compare mean of individual fits vs fit of mean ------------------
paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6);
paramNames = {'A2', 'mu2', 'sigma2'};
paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'};
meanOfIndividualFits = struct();
fitOfMeanCurve = struct();
for p = 1:numel(paramNames)
paramName = paramNames{p};
paramLabel = paramLabels{p};
paramIdx = paramMap.(paramName);
% --- Mean of individual fits per scan_reference_values ---
meanVals = nan(size(scan_reference_values)); % already unique
for k = 1:numel(scan_reference_values)
thisAlpha = scan_reference_values(k);
mask = scan_parameter_values == thisAlpha; % pick all repetitions
pvals = arrayfun(@(f) f.pFit(paramIdx), fitResults(mask), 'UniformOutput', true);
meanVals(k) = mean(pvals(~isnan(pvals) & isfinite(pvals)), 'omitnan');
end
meanOfIndividualFits.(paramName) = meanVals;
% --- Fit of mean curve ---
switch paramName
case 'A2'
fitOfMeanCurve.(paramName) = amp2_vals;
case 'mu2'
fitOfMeanCurve.(paramName) = mu2_vals;
case 'sigma2'
fitOfMeanCurve.(paramName) = sigma2_vals;
end
% --- Plot comparison ---
fig = figure('Name', 'Comparison', 'NumberTitle', 'off');
set(fig, 'Color', 'w', 'Position', [100 100 950 750]);
hold on;
plot(scan_reference_values, meanOfIndividualFits.(paramName), 'o-', 'LineWidth', 1.8, ...
'DisplayName', 'Mean of Individual Fits');
plot(scan_reference_values, fitOfMeanCurve.(paramName), 's--', 'LineWidth', 1.8, ...
'DisplayName', 'Fit of Mean Curve');
hold off;
ylim([0, 1.1])
xlabel('\alpha (degrees)', 'FontName', options.font, 'FontSize', 16);
ylabel(paramLabel, 'FontName', options.font, 'FontSize', 16);
title(options.titleString, 'FontName', options.font, 'FontSize', 16);
legend('Location', 'northeast');
grid on;
set(gca, 'FontSize', 14);
if ~options.skipSaveFigures
saveas(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.fig']));
exportgraphics(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.png']), 'Resolution', 300);
end
end
%% ------------------ 10. Save Fit Results ------------------
outputDir = fullfile(options.saveDirectory, 'BECToS_ASDFitData');
if ~exist(outputDir, 'dir')
mkdir(outputDir);
end
% --- Define filenames for each variable ---
file_scanParamVals = fullfile(outputDir, 'scan_parameter_values');
file_scanRefVals = fullfile(outputDir, 'scan_reference_values');
file_fitResults = fullfile(outputDir, 'fitResults.mat');
file_rawCurves = fullfile(outputDir, 'rawCurves.mat');
file_spectralResults = fullfile(outputDir, 'spectral_analysis_results.mat');
file_meanFits = fullfile(outputDir, 'fitOfMeanCurve.mat');
file_indivFits = fullfile(outputDir, 'meanOfIndividualFits.mat');
% --- Save each variable separately ---
save(file_scanParamVals, 'scan_parameter_values', '-v7.3');
save(file_scanRefVals, 'scan_reference_values', '-v7.3');
save(file_fitResults, 'fitResults', '-v7.3');
save(file_rawCurves, 'rawCurves', '-v7.3');
save(file_spectralResults, 'spectral_analysis_results', '-v7.3');
save(file_meanFits, 'fitOfMeanCurve', '-v7.3');
save(file_indivFits, 'meanOfIndividualFits', '-v7.3');
fprintf('\n--- Fit data saved successfully ---\n');
fprintf('scanParamVals: %s\n', file_scanParamVals);
fprintf('scanRefVals: %s\n', file_scanRefVals);
fprintf('fitResults: %s\n', file_fitResults);
fprintf('rawCurves: %s\n', file_rawCurves);
fprintf('spectral_analysis_results:%s\n', file_spectralResults);
fprintf('fitOfMeanCurve: %s\n', file_meanFits);
fprintf('meanOfIndividualFits: %s\n', file_indivFits);
fprintf('----------------------------------\n\n');
%% Inspect individual realizations of a single parameter %% Inspect individual realizations of a single parameter
% --- Recenter curves first --- % --- Recenter curves first ---

View File

@ -122,10 +122,31 @@ Plotter.plotSpectralCurves( ...
'PositionThreshold', 0.5, ... % minimum separation between peaks 'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction 'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
% --- Post-fit diagnostics ---
pFit_all = vertcat(fitResults.pFit); % Ncurves x Nparams
isValid_all = [fitResults.isValid]; % logical vector
% Extract last three parameters (usually secondary peak amplitude, position, width)
pTail = pFit_all(:, end-2:end);
% Count curves where *any* of these last three values are NaN or zero
numWithNaN = sum(any(isnan(pTail), 2));
numWithZero = sum(any(pTail == 0, 2));
% Count of valid fits
numValid = sum(isValid_all);
% Display summary
fprintf('\n--- Fit diagnostics (last 3 params) ---\n');
fprintf('Curves with 1 NaN in last three pFit elements: %d\n', numWithNaN);
fprintf('Curves with 1 zero in last three pFit elements: %d\n', numWithZero);
fprintf('Curves marked as isValid = true: %d\n', numValid);
fprintf('----------------------------------------\n\n');
%% ------------------ Plot Fits on Raw ------------------ %% ------------------ Plot Fits on Raw ------------------
options.skipLivePlot = true; options.skipLivePlot = true;
options.skipSaveFigures = false; options.skipSaveFigures = false;
Plotter.plotTwoModeGaussianFitsOnRaw(fitResults, rawCurves, 4, 6, ... Plotter.plotTwoModeGaussianFitsOnRawRSD(fitResults, rawCurves, 4, 6, ...
'SkipLivePlot', options.skipLivePlot, ... 'SkipLivePlot', options.skipLivePlot, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
@ -140,7 +161,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
'YLabel', 'Secondary peak amplitude', ... 'YLabel', 'Secondary peak amplitude', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 4, ... 'FigNum', 2, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakAmplitudePDF.fig', ... 'SaveFileName', 'SecondaryPeakAmplitudePDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -158,7 +179,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'mu2', ...
'YLabel', 'Secondary peak position (\theta, rad)', ... 'YLabel', 'Secondary peak position (\theta, rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 5, ... 'FigNum', 3, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionPDF.fig', ... 'SaveFileName', 'SecondaryPeakPositionPDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -175,7 +196,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'sigma2', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ... 'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 6, ... 'FigNum', 4, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthPDF.fig', ... 'SaveFileName', 'SecondaryPeakWidthPDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -193,7 +214,7 @@ Plotter.plotSecondaryGaussianRange(fitResults, scan_reference_values, ...
'YLabel', '\mu_2 \pm \sigma_2 (rad)', ... 'YLabel', '\mu_2 \pm \sigma_2 (rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 8, ... 'FigNum', 5, ...
'NumberOfBins', 20, ... 'NumberOfBins', 20, ...
'NormalizeHistogram', true, ... 'NormalizeHistogram', true, ...
'Colormap', @Colormaps.coolwarm, ... 'Colormap', @Colormaps.coolwarm, ...
@ -202,4 +223,159 @@ Plotter.plotSecondaryGaussianRange(fitResults, scan_reference_values, ...
'SaveFileName', 'SecondaryGaussianRange.fig', ... 'SaveFileName', 'SecondaryGaussianRange.fig', ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
%% ------------------ 7. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------
avgData = Analyzer.computeSpectralAverages(spectral_analysis_results.S_k_all, scan_reference_values);
% Extract averaged curves (mean across repetitions)
curves_mean = avgData.curves_mean; % [N_scanValues × N_k_rho]
krho_values = spectral_analysis_results.k_rho_vals;
% ---------- Fit two-Gaussian model to mean curves ----------
[fitResultsMean, ~] = Analyzer.fitTwoGaussianCurvesToRadialSpectralDistribution(...
curves_mean, ...
krho_values, ...
'KRhoRange', [0, 3], ... % truncate curves to 0 <= k_rho <= 3
'AmplitudeRange', [0, 0.3], ... % truncate curves to y >= 0 (all amplitudes)
'ResidualThreshold', 0.15, ... % maximum allowed residual
'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
% ---------- Extract fit parameters ----------
N_params = numel(fitResultsMean);
amp2_vals = nan(1, N_params);
mu2_vals = nan(1, N_params);
sigma2_vals = nan(1, N_params);
for i = 1:N_params
pFit = fitResultsMean(i).pFit;
if all(~isnan(pFit))
amp2_vals(i) = pFit(4);
mu2_vals(i) = pFit(5);
sigma2_vals(i) = pFit(6);
end
end
% ---------- Plot with SEM ----------
Plotter.plotMeanWithSE(scan_reference_values, amp2_vals, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', 'Secondary peak amplitude', ...
'FigNum', 6, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakAmplitudeMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
Plotter.plotMeanWithSE(scan_reference_values, mu2_vals, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', 'Secondary peak position (\theta, rad)', ...
'FigNum', 7, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
Plotter.plotMeanWithSE(scan_reference_values, sigma2_vals, ...
'Title', options.titleString, ...
'XLabel', 'B (G)', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FigNum', 8, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
%% ------------------ 8. Compare mean of individual fits vs fit of mean ------------------
paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6);
paramNames = {'A2', 'mu2', 'sigma2'};
paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'};
meanOfIndividualFits = struct();
fitOfMeanCurve = struct();
for p = 1:numel(paramNames)
paramName = paramNames{p};
paramLabel = paramLabels{p};
paramIdx = paramMap.(paramName);
% --- Mean of individual fits per scan_reference_values ---
meanVals = nan(size(scan_reference_values)); % already unique
for k = 1:numel(scan_reference_values)
thisAlpha = scan_reference_values(k);
mask = scan_parameter_values == thisAlpha; % pick all repetitions
pvals = arrayfun(@(f) f.pFit(paramIdx), fitResults(mask), 'UniformOutput', true);
meanVals(k) = mean(pvals(~isnan(pvals) & isfinite(pvals)), 'omitnan');
end
meanOfIndividualFits.(paramName) = meanVals;
% --- Fit of mean curve ---
switch paramName
case 'A2'
fitOfMeanCurve.(paramName) = amp2_vals;
case 'mu2'
fitOfMeanCurve.(paramName) = mu2_vals;
case 'sigma2'
fitOfMeanCurve.(paramName) = sigma2_vals;
end
% --- Plot comparison ---
fig = figure('Name', 'Comparison', 'NumberTitle', 'off');
set(fig, 'Color', 'w', 'Position', [100 100 950 750]);
hold on;
plot(scan_reference_values, meanOfIndividualFits.(paramName), 'o-', 'LineWidth', 1.8, ...
'DisplayName', 'Mean of Individual Fits');
plot(scan_reference_values, fitOfMeanCurve.(paramName), 's--', 'LineWidth', 1.8, ...
'DisplayName', 'Fit of Mean Curve');
hold off;
xlabel('\alpha (degrees)', 'FontName', options.font, 'FontSize', 16);
ylabel(paramLabel, 'FontName', options.font, 'FontSize', 16);
title(options.titleString, 'FontName', options.font, 'FontSize', 16);
legend('Location', 'northeast');
grid on;
set(gca, 'FontSize', 14);
if ~options.skipSaveFigures
saveas(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.fig']));
exportgraphics(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.png']), 'Resolution', 300);
end
end
%% ------------------ 9. Save Fit Results ------------------
outputDir = fullfile(options.saveDirectory, 'BECToS_RSDFitData');
if ~exist(outputDir, 'dir')
mkdir(outputDir);
end
% --- Define filenames for each variable ---
file_scanParamVals = fullfile(outputDir, 'scan_parameter_values');
file_scanRefVals = fullfile(outputDir, 'scan_reference_values');
file_fitResults = fullfile(outputDir, 'fitResults.mat');
file_rawCurves = fullfile(outputDir, 'rawCurves.mat');
file_spectralResults = fullfile(outputDir, 'spectral_analysis_results.mat');
file_meanFits = fullfile(outputDir, 'fitOfMeanCurve.mat');
file_indivFits = fullfile(outputDir, 'meanOfIndividualFits.mat');
% --- Save each variable separately ---
save(file_scanParamVals, 'scan_parameter_values', '-v7.3');
save(file_scanRefVals, 'scan_reference_values', '-v7.3');
save(file_fitResults, 'fitResults', '-v7.3');
save(file_rawCurves, 'rawCurves', '-v7.3');
save(file_spectralResults, 'spectral_analysis_results', '-v7.3');
save(file_meanFits, 'fitOfMeanCurve', '-v7.3');
save(file_indivFits, 'meanOfIndividualFits', '-v7.3');
fprintf('\n--- Fit data saved successfully ---\n');
fprintf('scanParamVals: %s\n', file_scanParamVals);
fprintf('scanRefVals: %s\n', file_scanRefVals);
fprintf('fitResults: %s\n', file_fitResults);
fprintf('rawCurves: %s\n', file_rawCurves);
fprintf('spectral_analysis_results:%s\n', file_spectralResults);
fprintf('fitOfMeanCurve: %s\n', file_meanFits);
fprintf('meanOfIndividualFits: %s\n', file_indivFits);
fprintf('----------------------------------\n\n');

View File

@ -254,7 +254,6 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'sigma2', ...
'YLim', [0, 1.6]); 'YLim', [0, 1.6]);
%% ------------------ 8. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------ %% ------------------ 8. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------
% --- Recenter curves first --- % --- Recenter curves first ---
results = Analyzer.recenterSpectralCurves(spectral_analysis_results.S_theta_norm_all, ... results = Analyzer.recenterSpectralCurves(spectral_analysis_results.S_theta_norm_all, ...
spectral_analysis_results.theta_vals/pi, ... spectral_analysis_results.theta_vals/pi, ...
@ -340,7 +339,6 @@ Plotter.plotMeanWithSE(scan_reference_values, sigma2_vals, ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
%% ------------------ 9. Compare mean of individual fits vs fit of mean ------------------ %% ------------------ 9. Compare mean of individual fits vs fit of mean ------------------
paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6); paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6);
paramNames = {'A2', 'mu2', 'sigma2'}; paramNames = {'A2', 'mu2', 'sigma2'};
paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'}; paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'};
@ -398,8 +396,8 @@ for p = 1:numel(paramNames)
end end
end end
%% ------------------ 5. Save Fit Results ------------------ %% ------------------ 10. Save Fit Results ------------------
outputDir = fullfile(options.saveDirectory, 'SToD_FitData'); outputDir = fullfile(options.saveDirectory, 'SToD_ASDFitData');
if ~exist(outputDir, 'dir') if ~exist(outputDir, 'dir')
mkdir(outputDir); mkdir(outputDir);
end end

View File

@ -122,10 +122,31 @@ Plotter.plotSpectralCurves( ...
'PositionThreshold', 0.5, ... % minimum separation between peaks 'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction 'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
% --- Post-fit diagnostics ---
pFit_all = vertcat(fitResults.pFit); % Ncurves x Nparams
isValid_all = [fitResults.isValid]; % logical vector
% Extract last three parameters (usually secondary peak amplitude, position, width)
pTail = pFit_all(:, end-2:end);
% Count curves where *any* of these last three values are NaN or zero
numWithNaN = sum(any(isnan(pTail), 2));
numWithZero = sum(any(pTail == 0, 2));
% Count of valid fits
numValid = sum(isValid_all);
% Display summary
fprintf('\n--- Fit diagnostics (last 3 params) ---\n');
fprintf('Curves with 1 NaN in last three pFit elements: %d\n', numWithNaN);
fprintf('Curves with 1 zero in last three pFit elements: %d\n', numWithZero);
fprintf('Curves marked as isValid = true: %d\n', numValid);
fprintf('----------------------------------------\n\n');
%% ------------------ Plot Fits on Raw ------------------ %% ------------------ Plot Fits on Raw ------------------
options.skipLivePlot = true; options.skipLivePlot = true;
options.skipSaveFigures = false; options.skipSaveFigures = false;
Plotter.plotTwoModeGaussianFitsOnRaw(fitResults, rawCurves, 4, 6, ... Plotter.plotTwoModeGaussianFitsOnRawRSD(fitResults, rawCurves, 4, 6, ...
'SkipLivePlot', options.skipLivePlot, ... 'SkipLivePlot', options.skipLivePlot, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
@ -140,7 +161,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
'YLabel', 'Secondary peak amplitude', ... 'YLabel', 'Secondary peak amplitude', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 4, ... 'FigNum', 2, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakAmplitudePDF.fig', ... 'SaveFileName', 'SecondaryPeakAmplitudePDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -158,7 +179,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'mu2', ...
'YLabel', 'Secondary peak position (\theta, rad)', ... 'YLabel', 'Secondary peak position (\theta, rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 5, ... 'FigNum', 3, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionPDF.fig', ... 'SaveFileName', 'SecondaryPeakPositionPDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -175,7 +196,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'sigma2', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ... 'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 6, ... 'FigNum', 4, ...
'SkipSaveFigures', options.skipSaveFigures, ... 'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthPDF.fig', ... 'SaveFileName', 'SecondaryPeakWidthPDF.fig', ...
'SaveDirectory', options.saveDirectory, ... 'SaveDirectory', options.saveDirectory, ...
@ -193,7 +214,7 @@ Plotter.plotSecondaryGaussianRange(fitResults, scan_reference_values, ...
'YLabel', '\mu_2 \pm \sigma_2 (rad)', ... 'YLabel', '\mu_2 \pm \sigma_2 (rad)', ...
'FontName', options.font, ... 'FontName', options.font, ...
'FontSize', 16, ... 'FontSize', 16, ...
'FigNum', 8, ... 'FigNum', 5, ...
'NumberOfBins', 20, ... 'NumberOfBins', 20, ...
'NormalizeHistogram', true, ... 'NormalizeHistogram', true, ...
'Colormap', @Colormaps.coolwarm, ... 'Colormap', @Colormaps.coolwarm, ...
@ -202,4 +223,159 @@ Plotter.plotSecondaryGaussianRange(fitResults, scan_reference_values, ...
'SaveFileName', 'SecondaryGaussianRange.fig', ... 'SaveFileName', 'SecondaryGaussianRange.fig', ...
'SaveDirectory', options.saveDirectory); 'SaveDirectory', options.saveDirectory);
%% ------------------ 7. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------
avgData = Analyzer.computeSpectralAverages(spectral_analysis_results.S_k_all, scan_reference_values);
% Extract averaged curves (mean across repetitions)
curves_mean = avgData.curves_mean; % [N_scanValues × N_k_rho]
krho_values = spectral_analysis_results.k_rho_vals;
% ---------- Fit two-Gaussian model to mean curves ----------
[fitResultsMean, ~] = Analyzer.fitTwoGaussianCurvesToRadialSpectralDistribution(...
curves_mean, ...
krho_values, ...
'KRhoRange', [0, 3], ... % truncate curves to 0 <= k_rho <= 3
'AmplitudeRange', [0, 0.3], ... % truncate curves to y >= 0 (all amplitudes)
'ResidualThreshold', 0.15, ... % maximum allowed residual
'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
% ---------- Extract fit parameters ----------
N_params = numel(fitResultsMean);
amp2_vals = nan(1, N_params);
mu2_vals = nan(1, N_params);
sigma2_vals = nan(1, N_params);
for i = 1:N_params
pFit = fitResultsMean(i).pFit;
if all(~isnan(pFit))
amp2_vals(i) = pFit(4);
mu2_vals(i) = pFit(5);
sigma2_vals(i) = pFit(6);
end
end
% ---------- Plot with SEM ----------
Plotter.plotMeanWithSE(scan_reference_values, amp2_vals, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak amplitude', ...
'FigNum', 6, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakAmplitudeMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
Plotter.plotMeanWithSE(scan_reference_values, mu2_vals, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak position (\theta, rad)', ...
'FigNum', 7, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakPositionMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
Plotter.plotMeanWithSE(scan_reference_values, sigma2_vals, ...
'Title', options.titleString, ...
'XLabel', '\alpha (degrees)', ...
'YLabel', 'Secondary peak width (\sigma, rad)', ...
'FigNum', 8, ...
'FontName', options.font, ...
'FontSize', 16, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SecondaryPeakWidthMeanWithSEM.fig', ...
'SaveDirectory', options.saveDirectory);
%% ------------------ 8. Compare mean of individual fits vs fit of mean ------------------
paramMap = struct('A1',1,'mu1',2,'sigma1',3,'A2',4,'mu2',5,'sigma2',6);
paramNames = {'A2', 'mu2', 'sigma2'};
paramLabels = {'Secondary peak amplitude', 'Secondary peak position (\theta, rad)', 'Secondary peak width (\sigma, rad)'};
meanOfIndividualFits = struct();
fitOfMeanCurve = struct();
for p = 1:numel(paramNames)
paramName = paramNames{p};
paramLabel = paramLabels{p};
paramIdx = paramMap.(paramName);
% --- Mean of individual fits per scan_reference_values ---
meanVals = nan(size(scan_reference_values)); % already unique
for k = 1:numel(scan_reference_values)
thisAlpha = scan_reference_values(k);
mask = scan_parameter_values == thisAlpha; % pick all repetitions
pvals = arrayfun(@(f) f.pFit(paramIdx), fitResults(mask), 'UniformOutput', true);
meanVals(k) = mean(pvals(~isnan(pvals) & isfinite(pvals)), 'omitnan');
end
meanOfIndividualFits.(paramName) = meanVals;
% --- Fit of mean curve ---
switch paramName
case 'A2'
fitOfMeanCurve.(paramName) = amp2_vals;
case 'mu2'
fitOfMeanCurve.(paramName) = mu2_vals;
case 'sigma2'
fitOfMeanCurve.(paramName) = sigma2_vals;
end
% --- Plot comparison ---
fig = figure('Name', 'Comparison', 'NumberTitle', 'off');
set(fig, 'Color', 'w', 'Position', [100 100 950 750]);
hold on;
plot(scan_reference_values, meanOfIndividualFits.(paramName), 'o-', 'LineWidth', 1.8, ...
'DisplayName', 'Mean of Individual Fits');
plot(scan_reference_values, fitOfMeanCurve.(paramName), 's--', 'LineWidth', 1.8, ...
'DisplayName', 'Fit of Mean Curve');
hold off;
xlabel('\alpha (degrees)', 'FontName', options.font, 'FontSize', 16);
ylabel(paramLabel, 'FontName', options.font, 'FontSize', 16);
title(options.titleString, 'FontName', options.font, 'FontSize', 16);
legend('Location', 'northeast');
grid on;
set(gca, 'FontSize', 14);
if ~options.skipSaveFigures
saveas(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.fig']));
exportgraphics(fig, fullfile(options.saveDirectory, ['Compare_' paramName '.png']), 'Resolution', 300);
end
end
%% ------------------ 9. Save Fit Results ------------------
outputDir = fullfile(options.saveDirectory, 'SToD_RSDFitData');
if ~exist(outputDir, 'dir')
mkdir(outputDir);
end
% --- Define filenames for each variable ---
file_scanParamVals = fullfile(outputDir, 'scan_parameter_values');
file_scanRefVals = fullfile(outputDir, 'scan_reference_values');
file_fitResults = fullfile(outputDir, 'fitResults.mat');
file_rawCurves = fullfile(outputDir, 'rawCurves.mat');
file_spectralResults = fullfile(outputDir, 'spectral_analysis_results.mat');
file_meanFits = fullfile(outputDir, 'fitOfMeanCurve.mat');
file_indivFits = fullfile(outputDir, 'meanOfIndividualFits.mat');
% --- Save each variable separately ---
save(file_scanParamVals, 'scan_parameter_values', '-v7.3');
save(file_scanRefVals, 'scan_reference_values', '-v7.3');
save(file_fitResults, 'fitResults', '-v7.3');
save(file_rawCurves, 'rawCurves', '-v7.3');
save(file_spectralResults, 'spectral_analysis_results', '-v7.3');
save(file_meanFits, 'fitOfMeanCurve', '-v7.3');
save(file_indivFits, 'meanOfIndividualFits', '-v7.3');
fprintf('\n--- Fit data saved successfully ---\n');
fprintf('scanParamVals: %s\n', file_scanParamVals);
fprintf('scanRefVals: %s\n', file_scanRefVals);
fprintf('fitResults: %s\n', file_fitResults);
fprintf('rawCurves: %s\n', file_rawCurves);
fprintf('spectral_analysis_results:%s\n', file_spectralResults);
fprintf('fitOfMeanCurve: %s\n', file_meanFits);
fprintf('meanOfIndividualFits: %s\n', file_indivFits);
fprintf('----------------------------------\n\n');