Calculations/Data-Analyzer/+Scripts/BECToDroplets/runAndCompareAngularSpectralDistributionAnalysis.m

183 lines
7.2 KiB
Matlab
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

%% ===== BEC-Droplets: Compare Mean and Variance Across Data Sources =====
% Author: Karthik
% Date: 2025-10-29
% Version: 1.0
%
% Description:
% Loops through multiple data sources, performs angular spectral analysis,
% extracts only the first two cumulants (mean, variance), and plots them
% together on a single figure for comparison.
% Each curve can be labeled manually (e.g., α = 0°, 15°, 30°).
% Results are saved for replotting later.
clear; clc; close all;
%% ===== Define Data Sources and Labels =====
dataSourcesList = {
struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/24', 'runs', [3]), ...
struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/12', 'runs', [6]), ...
struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/20', 'runs', [1])
};
% --- Define corresponding labels for plotting ---
% These can be freely changed or extended later
curveLabels = {'\alpha = 0^\circ', '\alpha = 15^\circ', '\alpha = 30^\circ'};
%% ===== Analysis Options (generic settings) =====
options = struct();
% File paths
options.baseDataFolder = '//DyLabNAS/Data';
options.FullODImagesFolder = 'E:/Data - Experiment/FullODImages/202510';
options.measurementName = 'BECToDroplets';
scriptFullPath = mfilename('fullpath');
options.saveDirectory = fileparts(scriptFullPath);
% Camera / imaging settings
options.cam = 4;
options.angle = 0;
options.center = [1420, 2030];
options.span = [200, 200];
options.fraction = [0.1, 0.1];
options.pixel_size = 5.86e-6;
options.magnification = 23.2;
options.ImagingMode = 'HighIntensity';
options.PulseDuration = 5e-6;
% 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;
options.k_min = 1.0500;
options.k_max = 2.7000;
options.N_angular_bins = 180;
options.Angular_Threshold = 75;
options.Angular_Sigma = 2;
options.Angular_WindowSize = 5;
options.zoom_size = 50;
% 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 Containers =====
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);
[od_imgs, scan_parameter_values, scan_reference_values, file_list] = ...
Helper.collectODImages(options);
spectral_analysis_results = Analyzer.extractFullAngularSpectralDistribution(od_imgs, options);
% --- Recenter and restrict curves ---
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
% --- Compute Mean and Variance across repetitions for each desired theta ---
thetaVals = results.x_values * pi;
for t = 1:numel(desiredTheta)
th = desiredTheta(t);
[~, 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 results ---
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 and Save =====
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('BECToDroplets_MeanVariance_theta_%d.fig', round(rad2deg(cumulantData(t,1).theta))));
savefig(fig, saveFileNameFig);
end
% --- Save all cumulant data ---
saveFileNameMat = fullfile(options.saveDirectory, 'BECToDroplets_MeanVariance_AllThetaData.mat');
save(saveFileNameMat, 'cumulantData', 'options');