Modifications in batch analysis script to take sequence name, date and run number, to reuse data saved in workspace and enhancements to image viewer.

This commit is contained in:
Karthik 2025-08-18 16:03:25 +02:00
parent f52666d929
commit 1f7526c594
4 changed files with 101 additions and 45 deletions

View File

@ -9,7 +9,7 @@ function results_all = batchAnalyze(dataSources, options)
options.baseDataFolder = '//DyLabNAS/Data'; options.baseDataFolder = '//DyLabNAS/Data';
end end
results_all = struct([]); % one element per folder results_all = {}; % one element per folder
for i = 1:numel(dataSources) for i = 1:numel(dataSources)
ds = dataSources{i}; ds = dataSources{i};
@ -63,7 +63,7 @@ function results_all = batchAnalyze(dataSources, options)
result.results = analysisResults; result.results = analysisResults;
% Append to output % Append to output
results_all(end+1,1) = result; results_all{end+1,1} = result;
catch ME catch ME
warning("Error processing %s/%s/%s: %s", ... warning("Error processing %s/%s/%s: %s", ...

View File

@ -20,6 +20,15 @@ function [ordered_od_imgs, ordered_scan_parameter_values, ordered_file_list] = c
% ordered_od_imgs : cell array of processed OD images (ordered) % ordered_od_imgs : cell array of processed OD images (ordered)
% ordered_scan_parameter_values: vector of scan parameter values (ordered) % ordered_scan_parameter_values: vector of scan parameter values (ordered)
% ordered_file_list : cell array of file names (ordered) % ordered_file_list : cell array of file names (ordered)
% --- Early exit if processed data already exist ---
if evalin('base', 'exist(''od_imgs'',''var'') && exist(''scan_parameter_values'',''var'') && exist(''file_list'',''var'')')
fprintf('\nReusing processed OD images, scan parameters, and file list from memory.\n');
ordered_od_imgs = evalin('base','od_imgs');
ordered_scan_parameter_values = evalin('base','scan_parameter_values');
ordered_file_list = evalin('base','file_list');
return; % skip rest of the function
end
% --- Check if the full OD dataset and scan parameters exist in workspace --- % --- Check if the full OD dataset and scan parameters exist in workspace ---
fullDataExists = evalin('base', 'exist(''full_od_imgs'', ''var'')') && ... fullDataExists = evalin('base', 'exist(''full_od_imgs'', ''var'')') && ...
@ -39,7 +48,7 @@ function [ordered_od_imgs, ordered_scan_parameter_values, ordered_file_list] = c
fprintf('\nFull OD image dataset or scan parameters not found in memory.\n'); fprintf('\nFull OD image dataset or scan parameters not found in memory.\n');
[full_od_imgs, full_bkg_imgs, raw_scan_parameter_values, raw_file_list] = Helper.processRawData(options); [full_od_imgs, full_bkg_imgs, raw_scan_parameter_values, raw_file_list] = Helper.processRawData(options);
% Optionally save the full dataset into workspace for future reuse % Save raw full dataset for reuse
assignin('base', 'full_od_imgs', full_od_imgs); assignin('base', 'full_od_imgs', full_od_imgs);
assignin('base', 'full_bkg_imgs', full_bkg_imgs); assignin('base', 'full_bkg_imgs', full_bkg_imgs);
assignin('base', 'raw_scan_parameter_values', raw_scan_parameter_values); assignin('base', 'raw_scan_parameter_values', raw_scan_parameter_values);
@ -103,9 +112,9 @@ function [ordered_od_imgs, ordered_scan_parameter_values, ordered_file_list] = c
ordered_file_list = cell(1, n_total); ordered_file_list = cell(1, n_total);
counter = 1; counter = 1;
temp_scan_values = raw_scan_parameter_values; % copy for indexing temp_scan_values = raw_scan_parameter_values;
temp_od_imgs = processed_od_imgs; temp_od_imgs = processed_od_imgs;
temp_file_list = raw_file_list; % copy original file paths for reordering temp_file_list = raw_file_list;
for rep = 1:n_reps for rep = 1:n_reps
for val = options.scan_reference_values for val = options.scan_reference_values
@ -113,25 +122,25 @@ function [ordered_od_imgs, ordered_scan_parameter_values, ordered_file_list] = c
if isempty(idx), continue; end if isempty(idx), continue; end
ordered_scan_parameter_values(counter) = temp_scan_values(idx); ordered_scan_parameter_values(counter) = temp_scan_values(idx);
ordered_od_imgs{counter} = temp_od_imgs{idx}; ordered_od_imgs{counter} = temp_od_imgs{idx};
ordered_file_list{counter} = temp_file_list{idx}; % reorder file list ordered_file_list{counter} = temp_file_list{idx};
temp_scan_values(idx) = NaN; % mark as used temp_scan_values(idx) = NaN;
temp_od_imgs{idx} = []; temp_od_imgs{idx} = [];
temp_file_list{idx} = []; temp_file_list{idx} = [];
counter = counter + 1; counter = counter + 1;
end end
end end
fprintf('\nImage reordering completed.\n'); fprintf('\nImage reordering completed.\n');
else else
% No unshuffling: keep original order % No unshuffling: keep original order
ordered_od_imgs = processed_od_imgs; ordered_od_imgs = processed_od_imgs;
ordered_scan_parameter_values = raw_scan_parameter_values; ordered_scan_parameter_values = raw_scan_parameter_values;
ordered_file_list = raw_file_list; ordered_file_list = raw_file_list;
end end
% Optionally save the full dataset into workspace for future reuse % --- Save processed dataset for reuse ---
assignin('base', 'od_imgs', ordered_od_imgs); assignin('base', 'od_imgs', ordered_od_imgs);
assignin('base', 'scan_parameter_values', ordered_scan_parameter_values); assignin('base', 'scan_parameter_values', ordered_scan_parameter_values);
assignin('base', 'file_list', ordered_file_list);
fprintf('\nOD image dataset ready for further analysis.\n'); fprintf('\nOD image dataset ready for further analysis.\n');
end end

View File

@ -1,6 +1,10 @@
idx = 1;
compiled_results = results_all{idx}.results;
options.skipSaveFigures = false;
%% ------------------ 1. Mean ± Std Plots ------------------ %% ------------------ 1. Mean ± Std Plots ------------------
% Plot Radial Spectral Contrast % Plot Radial Spectral Contrast
Plotter.plotMeanWithSE(scan_parameter_values, results_all.spectral_analysis_results.radial_spectral_contrast, ... Plotter.plotMeanWithSE(scan_parameter_values, compiled_results.spectral_analysis_results.radial_spectral_contrast, ...
'Title', options.titleString, ... 'Title', options.titleString, ...
'XLabel', 'B (G)', ... 'XLabel', 'B (G)', ...
'YLabel', 'Radial Spectral Contrast', ... 'YLabel', 'Radial Spectral Contrast', ...
@ -11,7 +15,7 @@ Plotter.plotMeanWithSE(scan_parameter_values, results_all.spectral_analysis_resu
'SkipSaveFigures', options.skipSaveFigures); 'SkipSaveFigures', options.skipSaveFigures);
% Plot Angular Spectral Weight % Plot Angular Spectral Weight
Plotter.plotMeanWithSE(scan_parameter_values, results_all.spectral_analysis_results.angular_spectral_weight, ... Plotter.plotMeanWithSE(scan_parameter_values, compiled_results.spectral_analysis_results.angular_spectral_weight, ...
'Title', options.titleString, ... 'Title', options.titleString, ...
'XLabel', 'B (G)', ... 'XLabel', 'B (G)', ...
'YLabel', 'Angular Spectral Weight', ... 'YLabel', 'Angular Spectral Weight', ...
@ -22,7 +26,7 @@ Plotter.plotMeanWithSE(scan_parameter_values, results_all.spectral_analysis_resu
'SkipSaveFigures', options.skipSaveFigures); 'SkipSaveFigures', options.skipSaveFigures);
% Plot Peak Offset Angular Correlation % Plot Peak Offset Angular Correlation
Plotter.plotMeanWithSE(options.scan_reference_values, results_all.custom_g_results.max_g2_all_per_scan_parameter_value, ... Plotter.plotMeanWithSE(options.scan_reference_values, compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, ...
'Title', options.titleString, ... 'Title', options.titleString, ...
'XLabel', 'B (G)', ... 'XLabel', 'B (G)', ...
'YLabel', '$\mathrm{max}[g^{(2)}_{[50,70]}(\delta\theta)]$', ... 'YLabel', '$\mathrm{max}[g^{(2)}_{[50,70]}(\delta\theta)]$', ...
@ -34,9 +38,9 @@ Plotter.plotMeanWithSE(options.scan_reference_values, results_all.custom_g_resul
'SkipSaveFigures', options.skipSaveFigures); 'SkipSaveFigures', options.skipSaveFigures);
%% ------------------ 2. g²(θ) across transition ------------------ %% ------------------ 2. g²(θ) across transition ------------------
Plotter.plotG2(results_all.full_g2_results.g2_all, ... Plotter.plotG2(compiled_results.full_g2_results.g2_all, ...
results_all.full_g2_results.g2_error_all, ... compiled_results.full_g2_results.g2_error_all, ...
results_all.full_g2_results.theta_values, ... compiled_results.full_g2_results.theta_values, ...
options.scan_reference_values, ... options.scan_reference_values, ...
'rot_mag_field', ... 'rot_mag_field', ...
'Title', options.titleString, ... 'Title', options.titleString, ...
@ -50,7 +54,7 @@ Plotter.plotG2(results_all.full_g2_results.g2_all, ...
'Colormap', @Colormaps.coolwarm); 'Colormap', @Colormaps.coolwarm);
%% ------------------ 3. PDF of max g² across transition ------------------ %% ------------------ 3. PDF of max g² across transition ------------------
Plotter.plotPDF(results_all.custom_g_results.max_g2_all_per_scan_parameter_value, options.scan_reference_values, ... Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, options.scan_reference_values, ...
'Title', options.titleString, ... 'Title', options.titleString, ...
'XLabel', 'B (G)', ... 'XLabel', 'B (G)', ...
'YLabel', '$\mathrm{max}[g^{(2)}]$', ... 'YLabel', '$\mathrm{max}[g^{(2)}]$', ...
@ -67,7 +71,7 @@ Plotter.plotPDF(results_all.custom_g_results.max_g2_all_per_scan_parameter_value
%% ------------------ 4. Cumulants across transition ------------------ %% ------------------ 4. Cumulants across transition ------------------
Plotter.plotCumulants(options.scan_reference_values, ... Plotter.plotCumulants(options.scan_reference_values, ...
{results_all.custom_g_results.mean_max_g2, results_all.custom_g_results.var_max_g2, results_all.custom_g_results.skew_max_g2_angle, results_all.custom_g_results.fourth_order_cumulant_max_g2}, ... {compiled_results.custom_g_results.mean_max_g2, compiled_results.custom_g_results.var_max_g2, compiled_results.custom_g_results.skew_max_g2_angle, compiled_results.custom_g_results.fourth_order_cumulant_max_g2}, ...
'Title', 'Cumulants of Peak Offset Angular Correlation', ... 'Title', 'Cumulants of Peak Offset Angular Correlation', ...
'XLabel', 'B (G)', ... 'XLabel', 'B (G)', ...
'FigNum', 6, ... 'FigNum', 6, ...
@ -136,7 +140,7 @@ compareMultipleDatasets(scanValsCell, meanValsCell, stderrValsCell, ...
BFields = [2.35, 2.15, 2.0, 1.85, 1.7, 1.55, 1.4, 1.35]; BFields = [2.35, 2.15, 2.0, 1.85, 1.7, 1.55, 1.4, 1.35];
% Heatmap of mean_max_g2_values % Heatmap of mean_max_g2_values
Plotter.plotHeatmap(results_all, options.scan_groups, BFields, 'mean_max_g2_values', ... Plotter.plotHeatmap(compiled_results, options.scan_groups, BFields, 'mean_max_g2_values', ...
'Colormap', @sky, ... 'Colormap', @sky, ...
'CLim', [0 1], ... 'CLim', [0 1], ...
'XLabel', '\alpha (degrees)', ... 'XLabel', '\alpha (degrees)', ...
@ -147,7 +151,7 @@ Plotter.plotHeatmap(results_all, options.scan_groups, BFields, 'mean_max_g2_valu
'SaveDirectory', options.resultsDir); 'SaveDirectory', options.resultsDir);
% Heatmap of radial_spectral_contrast % Heatmap of radial_spectral_contrast
Plotter.plotHeatmap(results_all, options.scan_groups, BFields, 'radial_spectral_contrast', ... Plotter.plotHeatmap(compiled_results, options.scan_groups, BFields, 'radial_spectral_contrast', ...
'Colormap', @sky, ... 'Colormap', @sky, ...
'CLim', [0 0.008], ... 'CLim', [0 0.008], ...
'XLabel', '\alpha (degrees)', ... 'XLabel', '\alpha (degrees)', ...

View File

@ -1,10 +1,19 @@
%% ===== BEC-Droplets Settings ===== %% ===== BEC-Droplets Settings =====
% Specify data location to run analysis on
dataSources = {
struct('sequence', 'StructuralPhaseTransition', ...
'date', '2025/08/13', ...
'runs', [62]) % specify run numbers as a string in "" or just as a numeric value
};
options = struct(); options = struct();
% File / paths % File / paths
options.folderPath = "//DyLabNAS/Data/StructuralPhaseTransition/2025/08/13/0062"; options.baseDataFolder = '//DyLabNAS/Data';
options.savefileName = 'BECToDroplets'; options.savefileName = 'BECToDroplets';
options.saveDirectory = "Z:/Users/Karthik/Data-Analyzer/+Scripts"; scriptFullPath = mfilename('fullpath');
options.saveDirectory = fileparts(scriptFullPath);
% Camera / imaging % Camera / imaging
options.cam = 5; options.cam = 5;
@ -19,41 +28,40 @@ options.ImagingMode = 'HighIntensity';
options.PulseDuration = 5e-6; % in s options.PulseDuration = 5e-6; % in s
% Fourier analysis settings % Fourier analysis settings
% Radial Spectral Distribution
options.theta_min = deg2rad(0); options.theta_min = deg2rad(0);
options.theta_max = deg2rad(180); options.theta_max = deg2rad(180);
options.N_radial_bins = 500; options.N_radial_bins = 500;
options.Radial_Sigma = 2; options.Radial_Sigma = 2;
options.Radial_WindowSize = 5; % odd number for centered moving avg options.Radial_WindowSize = 5; % odd number
% Angular Spectral Distribution options.k_min = 1.2771; % μm¹
options.k_min = 1.2771; % in μm¹ options.k_max = 2.5541; % μm¹
options.k_max = 2.5541; % in μm¹
options.N_angular_bins = 180; options.N_angular_bins = 180;
options.Angular_Threshold = 75; options.Angular_Threshold = 75;
options.Angular_Sigma = 2; options.Angular_Sigma = 2;
options.Angular_WindowSize = 5; options.Angular_WindowSize = 5;
options.zoom_size = 50; % zoomed-in region around center options.zoom_size = 50;
% Scan parameter % Scan parameter
options.scan_parameter = 'rot_mag_field'; options.scan_parameter = 'rot_mag_field';
if strcmp(options.savefileName, 'BECToDroplets') switch options.savefileName
options.scan_reference_values = [2.40, 2.39, 2.38, 2.37, 2.35, 2.34, 2.32, 2.30, 2.28, 2.26, 2.24, 2.22, 2.2, 2.15, 2.10, 2.05, 2, 1.95, 1.90, 1.85, 1.8]; case 'BECToDroplets'
options.titleString = 'BEC to Droplets'; options.scan_reference_values = [2.40, 2.39, 2.38, 2.37, 2.35, 2.34, 2.32, 2.30, 2.28, 2.26, 2.24, 2.22, 2.2, 2.15, 2.10, 2.05, 2, 1.95, 1.90, 1.85, 1.8];
elseif strcmp(options.savefileName, 'BECToStripes') options.titleString = 'BEC to Droplets';
options.scan_reference_values = [2.45, 2.44, 2.43, 2.42, 2.4, 2.39, 2.38, 2.37, 2.36, 2.35, 2.34, 2.32, 2.3, 2.28, 2.25, 2.2, 2.15, 2.10, 2.0, 1.90, 1.8]; case 'BECToStripes'
options.titleString = 'BEC to Stripes'; options.scan_reference_values = [2.45, 2.44, 2.43, 2.42, 2.4, 2.39, 2.38, 2.37, 2.36, 2.35, 2.34, 2.32, 2.3, 2.28, 2.25, 2.2, 2.15, 2.10, 2.0, 1.90, 1.8];
elseif strcmp(options.savefileName, 'DropletsToStripes') options.titleString = 'BEC to Stripes';
options.scan_reference_values = [0, 5, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 35, 40]; case 'DropletsToStripes'
options.titleString = 'Droplets to Stripes'; options.scan_reference_values = [0, 5, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 35, 40];
elseif strcmp(options.savefileName, 'StripesToDroplets') options.titleString = 'Droplets to Stripes';
options.scan_reference_values = fliplr([0, 5, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 35, 40]); case 'StripesToDroplets'
options.titleString = 'Stripes to Droplets'; options.scan_reference_values = fliplr([0, 5, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 35, 40]);
options.titleString = 'Stripes to Droplets';
end end
% Flags % Flags
options.skipNormalization = true; options.skipNormalization = false;
options.skipUnshuffling = false; options.skipUnshuffling = false;
options.skipPreprocessing = true; options.skipPreprocessing = true;
options.skipMasking = true; options.skipMasking = true;
@ -62,14 +70,49 @@ options.skipBinarization = true;
options.skipMovieRender = true; options.skipMovieRender = true;
options.skipSaveFigures = true; options.skipSaveFigures = true;
options.skipSaveOD = true; options.skipSaveOD = true;
options.skipLivePlot = false; options.skipLivePlot = false;
options.showProgressBar = true; options.showProgressBar = true;
% Optional extras % Extras
options.font = 'Bahnschrift'; options.font = 'Bahnschrift';
%% %% ===== Build Paths from Data Sources =====
allPaths = {}; % initialize
for i = 1:length(dataSources)
ds = dataSources{i};
% Split the date string into year/month/day
dateParts = strsplit(ds.date, '/');
for run = ds.runs
runStr = sprintf('%04d', run); % 4-digit run number
fullPath = fullfile(options.baseDataFolder, ds.sequence, dateParts{:}, runStr);
if isfolder(fullPath) % only include valid directories
allPaths{end+1} = fullPath;
else
warning('Path does not exist: %s', fullPath);
end
end
end
% Let user select a single path
set(0,'DefaultUicontrolFontSize',10); % increase default font size
[selectedIndex, tf] = listdlg('PromptString','Select a path to analyze:', ...
'SelectionMode','single', ...
'ListString', allPaths, ...
'ListSize',[400, 300]); % width x height in pixels
if tf
options.folderPath = allPaths{selectedIndex}; % store in options
fprintf('Path set to selection: %s\n', options.folderPath);
else
error('No path selected. Aborting.');
end
%% ===== Collect Images and Launch Viewer =====
[od_imgs, scan_parameter_values, file_list] = Helper.collectODImages(options); [od_imgs, scan_parameter_values, file_list] = Helper.collectODImages(options);
%%
Analyzer.runInteractiveODImageViewer(od_imgs, scan_parameter_values, file_list, options); Analyzer.runInteractiveODImageViewer(od_imgs, scan_parameter_values, file_list, options);