function results = recenterSpectralCurves(S_theta_all, theta_vals, scan_reference_values, varargin) %% recenterSpectralCurves % Author: Karthik % Date: 2025-10-09 % Version: 1.0 % % Description: % Recenters each curve so its first peak is at zero (no wrap-around), % pads shorter curves with NaN, and computes mean and SEM for each % scan parameter. Returns a struct ready for plotting. % % Inputs: % S_theta_all - 1x(N_reps*N_params) cell array of curves % theta_vals - vector of theta values (radians) % scan_reference_values - vector of unique scan parameters % % Optional name-value pairs: % 'SearchRange' - [deg_min deg_max] range for first-peak search (default: [0 90]) % % Output struct fields: % results.curves % results.x_values % results.curves_mean % results.curves_error % results.scan_parameter_values % --- Parse optional inputs --- p = inputParser; addParameter(p, 'SearchRange', [0 pi/2], @(x) isnumeric(x) && numel(x)==2); parse(p, varargin{:}); opts = p.Results; % --- Setup --- N_params = numel(scan_reference_values); Ntotal = numel(S_theta_all); Nreps = Ntotal / N_params; theta_min = opts.SearchRange(1); theta_max = opts.SearchRange(2); % --- Shift each curve so its first peak is at zero --- S_theta_all_shifted = cell(size(S_theta_all)); for k = 1:Ntotal curve = S_theta_all{k}; idx_range = find(theta_vals >= theta_min & theta_vals <= theta_max); if isempty(idx_range) [~, peak_idx] = max(curve); else [~, local_max_idx] = max(curve(idx_range)); peak_idx = idx_range(local_max_idx); end % From first peak onward S_theta_all_shifted{k} = curve(peak_idx:end); end % --- Pad shorter curves with NaN --- Npoints_shifted = max(cellfun(@numel, S_theta_all_shifted)); for k = 1:Ntotal len = numel(S_theta_all_shifted{k}); if len < Npoints_shifted S_theta_all_shifted{k} = [S_theta_all_shifted{k}, nan(1, Npoints_shifted - len)]; end end % --- Compute mean and SEM --- curves_all = cell(1, N_params); curves_mean = cell(1, N_params); curves_err = cell(1, N_params); for i = 1:N_params curves = zeros(Nreps, Npoints_shifted); for r = 1:Nreps idx = (r-1)*N_params + i; % interleaved indexing curves(r,:) = S_theta_all_shifted{idx}; end curves_all{i} = curves; curves_mean{i} = nanmean(curves,1); curves_err{i} = nanstd(curves,0,1)/sqrt(Nreps); end % --- Construct results struct --- results.curves = curves_all; results.x_values = theta_vals(1:Npoints_shifted) - theta_vals(1); % shift start to zero results.curves_mean = curves_mean; results.curves_error = curves_err; results.scan_reference_values = scan_reference_values; end