%% ===== Stripes-Droplets: Compare Mean and Variance Across Data Sources =====
% Author:       Karthik
% Date:         2025-10-29
% Version:      1.2
%
% Description:
%   Loops through multiple data sources, performs angular spectral analysis,
%   extracts the first two cumulants (Mean, Variance), and plots them
%   together in a 1×2 tiled layout
%   Each curve can be labeled manually.
%
%   Saves both figure (.fig) and data (.mat) for replotting later.

clear; clc; close all;

%% ===== Define Data Sources and Labels =====
dataSourcesList = {
    struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/13', 'runs', [11]), ...
    struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/13', 'runs', [12]), ...
    struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/14', 'runs', [0]), ...
    struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/14', 'runs', [1]), ...
    struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/14', 'runs', [2]), ...
    struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/14', 'runs', [3]), ...
    struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/14', 'runs', [4])
};

curveLabels = {'B = 2.55 G', 'B = 2.50 G', 'B = 2.45 G', ...
               'B = 2.40 G', 'B = 2.35 G', 'B = 2.30 G', ...
               'B = 2.20 G'};

%% ===== Analysis Options =====
options = struct();

% File paths
options.baseDataFolder     = '//DyLabNAS/Data';
options.FullODImagesFolder = 'E:/Data - Experiment/FullODImages/202510';
options.measurementName    = 'StripesToDroplets';
scriptFullPath             = mfilename('fullpath');
options.saveDirectory      = fileparts(scriptFullPath);

% Camera / imaging settings
options.cam                = 4;             % 1 - ODT_1_Axis_Camera; 2 - ODT_2_Axis_Camera; 3 - Horizontal_Axis_Camera;, 4 - Vertical_Axis_Camera;
options.angle              = 0;             % angle by which image will be rotated
options.center             = [1420, 2040];
options.span               = [200, 200];
options.fraction           = [0.1, 0.1];
options.pixel_size         = 5.86e-6;       % in meters
options.magnification      = 23.2;
options.ImagingMode        = 'HighIntensity';
options.PulseDuration      = 5e-6;          % in s

% Fourier analysis settings
options.theta_min          = deg2rad(0);
options.theta_max          = deg2rad(180);
options.N_radial_bins      = 500;
options.Radial_Sigma       = 2;
options.Radial_WindowSize  = 5;              % odd number

options.k_min              = 1.0500;         % μm⁻¹
options.k_max              = 2.7000;         % μm⁻¹
options.N_angular_bins     = 360;
options.Angular_Threshold  = 75;
options.Angular_Sigma      = 2;
options.Angular_WindowSize = 5;
options.zoom_size          = 50;

% Processing flags
options.skipUnshuffling           = false;
options.skipNormalization         = false;
options.skipFringeRemoval         = true;
options.skipPreprocessing         = true;
options.skipMasking               = true;
options.skipIntensityThresholding = true;
options.skipBinarization          = true;
options.skipFullODImagesFolderUse = false;
options.skipSaveData              = false;
options.skipSaveFigures           = true;
options.skipSaveProcessedOD       = true;
options.skipLivePlot              = false;
options.showProgressBar           = true;
options.font                      = 'Bahnschrift';

% ===== Initialize container =====
cumulantData = struct();  % will be indexed as cumulantData(thetaIdx, dataSourceIdx)
% ===== Specify theta values to analyze =====
desiredTheta = [pi/6, pi/3];  % you can add more angles here

%% ===== Loop over data sources =====
for d = 1:numel(dataSourcesList)
    dataSources = {dataSourcesList{d}};
    [options.selectedPath, options.folderPath] = Helper.selectDataSourcePath(dataSources, options);

    % --- Read all images for this data source once ---
    [od_imgs, scan_parameter_values, scan_reference_values, file_list] = ...
        Helper.collectODImages(options);

    spectral_analysis_results = Analyzer.extractFullAngularSpectralDistribution(od_imgs, options);

    results = Analyzer.recenterSpectralCurves( ...
        spectral_analysis_results.S_theta_norm_all, ...
        spectral_analysis_results.theta_vals/pi, ...
        scan_reference_values, ...
        'SearchRange', [0 90]);

    mask = results.x_values >= 0 & results.x_values <= 1;
    results.x_values = results.x_values(mask);
    for i = 1:numel(results.curves)
        results.curves{i} = results.curves{i}(:, mask);
    end

    % --- Loop over theta values for this data source ---
    for t = 1:numel(desiredTheta)
        th = desiredTheta(t);

        thetaVals = results.x_values * pi;
        [~, thIdx] = min(abs(thetaVals - th));

        N_params = numel(results.curves);
        meanVals = zeros(1, N_params);
        varVals  = zeros(1, N_params);

        for i = 1:N_params
            reps_values = results.curves{i}(:, thIdx);
            kappa = Calculator.computeCumulants(reps_values, 2);
            meanVals(i) = kappa(1);
            varVals(i)  = kappa(2);
        end

        % --- Store cumulants ---
        cumulantData(t,d).theta     = th;
        cumulantData(t,d).label     = curveLabels{d};
        cumulantData(t,d).mean      = meanVals;
        cumulantData(t,d).variance  = varVals;
        cumulantData(t,d).scan_vals = scan_reference_values;
    end
end

%% ===== Plot Mean and Variance per theta =====
N_theta = size(cumulantData,1);   % number of theta values
N_data  = size(cumulantData,2);   % number of data sources

% --- Colormap (trimmed coolwarm) ---
fullCmap = Colormaps.coolwarm(256);
blueSide = fullCmap(1:100,:);
redSide  = fullCmap(157:end,:);
trimmedCmap = [blueSide; redSide];
cmap = trimmedCmap(round(linspace(1,size(trimmedCmap,1),N_data)), :);

for t = 1:N_theta
    fig = figure('Color','w','Position',[100 100 1200 550]);
    tName = sprintf('\\theta = %.0f°', round(rad2deg(cumulantData(t,1).theta)));
    sgtitle(['Cumulants at ', tName], 'FontName', options.font, 'FontSize', 18);

    tLayout = tiledlayout(1,2,'TileSpacing','Compact','Padding','Compact');

    % --- Mean (κ₁) ---
    ax1 = nexttile; hold(ax1,'on');
    for d = 1:N_data
        plot(ax1, cumulantData(t,d).scan_vals, cumulantData(t,d).mean, '-o', ...
            'Color', cmap(d,:), 'LineWidth', 2, 'MarkerSize', 8, ...
            'MarkerFaceColor', cmap(d,:), 'DisplayName', cumulantData(t,d).label);
    end
    xlabel(ax1, '\alpha (degrees)', 'FontName', options.font, 'FontSize', 14);
    ylabel(ax1, '\kappa_1', 'FontName', options.font, 'FontSize', 14);
    title(ax1, 'Mean', 'FontName', options.font, 'FontSize', 16);
    grid(ax1,'on'); legend(ax1,'Location','northwest','FontSize',12);
    set(ax1,'FontName',options.font,'FontSize',14);

    % --- Variance (κ₂) ---
    ax2 = nexttile; hold(ax2,'on');
    for d = 1:N_data
        plot(ax2, cumulantData(t,d).scan_vals, cumulantData(t,d).variance, '-o', ...
            'Color', cmap(d,:), 'LineWidth', 2, 'MarkerSize', 8, ...
            'MarkerFaceColor', cmap(d,:), 'DisplayName', cumulantData(t,d).label);
    end
    xlabel(ax2, '\alpha (degrees)', 'FontName', options.font, 'FontSize', 14);
    ylabel(ax2, '\kappa_2', 'FontName', options.font, 'FontSize', 14);
    title(ax2, 'Variance', 'FontName', options.font, 'FontSize', 16);
    grid(ax2,'on'); legend(ax2,'Location','northwest','FontSize',12);
    set(ax2,'FontName',options.font,'FontSize',14);

    % --- Save figure ---
    saveFileNameFig = fullfile(options.saveDirectory, ...
        sprintf('StripesToDroplets_MeanVariance_theta_%d.fig', round(rad2deg(cumulantData(t,1).theta))));
    savefig(fig, saveFileNameFig);
end

% --- Save all cumulant data ---
saveFileNameMat = fullfile(options.saveDirectory, 'StripesToDroplets_MeanVariance_AllThetaData.mat');
save(saveFileNameMat, 'cumulantData', 'options');
