function results = computeSpectralAverages(S_all, scan_reference_values) %% computeSpectralAverages % Compute mean and SEM of spectra grouped by scan parameter. % Handles both 1D curves and 2D matrices. [uniqueParams, ~, idx] = unique(scan_reference_values); nParams = numel(uniqueParams); nTotal = numel(S_all); nReps = nTotal / nParams; % Determine data dimensionality firstData = S_all{1}; dataSize = size(firstData); isMatrix = (numel(size(firstData)) == 2) && all(size(firstData) > 1); curves_all = cell(1, nParams); curves_mean = cell(1, nParams); curves_err = cell(1, nParams); for i = 1:nParams if isMatrix % --- Case: 2D matrix (e.g., power spectra) --- data_sum = zeros(dataSize); % initialize nValid = zeros(dataSize); % count of non-NaN entries for r = 1:nReps idx_r = (r-1)*nParams + i; data = S_all{idx_r}; validMask = ~isnan(data); data_sum(validMask) = data_sum(validMask) + data(validMask); nValid(validMask) = nValid(validMask) + 1; end avg = data_sum ./ nValid; % mean ignoring NaNs curves_all{i} = []; % not used for 2D curves_mean{i} = avg; curves_err{i} = []; % SEM not computed for 2D else % --- Case: 1D curve --- nPoints = numel(S_all{1}); curves = zeros(nReps, nPoints); for r = 1:nReps idx_r = (r-1)*nParams + i; curves(r,:) = S_all{idx_r}; end curves_all{i} = curves; curves_mean{i} = mean(curves,1,'omitnan'); nValid = sum(~isnan(curves),1); curves_err{i} = std(curves,0,1,'omitnan') ./ sqrt(nValid); end end results.curves_all = curves_all; results.curves_mean = curves_mean; results.curves_error = curves_err; results.scan_parameters = uniqueParams; end