Replaced plotting of raw and fit curves for the radial and angular spectral distributions with an interactive viewer (Still will put back the plotting function for direct saving to file).

This commit is contained in:
Karthik 2025-10-16 19:06:38 +02:00
parent 5faf433329
commit 5761d3b0fe
12 changed files with 496 additions and 559 deletions

View File

@ -171,15 +171,17 @@ function [fitResults, rawCurves] = fitTwoGaussianCurvesToAngularSpectralDistribu
thetaFine = linspace(0, opts.MaxTheta, 500);
yFit = 1.0*exp(-0.5*((thetaFine - pCanonical(2))/max(pCanonical(3),1e-6)).^2) + ...
pCanonical(4)*exp(-0.5*((thetaFine - pCanonical(5))/max(pCanonical(6),1e-6)).^2);
fitResults(k).pFit = pCanonical;
fitResults(k).thetaFit = theta;
fitResults(k).xFit = x;
fitResults(k).thetaFine = thetaFine;
fitResults(k).yFit = yFit;
fitResults(k).isValid = true;
fitResults(k).fitMaxTheta = fitMaxTheta;
continue; % success next curve
if ~isnan(pCanonical)
fitResults(k).pFit = pCanonical;
fitResults(k).thetaFit = theta;
fitResults(k).xFit = x;
fitResults(k).thetaFine = thetaFine;
fitResults(k).yFit = yFit;
fitResults(k).isValid = true;
fitResults(k).fitMaxTheta = fitMaxTheta;
continue; % success next curve
end
catch
warning('Curve %d constrained fit failed, switching to generic fit.', k);
end
@ -209,14 +211,16 @@ function [fitResults, rawCurves] = fitTwoGaussianCurvesToAngularSpectralDistribu
fitMaxTheta = max(pFree(5), pFree(2));
thetaFine = linspace(0, opts.MaxTheta, 500);
yFit = twoGaussFree(pFree, thetaFine);
fitResults(k).pFit = pFree;
fitResults(k).thetaFit = theta;
fitResults(k).xFit = x;
fitResults(k).thetaFine = thetaFine;
fitResults(k).yFit = yFit;
fitResults(k).isValid = true;
fitResults(k).fitMaxTheta = fitMaxTheta;
if ~isnan(pFree)
fitResults(k).pFit = pFree;
fitResults(k).thetaFit = theta;
fitResults(k).xFit = x;
fitResults(k).thetaFine = thetaFine;
fitResults(k).yFit = yFit;
fitResults(k).isValid = true;
fitResults(k).fitMaxTheta = fitMaxTheta;
end
catch
warning('Curve %d: generic two-Gaussian fit failed.', k);
fitResults(k) = fillNaNStruct();

View File

@ -103,14 +103,16 @@ function [fitResults, rawCurves] = fitTwoGaussianCurvesToRadialSpectralDistribut
fitMaxKRho = max(pFit(5), pFit(2));
kFine = linspace(min(kVals), max(kVals), 500);
yFit = twoGauss(pFit, kFine);
fitResults(k).pFit = pFit;
fitResults(k).kFit = kVals;
fitResults(k).xFit = x;
fitResults(k).kFine = kFine;
fitResults(k).yFit = yFit;
fitResults(k).isValid = true;
fitResults(k).fitMaxKRho = fitMaxKRho;
if ~isnan(pFit)
fitResults(k).pFit = pFit;
fitResults(k).kFit = kVals;
fitResults(k).xFit = x;
fitResults(k).kFine = kFine;
fitResults(k).yFit = yFit;
fitResults(k).isValid = true;
fitResults(k).fitMaxKRho = fitMaxKRho;
end
catch
warning('Curve %d fit failed completely.', k);

View File

@ -0,0 +1,228 @@
function runInteractiveASDTwoGaussianFitGUI(spectral_analysis_results)
%% runInteractiveASDTwoGaussianFitGUI
% Author: Karthik
% Date: 2025-10-16
% Version: 1.0
%
% Description:
% Interactive viewer for raw angular spectral distributions.
% Lets user browse through individual curves and refit two-Gaussian models
% live as threshold parameters are adjusted.
%
% Controls:
% - Slider or / keys to browse curves
% - Editable boxes for thresholds (Residual, Position, Amplitude, MaxTheta)
% - "Re-fit" button triggers recomputation
%
% Dependencies:
% Requires Analyzer.fitTwoGaussianCurvesToAngularSpectralDistribution.m
%% --- Initialization ---
rawCurves.x = spectral_analysis_results.S_theta_norm_all;
rawCurves.theta = spectral_analysis_results.theta_vals;
% Handle input organization
if iscell(rawCurves.x)
Ncurves = numel(rawCurves.x);
else
Ncurves = size(rawCurves.x, 1);
tmp = arrayfun(@(i) struct('x', rawCurves.x(i, :), 'theta', rawCurves.theta(:)'), 1:Ncurves);
rawCurves = tmp(:);
end
% Default fit parameters
params.MaxTheta = pi/2;
params.ResidualThreshold = 0.15;
params.PositionThreshold = pi/15;
params.AmplitudeThreshold = 0.15;
currentIdx = 1;
%% --- Create figure ---
hFig = findobj('Type','figure','Tag','InteractiveTwoGaussianFit');
if isempty(hFig)
hFig = figure('Name','Angular Spectra Fit Viewer',...
'NumberTitle','off',...
'Position',[100 100 1250 800],...
'Color','w',...
'KeyPressFcn',@keyPressCallback,...
'Tag','InteractiveTwoGaussianFit');
else
figure(hFig); clf(hFig);
end
%% --- Axes for plot ---
hAx = axes('Parent',hFig,'Position',[0.08 0.1 0.55 0.8]);
grid(hAx,'on'); box(hAx,'on');
xlabel(hAx,'\theta (rad)','FontSize',12);
ylabel(hAx,'Normalized amplitude','FontSize',12);
%% --- Slider for curve index ---
hSlider = uicontrol('Style','slider','Min',1,'Max',Ncurves,'Value',1,...
'SliderStep',[1/(Ncurves-1), 10/(Ncurves-1)],...
'Units','normalized','Position',[0.1 0.02 0.5 0.03],...
'Callback',@(~,~) updatePlot());
%% --- Parameter definitions ---
paramNames = {'MaxTheta','ResidualThreshold','PositionThreshold','AmplitudeThreshold'};
paramLabels = {'Max Theta (rad)', 'Residual Threshold', 'Position Threshold (rad)', 'Amplitude Threshold'};
paramDescs = {'Upper limit for fitting range',...
'Maximum mean residual for valid fits',...
'Minimum peak separation required',...
'Minimum amplitude ratio threshold'};
nParams = numel(paramNames);
hEdit = gobjects(nParams,1);
baseY = 0.88;
%% --- Create parameter controls ---
for i = 1:nParams
yPos = baseY - 0.12*(i-1);
% Label
uicontrol('Style','text','Units','normalized',...
'Position',[0.68 yPos 0.25 0.04],...
'String',paramLabels{i},...
'HorizontalAlignment','left',...
'FontSize',10,'FontWeight','bold',...
'BackgroundColor','w');
% Edit box
hEdit(i) = uicontrol('Style','edit','Units','normalized',...
'Position',[0.9 yPos 0.07 0.045],...
'String',num2str(params.(paramNames{i}), '%.4f'),...
'Callback',@(src,~) applyParams());
% Description
uicontrol('Style','text','Units','normalized',...
'Position',[0.68 yPos - 0.04 0.35 0.03],...
'String',paramDescs{i},...
'HorizontalAlignment','left',...
'FontSize',8,'ForegroundColor',[0.4 0.4 0.4],...
'BackgroundColor','w');
end
%% --- Apply button ---
uicontrol('Style','pushbutton','Units','normalized',...
'Position',[0.70 0.35 0.25 0.06],...
'String','Re-fit All Curves',...
'FontSize',14,'FontWeight','bold',...
'BackgroundColor',[0.2 0.6 1],...
'ForegroundColor','w',...
'Callback',@(~,~) refitAll());
%% --- Fit info text boxes ---
infoLabels = {'Fit validity:', 'Peak positions (rad):', 'Amplitudes:'};
hInfoText = gobjects(numel(infoLabels),1);
for i = 1:numel(infoLabels)
yText = 0.22 - 0.07*(i-1);
uicontrol('Style','text','Units','normalized',...
'Position',[0.68 yText 0.25 0.05],...
'String',infoLabels{i},...
'FontSize',10,'FontWeight','bold',...
'HorizontalAlignment','left',...
'BackgroundColor','w');
hInfoText(i) = uicontrol('Style','text','Units','normalized',...
'Position',[0.88 yText 0.1 0.05],...
'String','-','FontSize',10,...
'HorizontalAlignment','left',...
'BackgroundColor','w');
end
%% --- Compute initial fits ---
[fitResults, rawData] = Analyzer.fitTwoGaussianCurvesToAngularSpectralDistribution(...
spectral_analysis_results.S_theta_norm_all,...
spectral_analysis_results.theta_vals,...
'MaxTheta', params.MaxTheta,...
'ResidualThreshold', params.ResidualThreshold,...
'PositionThreshold', params.PositionThreshold,...
'AmplitudeThreshold', params.AmplitudeThreshold);
%% --- Initial plot ---
updatePlot();
%% --- Nested functions ---
function applyParams()
% Update parameters from GUI fields
for j = 1:nParams
val = str2double(hEdit(j).String);
if ~isnan(val)
params.(paramNames{j}) = val;
end
end
refitAll();
end
function refitAll()
% Recompute all fits
drawnow;
[fitResults, rawData] = Analyzer.fitTwoGaussianCurvesToAngularSpectralDistribution(...
spectral_analysis_results.S_theta_norm_all,...
spectral_analysis_results.theta_vals,...
'MaxTheta', params.MaxTheta,...
'ResidualThreshold', params.ResidualThreshold,...
'PositionThreshold', params.PositionThreshold,...
'AmplitudeThreshold', params.AmplitudeThreshold);
updatePlot();
end
function updatePlot()
idx = round(get(hSlider,'Value'));
currentIdx = idx;
cla(hAx);
hold(hAx,'on');
raw = rawData(idx);
plot(hAx, raw.theta, raw.x, 'k.-', 'LineWidth', 1, 'DisplayName', 'Raw Data');
if idx <= numel(fitResults)
fit = fitResults(idx);
if isfield(fit,'isValid') && ~isempty(fit.isValid) && fit.isValid
plot(hAx, fit.thetaFine, fit.yFit, 'r-', 'LineWidth', 1.5, 'DisplayName', 'Two-Gaussian Fit');
% Extract parameters from pFit vector if available
if isfield(fit,'pFit') && numel(fit.pFit) >= 6
A1 = fit.pFit(1); mu1 = fit.pFit(2);
A2 = fit.pFit(4); mu2 = fit.pFit(5);
hInfoText(1).String = 'Valid';
hInfoText(1).ForegroundColor = [0 0.5 0];
hInfoText(2).String = sprintf('[%.3f, %.3f]', mu1, mu2);
hInfoText(3).String = sprintf('[%.2f, %.2f]', A1, A2);
else
hInfoText(1).String = 'Valid';
hInfoText(1).ForegroundColor = [0 0.5 0];
hInfoText(2).String = '-';
hInfoText(3).String = '-';
end
else
hInfoText(1).String = 'Invalid';
hInfoText(1).ForegroundColor = [0.7 0 0];
hInfoText(2).String = '-';
hInfoText(3).String = '-';
end
end
title(hAx,sprintf('Curve %d / %d', idx, Ncurves),'FontSize',16);
legend(hAx,'Location','northeast','FontSize',14);
hold(hAx,'off');
drawnow;
end
function keyPressCallback(event)
switch event.Key
case 'rightarrow'
if currentIdx < Ncurves
currentIdx = currentIdx + 1;
set(hSlider,'Value',currentIdx);
updatePlot();
end
case 'leftarrow'
if currentIdx > 1
currentIdx = currentIdx - 1;
set(hSlider,'Value',currentIdx);
updatePlot();
end
end
end
end

View File

@ -0,0 +1,219 @@
function runInteractiveRSDTwoGaussianFitGUI(spectral_analysis_results)
%% runInteractiveRSDTwoGaussianFitGUI
% Author: Karthik
% Date: 2025-10-16
% Version: 1.0
%
% Description:
% Interactive viewer for raw radial spectral distributions.
% Lets user browse through individual curves and refit two-Gaussian models
% live as threshold parameters are adjusted.
%
% Controls:
% - Slider or / keys to browse curves
% - Editable boxes for thresholds (Residual, Position, Amplitude, KRhoRange, AmplitudeRange)
% - "Re-fit Current Curve" button triggers recomputation
%
% Dependencies:
% Requires Analyzer.fitTwoGaussianCurvesToRadialSpectralDistribution.m
%% --- Initialization ---
rawCurves.x = spectral_analysis_results.S_k_all;
rawCurves.k = spectral_analysis_results.k_rho_vals;
% Handle input organization
if iscell(rawCurves.x)
Ncurves = numel(rawCurves.x);
else
Ncurves = size(rawCurves.x, 1);
tmp = arrayfun(@(i) struct('x', rawCurves.x(i,:), 'k', rawCurves.k(:)'), 1:Ncurves);
rawCurves = tmp(:);
end
% Default fit parameters
params.KRhoRange = [0, 3];
params.AmplitudeRange = [0, 0.5];
params.ResidualThreshold = 0.15;
params.PositionThreshold = 0.5;
params.AmplitudeThreshold = 0.015;
currentIdx = 1;
%% --- Create figure ---
hFig = findobj('Type','figure','Tag','InteractiveTwoGaussianRSD');
if isempty(hFig)
hFig = figure('Name','Radial Spectra Fit Viewer',...
'NumberTitle','off',...
'Position',[100 100 1250 800],...
'Color','w',...
'KeyPressFcn',@keyPressCallback,...
'Tag','InteractiveTwoGaussianRSD');
else
figure(hFig); clf(hFig);
end
%% --- Axes for plot ---
hAx = axes('Parent',hFig,'Position',[0.08 0.1 0.55 0.8]);
grid(hAx,'on'); box(hAx,'on');
xlabel(hAx,'k_\rho','FontSize',12);
ylabel(hAx,'Normalized amplitude','FontSize',12);
%% --- Slider for curve index ---
hSlider = uicontrol('Style','slider','Min',1,'Max',Ncurves,'Value',1,...
'SliderStep',[1/(Ncurves-1), 10/(Ncurves-1)],...
'Units','normalized','Position',[0.1 0.02 0.5 0.03],...
'Callback',@(~,~) updatePlot());
%% --- Parameter definitions ---
paramNames = {'KRhoRange','AmplitudeRange','ResidualThreshold','PositionThreshold','AmplitudeThreshold'};
paramLabels = {'KRho range [min,max]','Amplitude range [min,max]','Residual Threshold','Position Threshold','Amplitude Threshold'};
paramDescs = {'Truncate k_\rho range for fitting',...
'Truncate amplitudes below/above values',...
'Maximum mean residual for valid fits',...
'Minimum separation between peaks',...
'Minimum amplitude ratio threshold'};
nParams = numel(paramNames);
hEdit = gobjects(nParams,1);
baseY = 0.88;
%% --- Create parameter controls ---
for i = 1:nParams
yPos = baseY - 0.12*(i-1);
% Label
uicontrol('Style','text','Units','normalized',...
'Position',[0.68 yPos 0.25 0.04],...
'String',paramLabels{i},...
'HorizontalAlignment','left',...
'FontSize',10,'FontWeight','bold',...
'BackgroundColor','w');
% Edit box
hEdit(i) = uicontrol('Style','edit','Units','normalized',...
'Position',[0.9 yPos 0.07 0.045],...
'String',num2str(params.(paramNames{i}), '%.4f'),...
'Callback',@(src,~) applyParams());
% Description
uicontrol('Style','text','Units','normalized',...
'Position',[0.68 yPos - 0.04 0.35 0.03],...
'String',paramDescs{i},...
'HorizontalAlignment','left','FontSize',8,'ForegroundColor',[0.4 0.4 0.4],...
'BackgroundColor','w');
end
%% --- Re-fit button ---
uicontrol('Style','pushbutton','Units','normalized',...
'Position',[0.700 0.295 0.25 0.06],...
'String','Re-fit All Curves',...
'FontSize',14,'FontWeight','bold',...
'BackgroundColor',[0.2 0.6 1],...
'ForegroundColor','w',...
'Callback',@(~,~) refitAll());
%% --- Fit info text boxes ---
infoLabels = {'Fit validity:','Peak positions:','Amplitudes:'};
hInfoText = gobjects(numel(infoLabels),1);
for i = 1:numel(infoLabels)
yText = 0.22 - 0.07*(i-1);
uicontrol('Style','text','Units','normalized',...
'Position',[0.68 yText 0.25 0.05],...
'String',infoLabels{i},...
'FontSize',10,'FontWeight','bold',...
'HorizontalAlignment','left',...
'BackgroundColor','w');
hInfoText(i) = uicontrol('Style','text','Units','normalized',...
'Position',[0.88 yText 0.1 0.05],...
'String','-','FontSize',10,...
'HorizontalAlignment','left',...
'BackgroundColor','w');
end
%% --- Compute initial fits ---
[fitResults, rawData] = Analyzer.fitTwoGaussianCurvesToRadialSpectralDistribution(...
spectral_analysis_results.S_k_all,...
spectral_analysis_results.k_rho_vals,...
'KRhoRange', params.KRhoRange,...
'AmplitudeRange', params.AmplitudeRange,...
'ResidualThreshold', params.ResidualThreshold,...
'PositionThreshold', params.PositionThreshold,...
'AmplitudeThreshold', params.AmplitudeThreshold);
%% --- Initial plot ---
updatePlot();
%% --- Nested functions ---
function applyParams()
% Update parameters from GUI fields
for j = 1:nParams
val = str2double(hEdit(j).String);
if ~isnan(val)
params.(paramNames{j}) = val;
end
end
refitAll();
end
function refitAll()
% Recompute all fits for the entire radial dataset
drawnow;
[fitResults, rawData] = Analyzer.fitTwoGaussianCurvesToRadialSpectralDistribution(...
spectral_analysis_results.S_k_all, ...
spectral_analysis_results.k_rho_vals, ...
'KRhoRange', params.KRhoRange, ...
'AmplitudeRange', params.AmplitudeRange, ...
'ResidualThreshold', params.ResidualThreshold, ...
'PositionThreshold', params.PositionThreshold, ...
'AmplitudeThreshold', params.AmplitudeThreshold);
updatePlot();
end
function updatePlot()
% Display raw curve and two-Gaussian fit
idx = round(get(hSlider,'Value'));
currentIdx = idx;
cla(hAx); hold(hAx,'on');
raw = rawData(idx);
plot(hAx, raw.k, raw.x, 'k.-','LineWidth',1,'DisplayName','Raw Data');
fit = fitResults(idx);
if isfield(fit,'isValid') && ~isempty(fit.isValid) && fit.isValid && ...
isfield(fit,'kFine') && isfield(fit,'yFit') && ~isempty(fit.kFine)
plot(hAx, fit.kFine, fit.yFit, 'r-','LineWidth',1.5,'DisplayName','Two-Gaussian Fit');
if isfield(fit,'pFit') && numel(fit.pFit)>=6
A1=fit.pFit(1); mu1=fit.pFit(2);
A2=fit.pFit(4); mu2=fit.pFit(5);
hInfoText(1).String='Valid'; hInfoText(1).ForegroundColor=[0 0.5 0];
hInfoText(2).String=sprintf('[%.3f, %.3f]',mu1,mu2);
hInfoText(3).String=sprintf('[%.3f, %.3f]',A1,A2);
else
hInfoText(1).String='Valid'; hInfoText(1).ForegroundColor=[0 0.5 0];
hInfoText(2).String='-'; hInfoText(3).String='-';
end
else
hInfoText(1).String='Invalid'; hInfoText(1).ForegroundColor=[0.7 0 0];
hInfoText(2).String='-'; hInfoText(3).String='-';
end
xlabel(hAx,'k_\rho'); ylabel(hAx,'Normalized amplitude');
title(hAx,sprintf('Curve %d / %d',idx,Ncurves),'FontSize',16);
legend(hAx,'Location','northeast','FontSize',14);
hold(hAx,'off'); drawnow;
end
function keyPressCallback(event)
% Navigate curves via arrow keys
switch event.Key
case 'rightarrow'
if currentIdx<Ncurves, currentIdx=currentIdx+1; set(hSlider,'Value',currentIdx); updatePlot(); end
case 'leftarrow'
if currentIdx>1, currentIdx=currentIdx-1; set(hSlider,'Value',currentIdx); updatePlot(); end
end
end
end

View File

@ -167,71 +167,8 @@ Plotter.plotSpectralDistributionCumulants(results, ...
'PositionThreshold', pi/15, ...
'AmplitudeThreshold', 0.15);
%{
% --- Function call ---
plotTwoGaussianFitsOnRaw(fitResults, rawCurves, 8, 12); % 8×12 subplots per page
% --- Function definition ---
function plotTwoGaussianFitsOnRaw(fitResults, rawCurves, nRows, nCols)
% plotTwoGaussianFitsOnRaw - Plots raw curves and overlays valid two-Gaussian fits.
%
% Inputs:
% fitResults - struct array from fitTwoGaussianCurvesToAngularSpectralDistribution (may contain fits)
% rawCurves - struct array with fields:
% .x - raw curve
% .theta - corresponding theta values
% nRows - number of subplot rows per page (default: 4)
% nCols - number of subplot columns per page (default: 6)
if nargin < 3, nRows = 4; end
if nargin < 4, nCols = 6; end
Ncurves = numel(rawCurves);
plotsPerPage = nRows * nCols;
pageNum = 1;
for k = 1:Ncurves
% --- New figure/page if needed ---
if mod(k-1, plotsPerPage) == 0
figure('Name', sprintf('Curves Page %d', pageNum), ...
'NumberTitle', 'off', 'Color', 'w');
pageNum = pageNum + 1;
end
% --- Select subplot ---
subplot(nRows, nCols, mod(k-1, plotsPerPage)+1);
hold on; grid on; box on;
% --- Plot raw curve ---
xRaw = rawCurves(k).x;
thetaRaw = rawCurves(k).theta;
if ~isempty(xRaw) && ~isempty(thetaRaw) && all(isfinite(xRaw))
plot(thetaRaw, xRaw, 'k.-', 'LineWidth', 1, 'DisplayName', 'Raw data');
end
% --- Overlay fit if valid ---
if k <= numel(fitResults)
fit = fitResults(k);
if isfield(fit, 'isValid') && fit.isValid ...
&& ~isempty(fit.yFit) && ~isempty(fit.thetaFine)
plot(fit.thetaFine, fit.yFit, 'r-', 'LineWidth', 1.2, 'DisplayName', 'Two-Gaussian fit');
end
end
% --- Formatting ---
xlabel('\theta (rad)');
ylabel('Normalized amplitude');
title(sprintf('Curve %d', k), 'FontSize', 10);
% --- Legend once per page ---
if mod(k-1, plotsPerPage) == 0
legend('Location', 'best', 'FontSize', 8);
end
hold off;
end
end
%}
%% ------------------ Interactive Fit Viewer ------------------
Analyzer.runInteractiveASDTwoGaussianFitGUI(spectral_analysis_results);
%% ------------------ 5. Plot fit parameters - amplitude ------------------
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...

View File

@ -121,76 +121,10 @@ Plotter.plotSpectralCurves( ...
'ResidualThreshold', 0.15, ... % maximum allowed residual
'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
%%
%{
% --- Function call ---
plotTwoGaussianFitsOnRaw(fitResults, rawCurves, 8, 12); % 8×12 subplots per page
% --- Function definition ---
function plotTwoGaussianFitsOnRaw(fitResults, rawCurves, nRows, nCols)
%% plotTwoGaussianFitsOnRaw
% Plots raw radial spectral curves with their two-Gaussian fits.
%
% Inputs:
% fitResults - struct array from fitTwoGaussianCurvesToRadialSpectralDistribution
% rawCurves - struct array with fields:
% .x - raw normalized amplitudes
% .k - corresponding k_rho values
% nRows - number of subplot rows per page (default: 8)
% nCols - number of subplot columns per page (default: 12)
%% ------------------ Interactive Fit Viewer ------------------
Analyzer.runInteractiveRSDTwoGaussianFitGUI(spectral_analysis_results);
if nargin < 3, nRows = 8; end
if nargin < 4, nCols = 12; end
Ncurves = numel(rawCurves);
plotsPerPage = nRows * nCols;
pageNum = 1;
for k = 1:Ncurves
% --- Create new figure page if needed ---
if mod(k-1, plotsPerPage) == 0
figure('Name', sprintf('Radial Spectra Page %d', pageNum), ...
'NumberTitle', 'off', 'Color', 'w', ...
'Position', [50 50 1600 900]);
pageNum = pageNum + 1;
end
% --- Subplot selection ---
subplot(nRows, nCols, mod(k-1, plotsPerPage) + 1);
hold on; grid on; box on;
% --- Plot raw curve ---
if isfield(rawCurves, 'x') && isfield(rawCurves, 'k') && ...
~isempty(rawCurves(k).x) && all(isfinite(rawCurves(k).x))
plot(rawCurves(k).k, rawCurves(k).x, 'k.-', ...
'LineWidth', 1, 'DisplayName', 'Raw data');
end
% --- Overlay fit if valid ---
if k <= numel(fitResults)
fit = fitResults(k);
if isfield(fit, 'isValid') && fit.isValid && ...
isfield(fit, 'kFine') && isfield(fit, 'yFit') && ...
~isempty(fit.kFine) && all(isfinite(fit.yFit))
plot(fit.kFine, fit.yFit, 'r-', ...
'LineWidth', 1.2, 'DisplayName', 'Two-Gaussian fit');
end
end
% --- Labels and title ---
xlabel('k_\rho', 'FontSize', 10);
ylabel('Normalized amplitude', 'FontSize', 10);
title(sprintf('Curve %d', k), 'FontSize', 9, 'Interpreter', 'none');
% --- Legend on first subplot of each page ---
if mod(k-1, plotsPerPage) == 0
legend('Location', 'best', 'FontSize', 8);
end
hold off;
end
end
%}
%% ------------------ 3. Plot fit parameters - amplitude ------------------
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
'Title', options.titleString, ...

View File

@ -154,7 +154,7 @@ Plotter.plotSpectralDistributionCumulants(results, ...
'FontName', options.font, ...
'FontSize', 14, ...
'FigNum', 3, ...
'SkipSaveFigures', false, ...
'SkipSaveFigures', options.skipSaveFigures, ...
'SaveFileName', 'SpectralCumulants.fig', ...
'SaveDirectory', options.saveDirectory);
@ -167,71 +167,8 @@ Plotter.plotSpectralDistributionCumulants(results, ...
'PositionThreshold', pi/15, ...
'AmplitudeThreshold', 0.15);
%{
% --- Function call ---
plotTwoGaussianFitsOnRaw(fitResults, rawCurves, 8, 12); % 8×12 subplots per page
% --- Function definition ---
function plotTwoGaussianFitsOnRaw(fitResults, rawCurves, nRows, nCols)
% plotTwoGaussianFitsOnRaw - Plots raw curves and overlays valid two-Gaussian fits.
%
% Inputs:
% fitResults - struct array from fitTwoGaussianCurvesToAngularSpectralDistribution (may contain fits)
% rawCurves - struct array with fields:
% .x - raw curve
% .theta - corresponding theta values
% nRows - number of subplot rows per page (default: 4)
% nCols - number of subplot columns per page (default: 6)
if nargin < 3, nRows = 4; end
if nargin < 4, nCols = 6; end
Ncurves = numel(rawCurves);
plotsPerPage = nRows * nCols;
pageNum = 1;
for k = 1:Ncurves
% --- New figure/page if needed ---
if mod(k-1, plotsPerPage) == 0
figure('Name', sprintf('Curves Page %d', pageNum), ...
'NumberTitle', 'off', 'Color', 'w');
pageNum = pageNum + 1;
end
% --- Select subplot ---
subplot(nRows, nCols, mod(k-1, plotsPerPage)+1);
hold on; grid on; box on;
% --- Plot raw curve ---
xRaw = rawCurves(k).x;
thetaRaw = rawCurves(k).theta;
if ~isempty(xRaw) && ~isempty(thetaRaw) && all(isfinite(xRaw))
plot(thetaRaw, xRaw, 'k.-', 'LineWidth', 1, 'DisplayName', 'Raw data');
end
% --- Overlay fit if valid ---
if k <= numel(fitResults)
fit = fitResults(k);
if isfield(fit, 'isValid') && fit.isValid ...
&& ~isempty(fit.yFit) && ~isempty(fit.thetaFine)
plot(fit.thetaFine, fit.yFit, 'r-', 'LineWidth', 1.2, 'DisplayName', 'Two-Gaussian fit');
end
end
% --- Formatting ---
xlabel('\theta (rad)');
ylabel('Normalized amplitude');
title(sprintf('Curve %d', k), 'FontSize', 10);
% --- Legend once per page ---
if mod(k-1, plotsPerPage) == 0
legend('Location', 'best', 'FontSize', 8);
end
hold off;
end
end
%}
%% ------------------ Interactive Fit Viewer ------------------
Analyzer.runInteractiveASDTwoGaussianFitGUI(spectral_analysis_results);
%% ------------------ 5. Plot fit parameters - amplitude ------------------
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...

View File

@ -121,76 +121,10 @@ Plotter.plotSpectralCurves( ...
'ResidualThreshold', 0.15, ... % maximum allowed residual
'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
%%
%{
% --- Function call ---
plotTwoGaussianFitsOnRaw(fitResults, rawCurves, 8, 12); % 8×12 subplots per page
% --- Function definition ---
function plotTwoGaussianFitsOnRaw(fitResults, rawCurves, nRows, nCols)
%% plotTwoGaussianFitsOnRaw
% Plots raw radial spectral curves with their two-Gaussian fits.
%
% Inputs:
% fitResults - struct array from fitTwoGaussianCurvesToRadialSpectralDistribution
% rawCurves - struct array with fields:
% .x - raw normalized amplitudes
% .k - corresponding k_rho values
% nRows - number of subplot rows per page (default: 8)
% nCols - number of subplot columns per page (default: 12)
%% ------------------ Interactive Fit Viewer ------------------
Analyzer.runInteractiveRSDTwoGaussianFitGUI(spectral_analysis_results);
if nargin < 3, nRows = 8; end
if nargin < 4, nCols = 12; end
Ncurves = numel(rawCurves);
plotsPerPage = nRows * nCols;
pageNum = 1;
for k = 1:Ncurves
% --- Create new figure page if needed ---
if mod(k-1, plotsPerPage) == 0
figure('Name', sprintf('Radial Spectra Page %d', pageNum), ...
'NumberTitle', 'off', 'Color', 'w', ...
'Position', [50 50 1600 900]);
pageNum = pageNum + 1;
end
% --- Subplot selection ---
subplot(nRows, nCols, mod(k-1, plotsPerPage) + 1);
hold on; grid on; box on;
% --- Plot raw curve ---
if isfield(rawCurves, 'x') && isfield(rawCurves, 'k') && ...
~isempty(rawCurves(k).x) && all(isfinite(rawCurves(k).x))
plot(rawCurves(k).k, rawCurves(k).x, 'k.-', ...
'LineWidth', 1, 'DisplayName', 'Raw data');
end
% --- Overlay fit if valid ---
if k <= numel(fitResults)
fit = fitResults(k);
if isfield(fit, 'isValid') && fit.isValid && ...
isfield(fit, 'kFine') && isfield(fit, 'yFit') && ...
~isempty(fit.kFine) && all(isfinite(fit.yFit))
plot(fit.kFine, fit.yFit, 'r-', ...
'LineWidth', 1.2, 'DisplayName', 'Two-Gaussian fit');
end
end
% --- Labels and title ---
xlabel('k_\rho', 'FontSize', 10);
ylabel('Normalized amplitude', 'FontSize', 10);
title(sprintf('Curve %d', k), 'FontSize', 9, 'Interpreter', 'none');
% --- Legend on first subplot of each page ---
if mod(k-1, plotsPerPage) == 0
legend('Location', 'best', 'FontSize', 8);
end
hold off;
end
end
%}
%% ------------------ 3. Plot fit parameters - amplitude ------------------
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
'Title', options.titleString, ...
@ -207,7 +141,7 @@ Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
'NormalizeHistogram', true, ...
'Colormap', @Colormaps.coolwarm, ...
'XLim', [min(scan_reference_values), max(scan_reference_values)], ...
'YLim', [0, 0.06]);
'YLim', [0, 0.025]);
%% ------------------ 4. Plot fit parameters - position ------------------
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'mu2', ...

View File

@ -167,71 +167,8 @@ Plotter.plotSpectralDistributionCumulants(results, ...
'PositionThreshold', pi/15, ...
'AmplitudeThreshold', 0.15);
%{
% --- Function call ---
plotTwoGaussianFitsOnRaw(fitResults, rawCurves, 8, 12); % 8×12 subplots per page
% --- Function definition ---
function plotTwoGaussianFitsOnRaw(fitResults, rawCurves, nRows, nCols)
% plotTwoGaussianFitsOnRaw - Plots raw curves and overlays valid two-Gaussian fits.
%
% Inputs:
% fitResults - struct array from fitTwoGaussianCurvesToAngularSpectralDistribution (may contain fits)
% rawCurves - struct array with fields:
% .x - raw curve
% .theta - corresponding theta values
% nRows - number of subplot rows per page (default: 4)
% nCols - number of subplot columns per page (default: 6)
if nargin < 3, nRows = 4; end
if nargin < 4, nCols = 6; end
Ncurves = numel(rawCurves);
plotsPerPage = nRows * nCols;
pageNum = 1;
for k = 1:Ncurves
% --- New figure/page if needed ---
if mod(k-1, plotsPerPage) == 0
figure('Name', sprintf('Curves Page %d', pageNum), ...
'NumberTitle', 'off', 'Color', 'w');
pageNum = pageNum + 1;
end
% --- Select subplot ---
subplot(nRows, nCols, mod(k-1, plotsPerPage)+1);
hold on; grid on; box on;
% --- Plot raw curve ---
xRaw = rawCurves(k).x;
thetaRaw = rawCurves(k).theta;
if ~isempty(xRaw) && ~isempty(thetaRaw) && all(isfinite(xRaw))
plot(thetaRaw, xRaw, 'k.-', 'LineWidth', 1, 'DisplayName', 'Raw data');
end
% --- Overlay fit if valid ---
if k <= numel(fitResults)
fit = fitResults(k);
if isfield(fit, 'isValid') && fit.isValid ...
&& ~isempty(fit.yFit) && ~isempty(fit.thetaFine)
plot(fit.thetaFine, fit.yFit, 'r-', 'LineWidth', 1.2, 'DisplayName', 'Two-Gaussian fit');
end
end
% --- Formatting ---
xlabel('\theta (rad)');
ylabel('Normalized amplitude');
title(sprintf('Curve %d', k), 'FontSize', 10);
% --- Legend once per page ---
if mod(k-1, plotsPerPage) == 0
legend('Location', 'best', 'FontSize', 8);
end
hold off;
end
end
%}
%% ------------------ Interactive Fit Viewer ------------------
Analyzer.runInteractiveASDTwoGaussianFitGUI(spectral_analysis_results);
%% ------------------ 5. Plot fit parameters - amplitude ------------------
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...

View File

@ -121,76 +121,10 @@ Plotter.plotSpectralCurves( ...
'ResidualThreshold', 0.15, ... % maximum allowed residual
'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
%%
%{
% --- Function call ---
plotTwoGaussianFitsOnRaw(fitResults, rawCurves, 8, 12); % 8×12 subplots per page
% --- Function definition ---
function plotTwoGaussianFitsOnRaw(fitResults, rawCurves, nRows, nCols)
%% plotTwoGaussianFitsOnRaw
% Plots raw radial spectral curves with their two-Gaussian fits.
%
% Inputs:
% fitResults - struct array from fitTwoGaussianCurvesToRadialSpectralDistribution
% rawCurves - struct array with fields:
% .x - raw normalized amplitudes
% .k - corresponding k_rho values
% nRows - number of subplot rows per page (default: 8)
% nCols - number of subplot columns per page (default: 12)
%% ------------------ Interactive Fit Viewer ------------------
Analyzer.runInteractiveRSDTwoGaussianFitGUI(spectral_analysis_results);
if nargin < 3, nRows = 8; end
if nargin < 4, nCols = 12; end
Ncurves = numel(rawCurves);
plotsPerPage = nRows * nCols;
pageNum = 1;
for k = 1:Ncurves
% --- Create new figure page if needed ---
if mod(k-1, plotsPerPage) == 0
figure('Name', sprintf('Radial Spectra Page %d', pageNum), ...
'NumberTitle', 'off', 'Color', 'w', ...
'Position', [50 50 1600 900]);
pageNum = pageNum + 1;
end
% --- Subplot selection ---
subplot(nRows, nCols, mod(k-1, plotsPerPage) + 1);
hold on; grid on; box on;
% --- Plot raw curve ---
if isfield(rawCurves, 'x') && isfield(rawCurves, 'k') && ...
~isempty(rawCurves(k).x) && all(isfinite(rawCurves(k).x))
plot(rawCurves(k).k, rawCurves(k).x, 'k.-', ...
'LineWidth', 1, 'DisplayName', 'Raw data');
end
% --- Overlay fit if valid ---
if k <= numel(fitResults)
fit = fitResults(k);
if isfield(fit, 'isValid') && fit.isValid && ...
isfield(fit, 'kFine') && isfield(fit, 'yFit') && ...
~isempty(fit.kFine) && all(isfinite(fit.yFit))
plot(fit.kFine, fit.yFit, 'r-', ...
'LineWidth', 1.2, 'DisplayName', 'Two-Gaussian fit');
end
end
% --- Labels and title ---
xlabel('k_\rho', 'FontSize', 10);
ylabel('Normalized amplitude', 'FontSize', 10);
title(sprintf('Curve %d', k), 'FontSize', 9, 'Interpreter', 'none');
% --- Legend on first subplot of each page ---
if mod(k-1, plotsPerPage) == 0
legend('Location', 'best', 'FontSize', 8);
end
hold off;
end
end
%}
%% ------------------ 3. Plot fit parameters - amplitude ------------------
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
'Title', options.titleString, ...

View File

@ -167,71 +167,8 @@ Plotter.plotSpectralDistributionCumulants(results, ...
'PositionThreshold', pi/15, ...
'AmplitudeThreshold', 0.15);
%{
% --- Function call ---
plotTwoGaussianFitsOnRaw(fitResults, rawCurves, 8, 12); % 8×12 subplots per page
% --- Function definition ---
function plotTwoGaussianFitsOnRaw(fitResults, rawCurves, nRows, nCols)
% plotTwoGaussianFitsOnRaw - Plots raw curves and overlays valid two-Gaussian fits.
%
% Inputs:
% fitResults - struct array from fitTwoGaussianCurvesToAngularSpectralDistribution (may contain fits)
% rawCurves - struct array with fields:
% .x - raw curve
% .theta - corresponding theta values
% nRows - number of subplot rows per page (default: 4)
% nCols - number of subplot columns per page (default: 6)
if nargin < 3, nRows = 4; end
if nargin < 4, nCols = 6; end
Ncurves = numel(rawCurves);
plotsPerPage = nRows * nCols;
pageNum = 1;
for k = 1:Ncurves
% --- New figure/page if needed ---
if mod(k-1, plotsPerPage) == 0
figure('Name', sprintf('Curves Page %d', pageNum), ...
'NumberTitle', 'off', 'Color', 'w');
pageNum = pageNum + 1;
end
% --- Select subplot ---
subplot(nRows, nCols, mod(k-1, plotsPerPage)+1);
hold on; grid on; box on;
% --- Plot raw curve ---
xRaw = rawCurves(k).x;
thetaRaw = rawCurves(k).theta;
if ~isempty(xRaw) && ~isempty(thetaRaw) && all(isfinite(xRaw))
plot(thetaRaw, xRaw, 'k.-', 'LineWidth', 1, 'DisplayName', 'Raw data');
end
% --- Overlay fit if valid ---
if k <= numel(fitResults)
fit = fitResults(k);
if isfield(fit, 'isValid') && fit.isValid ...
&& ~isempty(fit.yFit) && ~isempty(fit.thetaFine)
plot(fit.thetaFine, fit.yFit, 'r-', 'LineWidth', 1.2, 'DisplayName', 'Two-Gaussian fit');
end
end
% --- Formatting ---
xlabel('\theta (rad)');
ylabel('Normalized amplitude');
title(sprintf('Curve %d', k), 'FontSize', 10);
% --- Legend once per page ---
if mod(k-1, plotsPerPage) == 0
legend('Location', 'best', 'FontSize', 8);
end
hold off;
end
end
%}
%% ------------------ Interactive Fit Viewer ------------------
Analyzer.runInteractiveASDTwoGaussianFitGUI(spectral_analysis_results);
%% ------------------ 5. Plot fit parameters - amplitude ------------------
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...

View File

@ -121,76 +121,10 @@ Plotter.plotSpectralCurves( ...
'ResidualThreshold', 0.15, ... % maximum allowed residual
'PositionThreshold', 0.5, ... % minimum separation between peaks
'AmplitudeThreshold', 0.015); % minimum secondary peak fraction
%%
%{
% --- Function call ---
plotTwoGaussianFitsOnRaw(fitResults, rawCurves, 8, 12); % 8×12 subplots per page
% --- Function definition ---
function plotTwoGaussianFitsOnRaw(fitResults, rawCurves, nRows, nCols)
%% plotTwoGaussianFitsOnRaw
% Plots raw radial spectral curves with their two-Gaussian fits.
%
% Inputs:
% fitResults - struct array from fitTwoGaussianCurvesToRadialSpectralDistribution
% rawCurves - struct array with fields:
% .x - raw normalized amplitudes
% .k - corresponding k_rho values
% nRows - number of subplot rows per page (default: 8)
% nCols - number of subplot columns per page (default: 12)
%% ------------------ Interactive Fit Viewer ------------------
Analyzer.runInteractiveRSDTwoGaussianFitGUI(spectral_analysis_results);
if nargin < 3, nRows = 8; end
if nargin < 4, nCols = 12; end
Ncurves = numel(rawCurves);
plotsPerPage = nRows * nCols;
pageNum = 1;
for k = 1:Ncurves
% --- Create new figure page if needed ---
if mod(k-1, plotsPerPage) == 0
figure('Name', sprintf('Radial Spectra Page %d', pageNum), ...
'NumberTitle', 'off', 'Color', 'w', ...
'Position', [50 50 1600 900]);
pageNum = pageNum + 1;
end
% --- Subplot selection ---
subplot(nRows, nCols, mod(k-1, plotsPerPage) + 1);
hold on; grid on; box on;
% --- Plot raw curve ---
if isfield(rawCurves, 'x') && isfield(rawCurves, 'k') && ...
~isempty(rawCurves(k).x) && all(isfinite(rawCurves(k).x))
plot(rawCurves(k).k, rawCurves(k).x, 'k.-', ...
'LineWidth', 1, 'DisplayName', 'Raw data');
end
% --- Overlay fit if valid ---
if k <= numel(fitResults)
fit = fitResults(k);
if isfield(fit, 'isValid') && fit.isValid && ...
isfield(fit, 'kFine') && isfield(fit, 'yFit') && ...
~isempty(fit.kFine) && all(isfinite(fit.yFit))
plot(fit.kFine, fit.yFit, 'r-', ...
'LineWidth', 1.2, 'DisplayName', 'Two-Gaussian fit');
end
end
% --- Labels and title ---
xlabel('k_\rho', 'FontSize', 10);
ylabel('Normalized amplitude', 'FontSize', 10);
title(sprintf('Curve %d', k), 'FontSize', 9, 'Interpreter', 'none');
% --- Legend on first subplot of each page ---
if mod(k-1, plotsPerPage) == 0
legend('Location', 'best', 'FontSize', 8);
end
hold off;
end
end
%}
%% ------------------ 3. Plot fit parameters - amplitude ------------------
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
'Title', options.titleString, ...