182 lines
7.4 KiB
Matlab
182 lines
7.4 KiB
Matlab
%% ===== BEC-Droplets: Compare Mean and Variance Across Data Sources =====
|
||
% Author: Karthik
|
||
% Date: 2025-10-29
|
||
% Version: 1.1
|
||
%
|
||
% 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., α = 45°, 60°).
|
||
% Results are saved for replotting later.
|
||
|
||
clear; clc; close all;
|
||
|
||
%% ===== Define Data Sources and Labels =====
|
||
dataSourcesList = {
|
||
struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/11', 'runs', [1]), ...
|
||
struct('sequence', 'StructuralPhaseTransition', 'date', '2025/10/10', 'runs', [2])
|
||
};
|
||
|
||
% --- Define corresponding labels for plotting ---
|
||
% These can be freely changed or extended later
|
||
curveLabels = {'\alpha = 45^\circ', '\alpha = 60^\circ'};
|
||
|
||
%% ===== Analysis Options (generic settings) =====
|
||
options = struct();
|
||
|
||
% File paths
|
||
options.baseDataFolder = '//DyLabNAS/Data';
|
||
options.FullODImagesFolder = 'E:/Data - Experiment/FullODImages/202510';
|
||
options.measurementName = 'BECToStripes';
|
||
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 = 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('BECToStripes_MeanVariance_theta_%d.fig', round(rad2deg(cumulantData(t,1).theta))));
|
||
savefig(fig, saveFileNameFig);
|
||
end
|
||
|
||
% --- Save all cumulant data ---
|
||
saveFileNameMat = fullfile(options.saveDirectory, 'BECToStripes_MeanVariance_AllThetaData.mat');
|
||
save(saveFileNameMat, 'cumulantData', 'options'); |