343 lines
13 KiB
Matlab
343 lines
13 KiB
Matlab
%% ===== BEC-Droplets-Stripes Settings =====
|
|
|
|
% Specify data location to run analysis on
|
|
dataSources = {
|
|
struct('sequence', 'TwoDGas', ...
|
|
'date', '2025/06/23', ...
|
|
'runs', [300]) % specify run numbers as a string in "" or just as a numeric value
|
|
};
|
|
|
|
options = struct();
|
|
|
|
% File paths
|
|
options.baseDataFolder = '//DyLabNAS/Data';
|
|
options.FullODImagesFolder = 'E:/Data - Experiment/FullODImages/202506';
|
|
options.measurementName = 'DropletsToStripes';
|
|
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 = [1410, 2030];
|
|
options.span = [200, 200];
|
|
options.fraction = [0.1, 0.1];
|
|
options.pixel_size = 5.86e-6; % in meters
|
|
options.magnification = 23.94;
|
|
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.2771; % μm⁻¹
|
|
options.k_max = 2.5541; % μm⁻¹
|
|
options.N_angular_bins = 360;
|
|
options.Angular_Threshold = 75;
|
|
options.Angular_Sigma = 2;
|
|
options.Angular_WindowSize = 5;
|
|
options.zoom_size = 50;
|
|
|
|
%
|
|
options.maximumShift = 8;
|
|
options.Radial_Theta = deg2rad(45);
|
|
options.Radial_Minimum = 2;
|
|
options.Radial_Maximum = 6;
|
|
options.skipLivePlot = false;
|
|
|
|
% 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;
|
|
|
|
% Extras
|
|
options.font = 'Bahnschrift';
|
|
switch options.measurementName
|
|
case 'BECToDroplets'
|
|
options.scan_parameter = 'rot_mag_field';
|
|
options.flipSortOrder = true;
|
|
options.scanParameterUnits = 'gauss';
|
|
options.titleString = 'BEC to Droplets';
|
|
case 'BECToStripes'
|
|
options.scan_parameter = 'rot_mag_field';
|
|
options.flipSortOrder = true;
|
|
options.scanParameterUnits = 'gauss';
|
|
options.titleString = 'BEC to Stripes';
|
|
case 'DropletsToStripes'
|
|
options.scan_parameter = 'ps_rot_mag_fin_pol_angle';
|
|
options.flipSortOrder = false;
|
|
options.scanParameterUnits = 'degrees';
|
|
options.titleString = 'Droplets to Stripes';
|
|
case 'StripesToDroplets'
|
|
options.scan_parameter = 'ps_rot_mag_fin_pol_angle';
|
|
options.flipSortOrder = false;
|
|
options.scanParameterUnits = 'degrees';
|
|
options.titleString = 'Stripes to Droplets';
|
|
end
|
|
|
|
%% ===== Collect Images and Launch Viewer =====
|
|
|
|
[options.selectedPath, options.folderPath] = Helper.selectDataSourcePath(dataSources, options);
|
|
|
|
[od_imgs, scan_parameter_values, scan_reference_values, file_list] = Helper.collectODImages(options);
|
|
|
|
%% Conduct spectral analysis
|
|
spectral_analysis_results = Analyzer.extractFullAngularSpectralDistribution(od_imgs, options);
|
|
|
|
%% ------------------ 1. Plot of all Angular Spectral Distribution Curves ------------------
|
|
Plotter.plotSpectralCurves( ...
|
|
spectral_analysis_results.S_theta_norm_all, ...
|
|
spectral_analysis_results.theta_vals/pi, ... % correct θ values
|
|
scan_reference_values, ... % correct scan params
|
|
'Title', options.titleString, ...
|
|
'XLabel', '\theta / \pi', ...
|
|
'YLabel', 'S(\theta)', ...
|
|
'HighlightEvery', 10, ... % highlight every 10th repetition
|
|
'FontName', options.font, ...
|
|
'FigNum', 1, ...
|
|
'TileTitlePrefix', '\alpha', ... % user-defined tile prefix
|
|
'TileTitleSuffix', '^\circ', ... % user-defined suffix (e.g., degrees symbol)
|
|
'SkipSaveFigures', options.skipSaveFigures, ...
|
|
'SaveFileName', 'SpectralCurves.fig', ...
|
|
'SaveDirectory', options.saveDirectory);
|
|
|
|
%% ------------------ 2. Plot of all Angular Spectral Distribution Curves shifted ------------------
|
|
|
|
% --- Recenter curves first ---
|
|
results = Analyzer.recenterSpectralCurves(spectral_analysis_results.S_theta_norm_all, ...
|
|
spectral_analysis_results.theta_vals/pi, ...
|
|
scan_reference_values, ...
|
|
'SearchRange', [0 90]); % degrees
|
|
|
|
% --- Restrict to desired theta range (e.g., 0 to 0.5*pi) ---
|
|
thetaMin = 0; % in units of pi (since you divided by pi)
|
|
thetaMax = 1; % corresponds to pi/2
|
|
|
|
mask = results.x_values >= thetaMin & results.x_values <= thetaMax;
|
|
results.x_values = results.x_values(mask);
|
|
|
|
% Apply the same mask to each curve set
|
|
for i = 1:numel(results.curves)
|
|
results.curves{i} = results.curves{i}(:, mask);
|
|
results.curves_mean{i} = results.curves_mean{i}(mask);
|
|
results.curves_error{i}= results.curves_error{i}(mask);
|
|
end
|
|
|
|
Plotter.plotSpectralCurvesRecentered( ...
|
|
results, ...
|
|
scan_reference_values, ... % correct scan params
|
|
'Title', options.titleString, ...
|
|
'XLabel', '\theta / \pi', ...
|
|
'YLabel', 'S(\theta)', ...
|
|
'HighlightEvery', 10, ... % highlight every 10th repetition
|
|
'FontName', options.font, ...
|
|
'FigNum', 2, ...
|
|
'TileTitlePrefix', '\alpha', ... % user-defined tile prefix
|
|
'TileTitleSuffix', '^\circ', ... % user-defined suffix (e.g., degrees symbol)
|
|
'SkipSaveFigures', options.skipSaveFigures, ...
|
|
'SaveFileName', 'SpectralCurves.fig', ...
|
|
'SaveDirectory', options.saveDirectory);
|
|
|
|
%% ------------------ 3. Plot cumulants from shifted Angular Spectral Distribution Curves ------------------
|
|
Plotter.plotSpectralDistributionCumulants(results, ...
|
|
'Title', options.titleString, ...
|
|
'XLabel', '\alpha (degrees)', ...
|
|
'FontName', options.font, ...
|
|
'FontSize', 14, ...
|
|
'FigNum', 3, ...
|
|
'SkipSaveFigures', false, ...
|
|
'SaveFileName', 'SpectralCumulants.fig');
|
|
|
|
%% ------------------ 4. Fit shifted Angular Spectral Distribution Curves ------------------
|
|
fitResults = Analyzer.fitTwoGaussianCurves(...
|
|
spectral_analysis_results.S_theta_norm_all, ...
|
|
spectral_analysis_results.theta_vals, ...
|
|
'MaxTheta', pi/2, ...
|
|
'DeviationLimit', 0.30, ...
|
|
'PositionThreshold', pi/15, ...
|
|
'AmplitudeThreshold', 0.02);
|
|
|
|
%% ------------------ 5. Plot fit parameters - amplitude ------------------
|
|
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'A2', ...
|
|
'Title', options.titleString, ...
|
|
'XLabel', '\alpha (degrees)', ...
|
|
'YLabel', 'Secondary peak amplitude', ...
|
|
'FontName', options.font, ...
|
|
'FontSize', 16, ...
|
|
'FigNum', 4, ...
|
|
'SkipSaveFigures', options.skipSaveFigures, ...
|
|
'SaveFileName', 'SecondaryPeakAmplitudePDF.fig', ...
|
|
'PlotType', 'histogram', ...
|
|
'NumberOfBins', 20, ...
|
|
'NormalizeHistogram', true, ...
|
|
'Colormap', @Colormaps.coolwarm, ...
|
|
'XLim', [min(scan_reference_values), max(scan_reference_values)]);
|
|
|
|
%% ------------------ 6. Plot fit parameters - position ------------------
|
|
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'mu2', ...
|
|
'Title', options.titleString, ...
|
|
'XLabel', '\alpha (degrees)', ...
|
|
'YLabel', 'Secondary peak position (\theta, rad)', ...
|
|
'FontName', options.font, ...
|
|
'FontSize', 16, ...
|
|
'FigNum', 5, ...
|
|
'SkipSaveFigures', options.skipSaveFigures, ...
|
|
'SaveFileName', 'SecondaryPeakPositionPDF.fig', ...
|
|
'PlotType', 'histogram', ...
|
|
'NumberOfBins', 20, ...
|
|
'NormalizeHistogram', true, ...
|
|
'Colormap', @Colormaps.coolwarm, ...
|
|
'XLim', [min(scan_reference_values), max(scan_reference_values)]);
|
|
|
|
%% ------------------ 7. Plot fit parameters - width ------------------
|
|
Plotter.plotFitParameterPDF(fitResults, scan_reference_values, 'sigma2', ...
|
|
'Title', options.titleString, ...
|
|
'XLabel', '\alpha (degrees)', ...
|
|
'YLabel', 'Secondary peak width (\sigma, rad)', ...
|
|
'FontName', options.font, ...
|
|
'FontSize', 16, ...
|
|
'FigNum', 6, ...
|
|
'SkipSaveFigures', options.skipSaveFigures, ...
|
|
'SaveFileName', 'SecondaryPeakWidthPDF.fig', ...
|
|
'PlotType', 'histogram', ...
|
|
'NumberOfBins', 20, ...
|
|
'NormalizeHistogram', true, ...
|
|
'Colormap', @Colormaps.coolwarm, ...
|
|
'XLim', [min(scan_reference_values), max(scan_reference_values)]);
|
|
|
|
%% ------------------ 8. Plot fit parameters of mean shifted Angular Spectral Distribution Curves ------------------
|
|
|
|
% --- Recenter curves first ---
|
|
results = Analyzer.recenterSpectralCurves(spectral_analysis_results.S_theta_norm_all, ...
|
|
spectral_analysis_results.theta_vals/pi, ...
|
|
scan_reference_values, ...
|
|
'SearchRange', [0 90]); % degrees
|
|
|
|
% --- Restrict to desired theta range (e.g., 0 to 0.5*pi) ---
|
|
thetaMin = 0; % in units of pi (since you divided by pi)
|
|
thetaMax = 1; % corresponds to pi/2
|
|
|
|
mask = results.x_values >= thetaMin & results.x_values <= thetaMax;
|
|
results.x_values = results.x_values(mask);
|
|
|
|
% Apply the same mask to each curve set
|
|
for i = 1:numel(results.curves)
|
|
results.curves_mean{i} = results.curves_mean{i}(mask);
|
|
end
|
|
|
|
% --- Fit two-Gaussian model to mean curves ---
|
|
fitResultsMean = Analyzer.fitTwoGaussianCurves(...
|
|
results.curves_mean, ...
|
|
results.x_values*pi, ...
|
|
'MaxTheta', pi/2, ...
|
|
'DeviationLimit', 0.30, ...
|
|
'PositionThreshold', pi/15, ...
|
|
'AmplitudeThreshold', 0.02, ...
|
|
'RecenterCurves', false);
|
|
|
|
% --- Prepare parameter values ---
|
|
N_params = numel(fitResultsMean);
|
|
amp2_vals = nan(1, N_params);
|
|
mu2_vals = nan(1, N_params);
|
|
sigma2_vals = nan(1, N_params);
|
|
|
|
for i = 1:N_params
|
|
pFit = fitResultsMean(i).pFit;
|
|
|
|
if all(pFit == 0)
|
|
% No secondary peak → plot as zero
|
|
amp2_vals(i) = 0;
|
|
mu2_vals(i) = 0;
|
|
sigma2_vals(i) = 0;
|
|
|
|
elseif all(~isnan(pFit))
|
|
% Successful fit → use fitted values
|
|
amp2_vals(i) = pFit(3);
|
|
mu2_vals(i) = pFit(4);
|
|
sigma2_vals(i) = pFit(5);
|
|
|
|
else
|
|
% Fit failed → leave as NaN (skipped automatically)
|
|
continue;
|
|
end
|
|
end
|
|
|
|
% --- Plot using plotMeanWithSE ---
|
|
Plotter.plotMeanWithSE(scan_reference_values, amp2_vals, ...
|
|
'Title', options.titleString, ...
|
|
'XLabel', '\alpha (degrees)', ...
|
|
'YLabel', 'Secondary peak amplitude', ...
|
|
'FigNum', 7, ...
|
|
'FontName', options.font, ...
|
|
'FontSize', 16);
|
|
|
|
% --- Plot using plotMeanWithSE ---
|
|
Plotter.plotMeanWithSE(scan_reference_values, mu2_vals, ...
|
|
'Title', options.titleString, ...
|
|
'XLabel', '\alpha (degrees)', ...
|
|
'YLabel', 'Secondary peak position (\theta, rad)', ...
|
|
'FigNum', 8, ...
|
|
'FontName', options.font, ...
|
|
'FontSize', 16);
|
|
|
|
Plotter.plotMeanWithSE(scan_reference_values, sigma2_vals, ...
|
|
'Title', options.titleString, ...
|
|
'XLabel', '\alpha (degrees)', ...
|
|
'YLabel', 'Secondary peak width (\sigma, rad)', ...
|
|
'FigNum', 9, ...
|
|
'FontName', options.font, ...
|
|
'FontSize', 16);
|
|
|
|
%% Inspect individual realizations of a single parameter
|
|
|
|
% --- Recenter curves first ---
|
|
results = Analyzer.recenterSpectralCurves( ...
|
|
spectral_analysis_results.S_theta_norm_all, ...
|
|
spectral_analysis_results.theta_vals/pi, ...
|
|
scan_reference_values, ...
|
|
'SearchRange', [0 90]); % degrees
|
|
|
|
% --- Restrict to desired theta range (e.g., 0 to 0.5*pi) ---
|
|
thetaMin = 0; % in units of pi (since you divided by pi)
|
|
thetaMax = 1; % corresponds to pi/2
|
|
|
|
mask = results.x_values >= thetaMin & results.x_values <= thetaMax;
|
|
results.x_values = results.x_values(mask);
|
|
|
|
% --- Apply the same mask to each curve set (1x10 cell, each 60x180) ---
|
|
for i = 1:numel(results.curves)
|
|
results.curves{i} = results.curves{i}(:, mask);
|
|
end
|
|
|
|
% --- Convert selected curve set (e.g., 5th) into 1x60 cell array of 1xN row vectors ---
|
|
paramIdx = 10; % <-- choose which scan point or curve set to analyze
|
|
curves_matrix = results.curves{paramIdx}; % 60xN numeric
|
|
curves_cell = num2cell(curves_matrix, 2); % 1x60 cell array
|
|
curves_cell = cellfun(@(x) x(:).', curves_cell, 'UniformOutput', false); % ensure 1xN row vectors
|
|
|
|
% --- Fit two-Gaussian model to these curves ---
|
|
fitResultsMean = Analyzer.fitTwoGaussianCurves( ...
|
|
curves_cell, ...
|
|
results.x_values*pi, ...
|
|
'MaxTheta', pi/2, ...
|
|
'DeviationLimit', 0.30, ...
|
|
'PositionThreshold', pi/15, ...
|
|
'AmplitudeThreshold', 0.02, ...
|
|
'RecenterCurves', false);
|