%% ===== 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; % 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.extractFullRadialSpectralDistribution(od_imgs, options); %% ------------------ 1. Plot of all Radial Spectral Distribution Curves ------------------ Plotter.plotSpectralCurves( ... spectral_analysis_results.S_k_all, ... spectral_analysis_results.k_rho_vals, ... scan_reference_values, ... % correct scan params 'Title', options.titleString, ... 'XLabel', 'k_\rho', ... 'YLabel', 'S(k_\rho)', ... 'YScale', 'log', ... 'XLim', [min(spectral_analysis_results.k_rho_vals), max(spectral_analysis_results.k_rho_vals)], ... '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. Fit truncated Radial Spectral Distribution Curves ------------------ [fitResults, rawCurves] = Analyzer.fitTwoGaussianCurvesToRadialSpectralDistribution(... spectral_analysis_results.S_k_all, ... % radial spectral curves spectral_analysis_results.k_rho_vals, ... % corresponding k_rho values 'KRhoRange', [0, 3], ... % truncate curves to 0 <= k_rho <= 3 'AmplitudeRange', [0, 0.5], ... % truncate curves to y >= 0 (all amplitudes) 'ResidualThreshold', 0.15, ... % maximum allowed residual 'PositionThreshold', 0.5, ... % minimum separation between peaks 'AmplitudeThreshold', 0.015); % minimum secondary peak fraction %% %{ % --- Function call --- plotTwoGaussianFitsOnRaw(fitResults, rawCurves, 8, 12); % 8×12 subplots per page % --- Function definition --- function plotTwoGaussianFitsOnRaw(fitResults, rawCurves, nRows, nCols) %% plotTwoGaussianFitsOnRaw % Plots raw radial spectral curves with their two-Gaussian fits. % % Inputs: % fitResults - struct array from fitTwoGaussianCurvesToRadialSpectralDistribution % rawCurves - struct array with fields: % .x - raw normalized amplitudes % .k - corresponding k_rho values % nRows - number of subplot rows per page (default: 8) % nCols - number of subplot columns per page (default: 12) if nargin < 3, nRows = 8; end if nargin < 4, nCols = 12; end Ncurves = numel(rawCurves); plotsPerPage = nRows * nCols; pageNum = 1; for k = 1:Ncurves % --- Create new figure page if needed --- if mod(k-1, plotsPerPage) == 0 figure('Name', sprintf('Radial Spectra Page %d', pageNum), ... 'NumberTitle', 'off', 'Color', 'w', ... 'Position', [50 50 1600 900]); pageNum = pageNum + 1; end % --- Subplot selection --- subplot(nRows, nCols, mod(k-1, plotsPerPage) + 1); hold on; grid on; box on; % --- Plot raw curve --- if isfield(rawCurves, 'x') && isfield(rawCurves, 'k') && ... ~isempty(rawCurves(k).x) && all(isfinite(rawCurves(k).x)) plot(rawCurves(k).k, rawCurves(k).x, 'k.-', ... 'LineWidth', 1, 'DisplayName', 'Raw data'); end % --- Overlay fit if valid --- if k <= numel(fitResults) fit = fitResults(k); if isfield(fit, 'isValid') && fit.isValid && ... isfield(fit, 'kFine') && isfield(fit, 'yFit') && ... ~isempty(fit.kFine) && all(isfinite(fit.yFit)) plot(fit.kFine, fit.yFit, 'r-', ... 'LineWidth', 1.2, 'DisplayName', 'Two-Gaussian fit'); end end % --- Labels and title --- xlabel('k_\rho', 'FontSize', 10); ylabel('Normalized amplitude', 'FontSize', 10); title(sprintf('Curve %d', k), 'FontSize', 9, 'Interpreter', 'none'); % --- Legend on first subplot of each page --- if mod(k-1, plotsPerPage) == 0 legend('Location', 'best', 'FontSize', 8); end hold off; end end %} %% ------------------ 3. 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)], ... 'YLim', [0, 0.06]); %% ------------------ 4. 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)], ... 'YLim', [1, 2]); %% ------------------ 5. 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)], ... 'YLim', [0, 1.5]); %% ------------------ 6. Plot secondary Gaussian range ------------------ Plotter.plotSecondaryGaussianRange(fitResults, scan_reference_values, ... 'Title', options.titleString, ... 'XLabel', '\alpha (degrees)', ... 'YLabel', '\mu_2 \pm \sigma_2 (rad)', ... 'FontName', options.font, ... 'FontSize', 16, ... 'FigNum', 8, ... 'NumberOfBins', 20, ... 'NormalizeHistogram', true, ... 'Colormap', @Colormaps.coolwarm, ... 'OverlayMeanSEM', true);