function plotSpectralDistributionCumulants(results, varargin) %% plotSpectralCumulants % Author: Karthik % Date: 2025-10-02 % Version: 1.0 % % Description: % Plot first four cumulants of recentered spectral curves vs scan parameter. % % Inputs: % results_struct - struct returned by plotSpectralCurvesRecentered % (fields: curves, x_values, scan_parameter_values) % % Notes: % Computes cumulants across repetitions at selected theta values % and plots them in 4 tiled subplots. % --- Parse name-value pairs --- p = inputParser; addParameter(p, 'Title', 'Spectral Cumulants', @(x) ischar(x) || isstring(x)); addParameter(p, 'XLabel', 'Scan Parameter', @(x) ischar(x) || isstring(x)); addParameter(p, 'FontName', 'Arial', @ischar); addParameter(p, 'FontSize', 14, @isnumeric); addParameter(p, 'FigNum', [], @(x) isempty(x) || (isnumeric(x) && isscalar(x))); addParameter(p, 'SkipSaveFigures', false, @islogical); addParameter(p, 'SaveFileName', 'SpectralCumulants.fig', @ischar); addParameter(p, 'SaveDirectory', pwd, @ischar); addParameter(p, 'MaxOrder', 4, @isnumeric); parse(p, varargin{:}); opts = p.Results; % --- Setup --- N_params = numel(results.curves); xvals = results.scan_reference_values; thetaVals = results.x_values * pi; % --- Select specific theta indices (like in g2 case) --- desiredTheta = [pi/12 pi/6 pi/3]; [~, thIdx] = arrayfun(@(t) min(abs(thetaVals - t)), desiredTheta); thetaLabels = {'\pi/12','\pi/6','\pi/3'}; % --- Compute cumulants: [theta × scan × cumulantOrder] --- kappa = zeros(numel(thIdx), N_params, opts.MaxOrder); for i = 1:N_params for t = 1:numel(thIdx) reps_values = results.curves{i}(:, thIdx(t)); kappa(t,i,:) = Calculator.computeCumulants(reps_values, opts.MaxOrder); end end % --- Colormap --- fullCmap = Colormaps.coolwarm(256); Ntheta = numel(thIdx); blueSide = fullCmap(1:100,:); % avoid white redSide = fullCmap(157:end,:); trimmedCmap = [blueSide; redSide]; indices = round(linspace(1,size(trimmedCmap,1),Ntheta)); cmap = trimmedCmap(indices,:); % --- Create figure --- if isempty(opts.FigNum), fig = figure; else, fig = figure(opts.FigNum); end clf(fig); set(fig,'Color','w','Position',[100 100 950 750]); t = tiledlayout(2,2,'TileSpacing','Compact','Padding','Compact'); title(t, opts.Title, 'FontName', opts.FontName, 'FontSize', opts.FontSize+4); cumulLabels = {'\kappa_1','\kappa_2','\kappa_3','\kappa_4'}; cumulTitles = {'Mean','Variance','Skewness','Binder Cumulant'}; for k = 1:opts.MaxOrder ax = nexttile; hold(ax,'on'); for idx = 1:numel(thIdx) plot(ax, xvals, squeeze(kappa(idx,:,k)), '-o', ... 'Color', cmap(idx,:), 'LineWidth', 2, 'MarkerSize', 8, 'MarkerFaceColor', cmap(idx,:)); end ylabel(ax, cumulLabels{k}, 'FontName', opts.FontName, 'FontSize', opts.FontSize); xlabel(ax, opts.XLabel, 'FontName', opts.FontName, 'FontSize', opts.FontSize); title(ax, cumulTitles{k}, 'FontName', opts.FontName, 'FontSize', opts.FontSize+2); grid(ax,'on'); set(ax,'FontName',opts.FontName,'FontSize',opts.FontSize); % --- Legend --- legend(ax, thetaLabels, 'Location', 'best', 'FontSize', opts.FontSize-2); end % --- Save figure --- if ~opts.SkipSaveFigures if ~exist(opts.SaveDirectory,'dir'), mkdir(opts.SaveDirectory); end savefig(fig, fullfile(opts.SaveDirectory, opts.SaveFileName)); end end