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 largest peak in [0, pi/2] 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
            % Find all peaks in the search range
            [pks, locs] = findpeaks(curve(idx_range));
            if isempty(pks)
                [~, local_max_idx] = max(curve(idx_range));
            else
                [~, max_idx_in_peaks] = max(pks);
                local_max_idx = locs(max_idx_in_peaks);
            end
            peak_idx = idx_range(local_max_idx);
        end

        % From the largest 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
