Added fit models for fitting ToF images of BEC to extract atom number and temperature (needs bugfixes) and added details of authorship, description (needs additions and corrections).

This commit is contained in:
Karthik 2025-09-12 19:47:37 +02:00
parent b6a49ff0f7
commit ad048ac2ef
51 changed files with 1500 additions and 291 deletions

View File

@ -1,5 +1,13 @@
function results = analyzeAutocorrelation(autocorrresults)
%% Computes features from g2(theta) curves and aggregates results.
%% analyzeAutocorrelation
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Computes features from g2(theta) curves and aggregates results.
%
% Notes:
% Assumes theta_values are given in radians.
feature_list = table();

View File

@ -1,5 +1,11 @@
function results = conductPCA(od_imgs)
%% computePCAfromImages: Performs PCA on optical density images and returns results in a struct
%% computePCAfromImages
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Performs PCA on optical density images and returns results in a struct.
%
% Inputs:
% od_imgs - cell array of OD images
@ -10,6 +16,9 @@ function results = conductPCA(od_imgs)
% .score - PCA scores for each image
% .explained - variance explained by each PC
% .Nx, .Ny - dimensions of individual images
%
% Notes:
% Optional notes, references.
allImgs3D = cat(3, od_imgs{:});
[Nx, Ny] = size(allImgs3D(:,:,1));

View File

@ -1,8 +1,13 @@
function results = conductSpectralAnalysis(od_imgs, scan_parameter_values, options)
%% Performs Fourier analysis on a set of optical density (OD) images.
% Computes radial and angular spectral distributions, optionally plots
% results, and saves figures.
%% conductSpectralAnalysis
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Performs Fourier analysis on a set of optical density (OD) images.
% Computes radial and angular spectral distributions, optionally plots
% results, and saves figures.
%
% Inputs:
% od_imgs - cell array of OD images
@ -32,6 +37,9 @@ function results = conductSpectralAnalysis(od_imgs, scan_parameter_values, optio
% results - struct containing spectra and analysis results
% Figures (if enabled) are saved into:
% [saveDirectory]/Results/SpectralAnalysisSavedFigures/
%
% Notes:
% Optional notes, references.
%% ===== Unpack struct arguments =====
pixel_size = options.pixel_size;

View File

@ -1,29 +1,37 @@
function [patchProps, patchCentroidsGlobal, imgCropped, xStart, yStart] = detectPatches(img, params)
% detectPatches
%% detectPatches
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Detect lattice patches (blobs/stripes) in a single OD image.
% Performs background subtraction, cloud segmentation, cropping,
% denoising, Difference-of-Gaussians filtering, patch detection, and plotting.
%
% INPUTS:
% img - 2D OD image (double or converted internally)
% params - struct of user-tunable parameters:
% backgroundDiskFraction - fraction of image size for morphological opening
% boundingBoxPadding - pixels of padding around cloud bounding box
% dogGaussianSmallSigma - sigma for small Gaussian in DoG
% dogGaussianLargeSigma - sigma for large Gaussian in DoG
% minPeakProminence - min DoG response for thresholding
% minPeakFraction - fraction of max DoG response for adaptive threshold
% subpixelWindowRadius - radius for potential subpixel refinement (not used here)
% minimumPatchArea - minimum patch area to keep
% pixelSize - meters/pixel
% magnification - imaging system magnification
% hAx - axes handle for plotting
% Inputs:
% img - 2D OD image (double or converted internally)
% params - struct of user-tunable parameters:
% backgroundDiskFraction - fraction of image size for morphological opening
% boundingBoxPadding - pixels of padding around cloud bounding box
% dogGaussianSmallSigma - sigma for small Gaussian in DoG
% dogGaussianLargeSigma - sigma for large Gaussian in DoG
% minPeakProminence - min DoG response for thresholding
% minPeakFraction - fraction of max DoG response for adaptive threshold
% subpixelWindowRadius - radius for potential subpixel refinement (not used here)
% minimumPatchArea - minimum patch area to keep
% pixelSize - meters/pixel
% magnification - imaging system magnification
% hAx - axes handle for plotting
%
% OUTPUTS:
% patchProps - struct array of detected patches
% patchCentroidsGlobal - Nx2 array of patch centroids in image coordinates
% imgCropped - cropped, background-subtracted image used for detection
% xAxis, yAxis - physical axes in microns
% Outputs:
% patchProps - struct array of detected patches
% patchCentroidsGlobal - Nx2 array of patch centroids in image coordinates
% imgCropped - cropped, background-subtracted image used for detection
% xAxis, yAxis - physical axes in microns
%
% Notes:
% Optional notes, references.
if ~isa(img,'double')
img = im2double(img);

View File

@ -1,18 +1,26 @@
function objective = evaluateFeatureDetectionPipeline(x, img, gtMask, params, doPlot)
% evaluateFeatureDetectionPipeline
%% evaluateFeatureDetectionPipeline
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Objective wrapper for Bayesian optimization.
% Runs the detection + shape extraction pipeline for a candidate
% parameter set and returns a score relative to ground truth.
%
% INPUTS:
% Inputs:
% x - struct or table from bayesopt with tunable params
% img - 2D image (double or uint)
% gtMask - logical mask of ground truth region(s)
% params - base parameter struct (fixed params)
% doPlot - optional boolean flag to display results (default=false)
%
% OUTPUT:
% Output:
% objective - scalar (to be MINIMIZED by bayesopt)
%
% Notes:
% Optional notes, references.
if nargin < 5
doPlot = false;

View File

@ -1,10 +1,15 @@
function results = extractAndClassifyShapes(imgCropped, patchProps, xStart, yStart, params)
% extractAndClassifyShapes
%% extractAndClassifyShapes
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Extracts internal shapes inside DoG-detected patches using intensity
% thresholding, optional multi-scale DoG fusion, and Canny edge detection.
% This function is robust to irregular shapes, filaments, and Y-shaped structures.
%
% INPUTS:
% Inputs:
% imgCropped - cropped image (DoG input)
% patchProps - struct array from detectPatchesDoG containing patch info
% xStart, yStart- offsets of the cropped region relative to full image
@ -18,13 +23,16 @@ function results = extractAndClassifyShapes(imgCropped, patchProps, xStart, ySta
% edgeThresholdLow - low threshold fraction for Canny
% edgeThresholdHigh - high threshold fraction for Canny
%
% OUTPUTS:
% Outputs:
% results - struct array with fields:
% BW - binary mask of detected shapes (local to cropped ROI)
% labels - labeled mask of shapes
% props - regionprops with classification
% skeletons - skeletons of shapes (if enabled)
% boundaries - global boundaries in full image coordinates
%
% Notes:
% Optional notes, references.
%% --- Return empty if no patches detected ---
if isempty(patchProps)

View File

@ -1,7 +1,15 @@
function results = extractAutocorrelation(theta_values, angular_spectral_distribution, scan_parameter_values, N_shots, N_angular_bins)
%% Extract g² (autocorrelation)
% Computes angular autocorrelation g² for a set of angular spectral distribution.
% Returns all g2 curves grouped by unique scan parameter, mean, error
%% extractAutocorrelation
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Computes angular autocorrelation g² for a set of angular spectral distribution.
% Returns all g2 curves grouped by unique scan parameter, mean, error
%
% Notes:
% Optional notes, references.
% ===== Convert spectral distributions to matrix =====
delta_nkr_all = zeros(N_shots, N_angular_bins);

View File

@ -1,6 +1,15 @@
function results = extractCustomCorrelation(angular_spectral_distribution, scan_parameter_values, N_shots, N_angular_bins)
%% Extracts correlation of a single (highest) peak with possible secondary peak (50-70°)
% Computes correlations and cumulants grouped by unique scan parameter.
%% extractCustomCorrelation
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Extracts correlation of a single (highest) peak with possible secondary peak (50-70°)
% Computes correlations and cumulants grouped by unique scan parameter.
%
% Notes:
% Optional notes, references.
% ===== Convert spectral distributions to matrix =====
delta_nkr_all = zeros(N_shots, N_angular_bins);

View File

@ -1,4 +1,15 @@
function [results, scan_parameter_values, scan_reference_values] = performAnalysis(options)
%% performAnalysis
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Brief description of the script functionality.
%
% Notes:
% Optional notes, references.
arguments
options.scan_parameter (1,:) char
options.ignore_scan_parameter {mustBeText} = ''

View File

@ -1,6 +1,15 @@
function runInteractiveFeatureDetectorGUI(od_imgs, scan_parameter_values, file_list, options, params)
% Interactive OD image viewer with patch detection
% Supports slider, arrow keys, editable parameters, and displays scan parameter
%% runInteractiveFeatureDetectorGUI
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Interactive OD image viewer with patch detection
% Supports slider, arrow keys, editable parameters, and displays scan parameter
%
% Notes:
% Optional notes, references.
numImages = numel(od_imgs);
currentFrame = 1;
@ -225,25 +234,39 @@ function runInteractiveFeatureDetectorGUI(od_imgs, scan_parameter_values, file_l
'HorizontalAlignment', 'right', ...
'VerticalAlignment', 'top');
% --- Display scan parameter ---
if ~isempty(scan_parameter_values)
val = scan_parameter_values(idxImg);
% Determine units
switch lower(options.scanParameterUnits)
case {'degrees','deg','°'}
unitStr = '^\circ';
interpStr = 'tex';
case {'gauss','g'}
unitStr = ' G';
interpStr = 'none';
otherwise
unitStr = options.scanParameterUnits;
interpStr = 'none';
end
txtHandle.String = sprintf('%g%s', val, unitStr);
txtHandle.Interpreter = interpStr;
%% --- Generalized unit handling ---
% Extract parameter row for this shot
if iscell(scan_parameter_values)
% Multi-parameter scan stored as cell array of row vectors
param_row = scan_parameter_values{idxImg};
else
% Numeric vector / matrix
param_row = scan_parameter_values(idxImg,:);
end
% Wrap single unit string into a cell if needed
if ischar(options.scanParameterUnits) || isstring(options.scanParameterUnits)
unitList = {char(options.scanParameterUnits)};
else
unitList = options.scanParameterUnits; % assume cell array
end
% Ensure units list is long enough
if numel(unitList) < numel(param_row)
unitList(end+1:numel(param_row)) = {''}; % pad with empty units
end
% Build text lines for each parameter
txtLines = cell(1, numel(param_row));
for j = 1:numel(param_row)
[unitSuffix, txtInterpreter] = getUnitInfo(unitList{j});
txtLines{j} = sprintf('%.2f%s', param_row(j), unitSuffix);
end
% Join multiple parameters with newline
txtHandle.String = strjoin(txtLines, '\n');
txtHandle.Interpreter = txtInterpreter; % use last parameter's interpreter
% Update slider value
hSlider.Value = idxImg;
drawnow;
@ -266,3 +289,18 @@ function runInteractiveFeatureDetectorGUI(od_imgs, scan_parameter_values, file_l
end
end
end
%% --- Helper function ---
function [unitSuffix, txtInterpreter] = getUnitInfo(u)
switch lower(u)
case {'degrees','deg','°'}
unitSuffix = '^\circ';
txtInterpreter = 'tex';
case {'gauss','g'}
unitSuffix = ' G';
txtInterpreter = 'none';
otherwise
unitSuffix = '';
txtInterpreter = 'none';
end
end

View File

@ -1,10 +1,22 @@
function runInteractiveODImageViewer(od_imgs, scan_parameter_values, file_list, options)
%% Interactive OD Image Viewer
% od_imgs : cell array of 2D OD images
% scan_parameter_values : array of corresponding scan parameter values
% file_list : cell array of corresponding filenames
% options : struct with fields
% .pixel_size, .magnification, .center, .font, .zoom_size, .scan_parameter
%% runInteractiveFeatureDetectorGUI
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Interactive OD image viewer with patch detection
% Supports slider, arrow keys, editable parameters, and displays scan parameter
%
% Inputs:
% od_imgs : cell array of 2D OD images
% scan_parameter_values : array of corresponding scan parameter values
% file_list : cell array of corresponding filenames
% options : struct with fields
% .pixel_size, .magnification, .center, .font, .zoom_size, .scan_parameter
%
% Notes:
% Optional notes, references.
%% --- Create Figure ---
% Try to find an existing figure by a unique tag

View File

@ -1,4 +1,15 @@
function [theta_vals, S_theta] = computeAngularSpectralDistribution(IMGFFT, kx, ky, k_min, k_max, num_bins, threshold, sigma, windowSize)
%% computeAngularSpectralDistribution
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Brief description of the script functionality.
%
% Notes:
% Optional notes, references.
% Apply threshold to isolate strong peaks
IMGFFT(IMGFFT < threshold) = 0;

View File

@ -1,7 +1,11 @@
function cumulants = computeCumulants(x, maxOrder)
% computeCumulants - compute cumulants up to specified order from data vector x
%% computeCumulants
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Syntax: cumulants = computeCumulants(x, maxOrder)
% Description:
% Compute cumulants up to specified order from data vector x.
%
% Inputs:
% x - 1D numeric vector (may contain NaNs)
@ -9,6 +13,9 @@ function cumulants = computeCumulants(x, maxOrder)
%
% Output:
% cumulants - vector [kappa_1, ..., kappa_maxOrder]
%
% Notes:
% Syntax- cumulants = computeCumulants(x, maxOrder).
if nargin < 2
maxOrder = 6;

View File

@ -1,12 +1,19 @@
function [IMGFFT, IMGPR] = computeFourierTransform(I, skipPreprocessing, skipMasking, skipIntensityThresholding, skipBinarization)
% computeFourierSpectrum - Computes the 2D Fourier power spectrum
% of binarized and enhanced lattice image features, with optional central mask.
%
% Inputs:
% I - Grayscale or RGB image matrix
%
% Output:
% F_mag - 2D Fourier power spectrum (shifted)
%% computeFourierTransform
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Computes the 2D Fourier power spectrum of binarized and enhanced lattice image features, with optional central mask.
% Inputs:
% I - Grayscale or RGB image matrix
%
% Output:
% F_mag - 2D Fourier power spectrum (shifted)
%
% Notes:
% Optional notes, references.
if ~skipPreprocessing
% Preprocessing: Denoise

View File

@ -1,6 +1,14 @@
function contrast = computeRadialSpectralContrast(k_rho_vals, S_k_smoothed, k_min, k_max)
% Computes the ratio of the peak in S_k_smoothed within [k_min, k_max]
% to the value at (or near) k = 0.
%% computeRadialSpectralContrast
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Computes the ratio of the peak in S_k_smoothed within [k_min, k_max] to the value at (or near) k = 0.
%
% Notes:
% Optional notes, references.
% Ensure inputs are column vectors
k_rho_vals = k_rho_vals(:);

View File

@ -1,9 +1,25 @@
function [k_rho_vals, S_radial] = computeRadialSpectralDistribution(IMGFFT, kx, ky, thetamin, thetamax, num_bins)
% IMGFFT : 2D FFT image (fftshifted and cropped)
% kx, ky : 1D physical wavenumber axes [μm¹] matching FFT size
% thetamin : Minimum angle (in radians)
% thetamax : Maximum angle (in radians)
% num_bins : Number of radial bins
%% computeRadialSpectralDistribution
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Computes the ratio of the peak in S_k_smoothed within [k_min, k_max] to the value at (or near) k = 0.
%
% Inputs:
% IMGFFT : 2D FFT image (fftshifted and cropped)
% kx, ky : 1D physical wavenumber axes [μm¹] matching FFT size
% thetamin : Minimum angle (in radians)
% thetamax : Maximum angle (in radians)
% num_bins : Number of radial bins
%
% Outputs:
% k_rho_vals:
% S_radial :
%
% Notes:
% Optional notes, references.
[KX, KY] = meshgrid(kx, ky);
K_rho = sqrt(KX.^2 + KY.^2);

View File

@ -0,0 +1,568 @@
classdef DensityProfileBEC2DModel < handle
%% DensityProfileBEC2DModel
% Author: Jianshun Gao
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% This class provides methods to model, fit, and analyze 2D Bose-Einstein
% condensate (BEC) density profiles, including both condensed (Thomas-Fermi)
% and thermal (polylog) components.
%
% Properties:
% - params: Structure storing parameter values and bounds.
% - fitResult: MATLAB fit object after fitting.
% - gof: Goodness-of-fit structure from the fit.
%
% Methods:
% - cal_cond_frac(X, Y): Compute condensate fraction from fitted profile.
% - return_atom_number(X, Y): Compute total, BEC, and thermal atom numbers.
% - return_temperature(tof, omega): Estimate temperature from thermal cloud width.
%
% Static Methods:
% - ThomasFermi_2d: 2D Thomas-Fermi parabolic profile.
% - polylog: Series approximation of polylogarithm function.
% - polylog2_2d: 2D thermal cloud profile using polylog(2) function.
% - density_profile_BEC_2d: Full 2D density (BEC + thermal), optionally rotated.
% - density_1d: 1D slice of the density profile combining BEC and thermal parts.
%
% Usage:
% obj = DensityProfileBEC2DModel();
% atom_n = obj.return_atom_number(X, Y); % Atom numbers
% cond_frac = obj.cal_cond_frac(X, Y); % Condensate fraction
% T = obj.return_temperature(tof, omega); % Temperature
%
% Notes:
% - All static methods can be called independently without creating an object.
properties
% Conversion factors and default constants
fwhm_factor = 2*sqrt(2*log(2)); % FWHM factor for Gaussian
height_factor = 1/(2*pi); % Height normalization factor
prefix = ''; % Optional parameter prefix
tiny = 1e-15; % Small number to avoid division by zero
params; % Struct for parameter definitions
fitResult; % Result of 2D fit
cond_frac; % Condensate fraction
gof; % Goodness-of-fit structure
atom_n_conv = 144; % Conversion factor for atom number
pre_check = false; % Flag for pre-fit check
post_check = false; % Flag for post-fit check
is_debug = false; % Flag for debug plots
end
methods
function obj = DensityProfileBEC2DModel(prefix)
% Constructor
if nargin > 0
obj.prefix = prefix;
end
obj.set_paramhints_prefix();
end
function set_paramhints_prefix(obj)
% Initialize parameter hints and expressions
obj.params = struct();
% Minimum values
obj.params.([obj.prefix 'amp_bec']).min = 0;
obj.params.([obj.prefix 'amp_th']).min = 0;
obj.params.([obj.prefix 'x0_bec']).min = 0;
obj.params.([obj.prefix 'y0_bec']).min = 0;
obj.params.([obj.prefix 'x0_th']).min = 0;
obj.params.([obj.prefix 'y0_th']).min = 0;
obj.params.([obj.prefix 'sigmax_bec']).min = 0;
obj.params.([obj.prefix 'sigmay_bec']).min = 0;
obj.params.([obj.prefix 'sigma_th']).min = 0;
obj.params.([obj.prefix 'rot_angle']).min = -90;
obj.params.([obj.prefix 'rot_angle']).max = 90;
% Expressions for derived parameters
obj.params.([obj.prefix 'atom_number_bec']).expr = ...
[obj.prefix 'amp_bec / 5 * 2 * pi * ' obj.prefix 'sigmax_bec * ' obj.prefix 'sigmay_bec'];
obj.params.([obj.prefix 'atom_number_th']).expr = ...
[obj.prefix 'amp_th * 2 * pi * 1.20206 / 1.643 * ' obj.prefix 'sigma_th * ' obj.prefix 'sigma_th'];
obj.params.([obj.prefix 'condensate_fraction']).expr = ...
[obj.prefix 'atom_number_bec / (' obj.prefix 'atom_number_bec + ' obj.prefix 'atom_number_th)'];
end
function params = guess(obj, data, x, y, varargin)
% Estimate initial parameters for BEC + thermal cloud fit.
% Performs 1D slicing along the shorter axis of the image and initial amplitude guesses.
p = inputParser;
addParameter(p, 'negative', false);
addParameter(p, 'pureBECThreshold', 0.5);
addParameter(p, 'noBECThThreshold', 0.0);
addParameter(p, 'rot_angle', 0);
addParameter(p, 'vary_rot', false);
addParameter(p, 'is_debug', false);
addParameter(p, 'pre_check', false);
addParameter(p, 'post_check', false);
parse(p, varargin{:});
obj.is_debug = p.Results.is_debug;
obj.pre_check = p.Results.pre_check;
obj.post_check = p.Results.post_check;
x_width = length(unique(x));
y_width = length(unique(y));
x_1d = linspace(x(1), x(end), x_width);
y_1d = linspace(y(1), y(end), y_width);
data_2d = reshape(data, y_width, x_width)';
% Rotate image if needed
rot_angle = p.Results.rot_angle;
if rot_angle ~= 0
data_2d = imrotate(data_2d, rot_angle, 'bilinear', 'crop');
end
% Debug plot of input data
if obj.is_debug
figure;
imagesc(x_1d, y_1d, data_2d');
axis equal tight;
colorbar;
colormap('jet');
title('Input Data');
xlabel('x-axis');
ylabel('y-axis');
end
% Binarize and locate BEC
thresh = obj.calc_thresh(data_2d, 0.5);
center_pix = obj.calc_cen_pix(thresh);
center = obj.center_pix_conv(center_pix, x_1d, y_1d);
BEC_width_guess = obj.guess_BEC_width(thresh, center_pix);
if obj.is_debug
figure;
imagesc(x_1d, y_1d, thresh');
hold on;
plot(center(1), center(2), 'gx', 'MarkerSize', 25, 'LineWidth', 2);
axis equal tight;
colorbar;
colormap('jet');
title(sprintf('Binarized Image (BEC Width: x=%.0f, y=%.0f pixels)', BEC_width_guess(1), BEC_width_guess(2)));
xlabel('x-axis');
ylabel('y-axis');
end
% 1D slicing along the shorter axis
if BEC_width_guess(1) < BEC_width_guess(2)
s_width_ind = 1;
x_fit = x_1d;
slice_range = round(center_pix(2) - BEC_width_guess(2)/2) : round(center_pix(2) + BEC_width_guess(2)/2);
X_guess = sum(data_2d(:, slice_range), 2) / length(slice_range);
else
s_width_ind = 2;
x_fit = y_1d;
slice_range = round(center_pix(1) - BEC_width_guess(1)/2) : round(center_pix(1) + BEC_width_guess(1)/2);
X_guess = sum(data_2d(slice_range, :), 1) / length(slice_range);
end
max_val = max(X_guess);
% Construct initial parameter struct
params_1d = struct();
params_1d.x0_bec.value = center(s_width_ind);
params_1d.x0_bec.min = center(s_width_ind) - 10;
params_1d.x0_bec.max = center(s_width_ind) + 10;
params_1d.x0_th.value = center(s_width_ind);
params_1d.x0_th.min = center(s_width_ind) - 10;
params_1d.x0_th.max = center(s_width_ind) + 10;
params_1d.amp_bec.value = 0.5 * max_val;
params_1d.amp_bec.min = 0;
params_1d.amp_bec.max = 1.3 * max_val;
params_1d.amp_th.value = 0.5 * max_val;
params_1d.amp_th.min = 0;
params_1d.amp_th.max = 1.3 * max_val;
params_1d.sigma_bec.value = BEC_width_guess(s_width_ind) / 1.22;
params_1d.sigma_bec.min = 0;
params_1d.sigma_bec.max = 2 * BEC_width_guess(s_width_ind);
params_1d.sigma_th.value = 0.632 * params_1d.sigma_bec.value + 0.518 * 3 * BEC_width_guess(s_width_ind);
params_1d.sigma_th.min = 0;
params_1d.sigma_th.max = 3 * (0.632 * params_1d.sigma_bec.value + 0.518 * 3 * BEC_width_guess(s_width_ind));
% Perform 1D bimodal fit
[fitResult_1d, gof_1d] = fit_1d_bimodal(x_fit, X_guess, params_1d);
% Extract fit coefficients
bval_1d = coeffvalues(fitResult_1d);
paramNames_1d = coeffnames(fitResult_1d);
for i = 1:length(paramNames_1d)
bval_1d_struct.(paramNames_1d{i}) = bval_1d(i);
end
if obj.is_debug
disp('Initial 1D fit parameters:');
disp(bval_1d);
figure;
plot(x_fit, X_guess, 'b-', 'LineWidth', 2);
hold on;
plot(x_fit, obj.density_1d(x_fit, bval_1d.x0_bec, bval_1d.x0_th, ...
bval_1d.amp_bec, bval_1d.amp_th, bval_1d.sigma_bec, bval_1d.sigma_th), 'r-', 'LineWidth', 2);
legend('Data', 'Fit');
if s_width_ind == 1
xlabel('x-axis'); title('1D Fit along x-axis');
else
xlabel('y-axis'); title('1D Fit along y-axis');
end
ylabel('Intensity');
end
% Final parameter preparation (pre_check logic omitted for brevity)
params = params_1d;
obj.params = params;
end
function [fitResult, gof] = fit(obj, data, x, y, varargin)
% Perform 2D nonlinear least squares fit for BEC + thermal cloud.
% Optionally includes rotation of the cloud profile.
data = double(data);
figure
imagesc(data);
axis equal tight;
colorbar;
colormap('jet');
if isempty(obj.params)
obj.guess(data, x, y, varargin{:});
end
% Prepare grid and data
[X, Y] = meshgrid(x, y);
xyData = [X(:), Y(:)];
zData = double(data(:));
% Create fit options and fittype
options = fitoptions('Method', 'NonlinearLeastSquares');
if obj.params.([obj.prefix 'rot_angle']).vary
% Include rotation parameter
paramOrder = {[obj.prefix 'amp_bec'], [obj.prefix 'amp_th'], ...
[obj.prefix 'x0_bec'], [obj.prefix 'y0_bec'], ...
[obj.prefix 'x0_th'], [obj.prefix 'y0_th'], ...
[obj.prefix 'sigmax_bec'], [obj.prefix 'sigmay_bec'], ...
[obj.prefix 'sigma_th'], [obj.prefix 'rot_angle']};
% Start point, lower and upper bounds
startPoint = zeros(1, length(paramOrder));
lowerBounds = zeros(1, length(paramOrder));
upperBounds = zeros(1, length(paramOrder));
for i = 1:length(paramOrder)
paramName = paramOrder{i};
startPoint(i) = obj.params.(paramName).value;
lowerBounds(i) = obj.params.(paramName).min;
upperBounds(i) = obj.params.(paramName).max;
end
options.StartPoint = startPoint;
options.Lower = lowerBounds;
options.Upper = upperBounds;
ft = fittype(@(amp_bec, amp_th, x0_bec, y0_bec, x0_th, y0_th, ...
sigmax_bec, sigmay_bec, sigma_th, rot_angle, x, y) ...
obj.density_profile_BEC_2d(x, y, amp_bec, amp_th, x0_bec, y0_bec, ...
x0_th, y0_th, sigmax_bec, sigmay_bec, sigma_th, rot_angle), ...
'independent', {'x', 'y'}, 'dependent', 'z');
else
% No rotation
paramOrder = {[obj.prefix 'amp_bec'], [obj.prefix 'amp_th'], ...
[obj.prefix 'x0_bec'], [obj.prefix 'y0_bec'], ...
[obj.prefix 'x0_th'], [obj.prefix 'y0_th'], ...
[obj.prefix 'sigmax_bec'], [obj.prefix 'sigmay_bec'], ...
[obj.prefix 'sigma_th']};
startPoint = zeros(1, length(paramOrder));
lowerBounds = zeros(1, length(paramOrder));
upperBounds = zeros(1, length(paramOrder));
for i = 1:length(paramOrder)
paramName = paramOrder{i};
startPoint(i) = obj.params.(paramName).value;
lowerBounds(i) = obj.params.(paramName).min;
upperBounds(i) = obj.params.(paramName).max;
end
options.StartPoint = startPoint;
options.Lower = lowerBounds;
options.Upper = upperBounds;
ft = fittype(@(amp_bec, amp_th, x0_bec, y0_bec, x0_th, y0_th, ...
sigmax_bec, sigmay_bec, sigma_th, x, y) ...
obj.density_profile_BEC_2d(x, y, amp_bec, amp_th, x0_bec, y0_bec, ...
x0_th, y0_th, sigmax_bec, sigmay_bec, sigma_th, 0), ...
'independent', {'x', 'y'}, 'dependent', 'z');
end
[obj.fitResult, obj.gof] = fit(xyData, zData, ft, options);
fitResult = obj.fitResult;
gof = obj.gof;
% Compute condensate fraction
obj.cond_frac = obj.cal_cond_frac(X, Y);
end
function thresh = calc_thresh(obj, data, thresh_val, sigma)
% Binarize image for BEC detection
if nargin < 3, thresh_val = 0.3; end
if nargin < 4, sigma = 0.4; end
blurred = imgaussfilt(data, sigma);
thresh = blurred < max(blurred(:)) * thresh_val;
thresh = double(~thresh);
end
function center_pix = calc_cen_pix(obj, thresh)
% Compute center of binarized image
[X, Y] = size(thresh);
thresh = thresh / sum(thresh(:));
dx = sum(thresh, 2);
dy = sum(thresh, 1);
center_pix = [sum(dx .* (1:X)'), sum(dy .* (1:Y))];
end
function center = center_pix_conv(obj, center_pix, x, y)
% Convert pixel indices to coordinate values
center = [x(round(center_pix(1))), y(round(center_pix(2)))];
end
function BEC_width_guess = guess_BEC_width(obj, thresh, center)
% Estimate BEC width along x and y
[X, Y] = size(thresh);
BEC_width_guess = [sum(thresh(:, round(center(2)))), sum(thresh(round(center(1)), :))];
BEC_width_guess(BEC_width_guess<=0) = 1;
end
function cond_frac = cal_cond_frac(obj, X, Y)
% Compute condensate fraction from fitted BEC + thermal cloud profile
bval = coeffvalues(obj.fitResult);
paramNames = coeffnames(obj.fitResult);
% Extract fit parameters
for i = 1:length(paramNames)
eval([paramNames{i} ' = bval(i);']);
end
if ~obj.params.([obj.prefix 'rot_angle']).vary
rot_angle = 0;
end
% Thomas-Fermi fit for condensate
tf_fit = obj.ThomasFermi_2d(X, Y, x0_bec, y0_bec, amp_bec, sigmax_bec, sigmay_bec);
% Total density profile (BEC + thermal cloud)
fit_total = obj.density_profile_BEC_2d(X, Y, amp_bec, amp_th, x0_bec, y0_bec, ...
x0_th, y0_th, sigmax_bec, sigmay_bec, sigma_th, rot_angle);
N_bec = sum(tf_fit(:));
N_ges = sum(fit_total(:));
cond_frac = N_bec / N_ges;
end
function atom_n = return_atom_number(obj, X, Y, is_print)
% Compute total number of atoms, BEC atoms, thermal atoms, and condensate fraction
if nargin < 4
is_print = true;
end
bval = coeffvalues(obj.fitResult);
paramNames = coeffnames(obj.fitResult);
% Extract fit parameters
for i = 1:length(paramNames)
eval([paramNames{i} ' = bval(i);']);
end
tf_fit = obj.ThomasFermi_2d(X, Y, x0_bec, y0_bec, amp_bec, sigmax_bec, sigmay_bec);
th_fit = obj.polylog2_2d(X, Y, x0_th, y0_th, amp_th, sigma_th, sigma_th);
N_bec = obj.atom_n_conv * sum(tf_fit(:));
N_th = obj.atom_n_conv * sum(th_fit(:));
N = N_bec + N_th;
frac = N_bec / N;
if is_print
fprintf('\nAtom numbers:\n');
fprintf(' N_bec: %.0f\n', N_bec);
fprintf(' N_th: %.0f\n', N_th);
fprintf(' N_total: %.0f\n', N);
fprintf(' Condensate fraction: %.2f %%\n', frac * 100);
end
atom_n = struct('N', N, 'N_bec', N_bec, 'N_th', N_th, 'cond_f', frac);
end
function T = return_temperature(obj, tof, omg, is_print, eff_pix)
% Compute temperature from thermal cloud width and time-of-flight
if nargin < 3
omg = [];
end
if nargin < 4
is_print = true;
end
if nargin < 5
eff_pix = 2.472e-6;
end
bval = coeffvalues(obj.fitResult);
paramNames = coeffnames(obj.fitResult);
% Extract fit parameters
for i = 1:length(paramNames)
eval([paramNames{i} ' = bval(i);']);
end
R_th = sigma_th * eff_pix * sqrt(2); % Thermal cloud radius
% Physical constants
u = 1.66053906660e-27; % Atomic mass unit [kg]
k = 1.380649e-23; % Boltzmann constant [J/K]
if isempty(omg)
% Free expansion
T = R_th^2 * 164 * u / k / tof^2;
else
% Trap expansion included
T = R_th^2 * 164 * u / k / (1/omg^2 + tof^2);
end
if is_print
fprintf('Temperature: %.2f nK\n', T * 1e9);
end
end
end
methods (Static)
function res = ThomasFermi_2d(x, y, centerx, centery, amplitude, sigmax, sigmay)
% 2D Thomas-Fermi distribution for a BEC (parabolic density profile)
res = (1 - ((x - centerx)/sigmax).^2 - ((y - centery)/sigmay).^2);
res(res < 0) = 0;
res = amplitude * res.^(3/2); % Standard TF 3/2 exponent
end
function res = polylog(power, numerator)
% Approximate polylogarithm function using truncated series
order = 20; % Truncation order
dataShape = size(numerator);
numerator = repmat(numerator(:), 1, order);
numerator = numerator .^ repmat(1:order, prod(dataShape), 1);
denominator = repmat((1:order), prod(dataShape), 1);
data = numerator ./ (denominator .^ power);
res = sum(data, 2);
res = reshape(res, dataShape);
end
function res = polylog2_2d(x, y, centerx, centery, amplitude, sigmax, sigmay)
% 2D thermal cloud distribution using polylog(2)
arg = exp(-((x - centerx).^2 / (2*sigmax^2)) - ((y - centery).^2 / (2*sigmay^2)));
res = amplitude / 1.643 * FitModels.DensityProfileBEC2DModel.polylog(2, arg);
end
function res = density_profile_BEC_2d(x, y, amp_bec, amp_th, x0_bec, y0_bec, ...
x0_th, y0_th, sigmax_bec, sigmay_bec, sigma_th, rot_angle)
% Combined 2D density profile: BEC (Thomas-Fermi) + thermal cloud (polylog)
if nargin < 12
rot_angle = 0;
end
% Rotate coordinates if needed
if rot_angle ~= 0
rot_angle_rad = -rot_angle * pi/180; % Clockwise rotation
% Rotate coordinates
x_rot = x * cos(rot_angle_rad) + y * sin(rot_angle_rad);
y_rot = -x * sin(rot_angle_rad) + y * cos(rot_angle_rad);
% Rotate centers
x0_bec_rot = x0_bec * cos(rot_angle_rad) + y0_bec * sin(rot_angle_rad);
y0_bec_rot = -x0_bec * sin(rot_angle_rad) + y0_bec * cos(rot_angle_rad);
x0_th_rot = x0_th * cos(rot_angle_rad) + y0_th * sin(rot_angle_rad);
y0_th_rot = -x0_th * sin(rot_angle_rad) + y0_th * cos(rot_angle_rad);
x = x_rot;
y = y_rot;
x0_bec = x0_bec_rot;
y0_bec = y0_bec_rot;
x0_th = x0_th_rot;
y0_th = y0_th_rot;
end
% Thomas-Fermi part (BEC)
TF_part = FitModels.DensityProfileBEC2DModel.ThomasFermi_2d(x, y, x0_bec, y0_bec, amp_bec, sigmax_bec, sigmay_bec);
% Polylog thermal part
poly_part = FitModels.DensityProfileBEC2DModel.polylog2_2d(x, y, x0_th, y0_th, amp_th, sigma_th, sigma_th);
% Total density
res = TF_part + poly_part;
end
function res = density_1d(x, x0_bec, x0_th, amp_bec, amp_th, sigma_bec, sigma_th)
% 1D density profile (Thomas-Fermi + thermal polylog)
thermal_part = amp_th / 1.643 * polylog_int(exp(-0.5 * (x - x0_th).^2 / sigma_th^2));
TF_part = amp_bec * (1 - ((x - x0_bec)/sigma_bec).^2);
TF_part(TF_part < 0) = 0;
TF_part = TF_part.^(3/2);
res = thermal_part + TF_part;
end
end
end
function res = polylog_int(x)
x_int = linspace(0, 1.00001, 1000);
poly_tab = zeros(size(x_int));
for i = 1:length(x_int)
poly_tab(i) = sum((x_int(i).^(1:20)) ./ (1:20).^2);
end
res = interp1(x_int, poly_tab, x, 'linear', 'extrap');
end
function [fitResult, gof] = fit_1d_bimodal(x, y, initialParams)
bimodal1d = @(amp_bec, amp_th, x0_bec, x0_th, sigma_bec, sigma_th, x) ...
FitModels.DensityProfileBEC2DModel.density_1d(x, x0_bec, x0_th, amp_bec, amp_th, sigma_bec, sigma_th);
paramNames = {'amp_bec', 'amp_th', 'x0_bec', 'x0_th', 'sigma_bec', 'sigma_th'};
ft = fittype(bimodal1d, 'independent', 'x', 'dependent', 'y');
options = fitoptions(ft);
% paramNames = fieldnames(initialParams);
startPoint = zeros(1, length(paramNames));
lowerBounds = zeros(1, length(paramNames));
upperBounds = zeros(1, length(paramNames));
for i = 1:length(paramNames)
paramName = paramNames{i};
startPoint(i) = initialParams.(paramName).value;
lowerBounds(i) = initialParams.(paramName).min;
upperBounds(i) = initialParams.(paramName).max;
end
options.StartPoint = startPoint;
options.Lower = lowerBounds;
options.Upper = upperBounds;
[fitResult, gof] = fit(x(:), y(:), ft, options);
end

View File

@ -0,0 +1,202 @@
classdef TwoGaussian2DModel < handle
%% TwoGaussian2DModel
% Author: Jianshun Gao
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% This class provides methods to model, fit, and analyze 2D datasets using
% a sum of two Gaussian distributions. It supports:
% - Initial parameter estimation from 2D data.
% - Nonlinear least-squares fitting to extract Gaussian parameters.
% - Access and modification of parameter values and bounds.
%
% Properties:
% - params: Structure storing parameter values and bounds.
% - fitResult: MATLAB fit object after fitting.
% - gof: Goodness-of-fit structure from the fit.
%
% Methods:
% - guess(data, x, y): Estimate initial parameters from 2D data.
% - fit(data, x, y): Fit the two-Gaussian model to data.
% - getParamValue(paramName): Retrieve the current value of a parameter.
% - setParamValue(paramName, value): Update the value of a parameter.
% - setParamBounds(paramName, minVal, maxVal): Set parameter bounds.
%
% Usage:
% obj = TwoGaussian2DModel(); % Create object
% params = obj.guess(data, x, y); % Estimate parameters
% [fitResult, gof] = obj.fit(data, x, y); % Perform fitting
% ampA = obj.getParamValue('A_amplitude'); % Access parameter
% obj.setParamValue('B_sigmax', 5.0); % Modify parameter
% obj.setParamBounds('A_sigmay', 1.0, 10.0); % Set bounds
%
% Notes:
% - All parameter names must match those defined in the params structure.
% - This class is intended for 2D datasets where two Gaussian peaks are present.
properties
params; % Structure storing parameter values, bounds, etc.
fitResult; % MATLAB fit object after fitting
gof; % Goodness-of-fit metrics
end
methods
function obj = TwoGaussian2DModel()
% Constructor (empty)
end
function params = guess(obj, data, x, y, varargin)
% Estimate initial parameters for two Gaussian peaks
% Usage: obj.guess(data, x, y)
% Optional parameter:
% 'negative' - boolean, allow negative amplitude (default: false)
p = inputParser;
addParameter(p, 'negative', false);
parse(p, varargin{:});
% Simple peak estimation
[maxVal, maxIdx] = max(data(:));
[row, col] = ind2sub(size(data), maxIdx);
% Create parameter structure with values, min, and max
params = struct();
% Amplitude parameters
params.A_amplitude.value = maxVal;
params.A_amplitude.min = 0;
params.A_amplitude.max = 2 * maxVal;
params.B_amplitude.value = maxVal / 2;
params.B_amplitude.min = 0;
params.B_amplitude.max = 2 * maxVal;
% Center positions
params.A_centerx.value = x(col);
params.A_centerx.min = min(x);
params.A_centerx.max = max(x);
params.A_centery.value = y(row);
params.A_centery.min = min(y);
params.A_centery.max = max(y);
params.B_centerx.value = x(round(end/2));
params.B_centerx.min = min(x);
params.B_centerx.max = max(x);
params.B_centery.value = y(round(end/2));
params.B_centery.min = min(y);
params.B_centery.max = max(y);
% Standard deviations
sigmax_range = max(x) - min(x);
sigmay_range = max(y) - min(y);
params.A_sigmax.value = sigmax_range / 10;
params.A_sigmax.min = sigmax_range / 100;
params.A_sigmax.max = sigmax_range / 2;
params.A_sigmay.value = sigmay_range / 10;
params.A_sigmay.min = sigmay_range / 100;
params.A_sigmay.max = sigmay_range / 2;
params.B_sigmax.value = sigmax_range / 5;
params.B_sigmax.min = sigmax_range / 100;
params.B_sigmax.max = sigmax_range / 2;
params.B_sigmay.value = sigmay_range / 5;
params.B_sigmay.min = sigmay_range / 100;
params.B_sigmay.max = sigmay_range / 2;
obj.params = params;
end
function [fitResult, gof] = fit(obj, data, x, y, varargin)
% Fit the data to a sum of two 2D Gaussian distributions
% Usage: [fitResult, gof] = obj.fit(data, x, y)
% Optional parameter:
% 'params' - struct with initial guesses and bounds
p = inputParser;
addParameter(p, 'params', []);
parse(p, varargin{:});
if isempty(p.Results.params) && isempty(obj.params)
obj.guess(data, x, y, varargin{:});
elseif ~isempty(p.Results.params)
obj.params = p.Results.params;
end
% Prepare fitting data
[X, Y] = meshgrid(x, y);
xData = X(:);
yData = Y(:);
zData = data(:);
% Define two-Gaussian function
twoGauss = @(A_amplitude, B_amplitude, A_centerx, A_centery, ...
B_centerx, B_centery, A_sigmax, A_sigmay, B_sigmax, B_sigmay, x, y) ...
A_amplitude * exp(-((x-A_centerx).^2/(2*A_sigmax^2) + (y-A_centery).^2/(2*A_sigmay^2))) + ...
B_amplitude * exp(-((x-B_centerx).^2/(2*B_sigmax^2) + (y-B_centery).^2/(2*B_sigmay^2)));
% Create MATLAB fittype
ft = fittype(twoGauss, 'independent', {'x','y'}, 'dependent', 'z');
% Fit options
options = fitoptions(ft);
% Parameter order
paramOrder = {'A_amplitude', 'B_amplitude', 'A_centerx', 'A_centery', ...
'B_centerx', 'B_centery', 'A_sigmax', 'A_sigmay', 'B_sigmax', 'B_sigmay'};
% Build StartPoint, Lower, Upper
startPoint = zeros(1, length(paramOrder));
lowerBounds = zeros(1, length(paramOrder));
upperBounds = zeros(1, length(paramOrder));
for i = 1:length(paramOrder)
paramName = paramOrder{i};
startPoint(i) = obj.params.(paramName).value;
lowerBounds(i) = obj.params.(paramName).min;
upperBounds(i) = obj.params.(paramName).max;
end
options.StartPoint = startPoint;
options.Lower = lowerBounds;
options.Upper = upperBounds;
% Perform the fit
[obj.fitResult, obj.gof] = fit([xData, yData], zData, ft, options);
fitResult = obj.fitResult;
gof = obj.gof;
end
function paramValue = getParamValue(obj, paramName)
% Get the value of a specified parameter
if isfield(obj.params, paramName)
paramValue = obj.params.(paramName).value;
else
error('Parameter %s does not exist', paramName);
end
end
function setParamValue(obj, paramName, value)
% Set the value of a specified parameter
if isfield(obj.params, paramName)
obj.params.(paramName).value = value;
else
error('Parameter %s does not exist', paramName);
end
end
function setParamBounds(obj, paramName, minVal, maxVal)
% Set the bounds of a specified parameter
if isfield(obj.params, paramName)
obj.params.(paramName).min = minVal;
obj.params.(paramName).max = maxVal;
else
error('Parameter %s does not exist', paramName);
end
end
end
end

View File

@ -1,4 +1,15 @@
function results_all = batchAnalyze(dataSources, options)
%% batchAnalyze
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Brief description of the script functionality.
%
% Notes:
% Optional notes, references.
arguments
dataSources (1,:) cell
options struct

View File

@ -1,18 +1,24 @@
function imageOD = calculateODImage(imageAtom, imageBackground, imageDark, mode, exposureTime)
%CALCULATEODIMAGE Calculates the optical density (OD) image for absorption imaging.
%% calculateODImage
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% imageOD = calculateODImage(imageAtom, imageBackground, imageDark, mode, exposureTime)
% Description:
% Calculates the optical density (OD) image for absorption imaging.
%
% Inputs:
% imageAtom - Image with atoms
% imageBackground - Image without atoms
% imageDark - Image without light
% mode - 'LowIntensity' (default) or 'HighIntensity'
% exposureTime - Required only for 'HighIntensity' [in seconds]
% Inputs:
% imageAtom - Image with atoms
% imageBackground - Image without atoms
% imageDark - Image without light
% mode - 'LowIntensity' (default) or 'HighIntensity'
% exposureTime - Required only for 'HighIntensity' [in seconds]
%
% Output:
% imageOD - Computed OD image
% Output:
% imageOD - Computed OD image
%
% Notes:
% Syntax - imageOD = calculateODImage(imageAtom, imageBackground, imageDark, mode, exposureTime)
arguments
imageAtom (:,:) {mustBeNumeric}

View File

@ -1,7 +1,12 @@
function [od_imgs, scan_parameter_values, scan_reference_values, file_list] = collectODImages(options)
%% Applies cropping, background subtraction, and optional fringe removal, optional unshuffling on OD image dataset
% Automatically reuses in-memory full dataset if available;
% otherwise, reads and processes raw HDF5 data.
%% collectODImages
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Applies cropping, background subtraction, and optional fringe removal, optional unshuffling on OD image dataset.
% Automatically reuses in-memory full dataset if available otherwise, reads and processes raw HDF5 data.
%
% Inputs:
% options - structure containing processing options:
@ -20,6 +25,9 @@ function [od_imgs, scan_parameter_values, scan_reference_values, file_list] = co
% od_imgs : cell array of processed OD images
% scan_parameter_values: vector of scan parameter values
% file_list : cell array of file names
%
% Notes:
% Optional notes, references.
% --- Early exit if processed OD images already exist AND options match ---
reuseExistingODImages = evalin('base', ...
@ -254,9 +262,11 @@ function [od_imgs, scan_parameter_values, scan_reference_values, file_list] = co
end
% --- If a folder was determined, load its contents (listing) ---
if isfolder(full_od_image_subfolder) && ~isempty(full_od_image_subfolder) && useFullODFolders
[mat_files, raw_scan_parameter_names, raw_scan_parameter_values, raw_file_list, nFiles] = prepareFromOnDiskData(full_od_image_subfolder);
fprintf('\n[INFO] Cropping and subtracting background from images in full OD images folder on disk...\n');
if ~isempty(full_od_image_subfolder) && useFullODFolders
if isfolder(full_od_image_subfolder)
[mat_files, raw_scan_parameter_names, raw_scan_parameter_values, raw_file_list, nFiles] = prepareFromOnDiskData(full_od_image_subfolder);
fprintf('\n[INFO] Cropping and subtracting background from images in full OD images folder on disk...\n');
end
end
end

View File

@ -1,13 +1,14 @@
function ret = cropODImage(img, center, span)
% Crop the image according to the region of interest (ROI).
% :param dataSet: The images
% :type dataSet: xarray DataArray or DataSet
% :param center: The center of region of interest (ROI)
% :type center: tuple
% :param span: The span of region of interest (ROI)
% :type span: tuple
% :return: The cropped images
% :rtype: xarray DataArray or DataSet
%% cropODImage
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Crop the image according to the region of interest (ROI).
%
% Notes:
% Optional notes, references.
x_start = floor(center(1) - span(1) / 2);
x_end = floor(center(1) + span(1) / 2);

View File

@ -1,36 +1,46 @@
function drawODOverlays(x1, y1, x2, y2)
%% drawODOverlays
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Brief description of the script functionality.
%
% Notes:
% Optional notes, references.
% Parameters
tick_spacing = 10; % µm between ticks
tick_length = 2; % µm tick mark length
line_color = [0.5 0.5 0.5];
tick_color = [0.5 0.5 0.5];
font_size = 10;
n_ticks = 5; % Fixed number of ticks along the diagonal
tick_length = 1; % µm tick mark length
line_color = [0.5 0.5 0.5];
tick_color = [0.5 0.5 0.5];
font_size = 10;
% Vector from start to end
dx = x2 - x1;
dy = y2 - y1;
L = sqrt(dx^2 + dy^2);
dx = x2 - x1;
dy = y2 - y1;
L = sqrt(dx^2 + dy^2);
% Unit direction vector along diagonal
ux = dx / L;
uy = dy / L;
ux = dx / L;
uy = dy / L;
% Perpendicular unit vector for ticks
perp_ux = -uy;
perp_uy = ux;
perp_ux = -uy;
perp_uy = ux;
% Midpoint (center)
xc = (x1 + x2) / 2;
yc = (y1 + y2) / 2;
xc = (x1 + x2) / 2;
yc = (y1 + y2) / 2;
% Number of positive and negative ticks
n_ticks = floor(L / (2 * tick_spacing));
% Dynamic tick spacing
tick_spacing = L / (2 * n_ticks);
% Draw main diagonal line
plot([x1 x2], [y1 y2], '--', 'Color', line_color, 'LineWidth', 1.2);
for i = -n_ticks:n_ticks
for i = -n_ticks+1:n_ticks-1 % exclude endpoints
d = i * tick_spacing;
xt = xc + d * ux;
yt = yc + d * uy;
@ -45,14 +55,13 @@ function drawODOverlays(x1, y1, x2, y2)
plot([xt1 xt2], [yt1 yt2], '--', 'Color', tick_color, 'LineWidth', 1);
% Label: centered at tick, offset slightly along diagonal
if d ~= 0
text(xt, yt, sprintf('%+d', d), ...
if i > -n_ticks && i < n_ticks && i ~= 0
text(xt, yt, sprintf('%+d', round(d)), ...
'Color', tick_color, ...
'FontSize', font_size, ...
'HorizontalAlignment', 'center', ...
'VerticalAlignment', 'bottom', ...
'Rotation', atan2d(dy, dx));
end
end
end
end

View File

@ -1,5 +1,11 @@
function drawPSOverlays(kx, ky, k_min, k_max)
% drawPSOverlays - Draw overlays on existing FFT plot:
%% drawPSOverlays
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Draw overlays on existing FFT plot.
% - Radial lines every 30°
% - Annular highlight with white (upper half) and gray (lower half) circles at k_min and k_max
% - Horizontal white bands at ky=0 between k_min and k_max
@ -9,6 +15,9 @@ function drawPSOverlays(kx, ky, k_min, k_max)
% kx, ky - reciprocal space vectors (μm¹)
% k_min - inner annulus radius (μm¹)
% k_max - outer annulus radius (μm¹)
%
% Notes:
% Optional notes, references.
hold on

View File

@ -1,7 +1,15 @@
function [SAVE_TO_WORKSPACE, runMemoryGB] = estimateDatasetMemory(dataSources, options)
% Estimate per-run memory and decide whether to save dataset to workspace
%% estimateDatasetMemory
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Supports both raw data folders and a preselected run folder.
% Description:
% Estimate per-run memory and decide whether to save dataset to workspace
% Supports both raw data folders and a preselected run folder.
%
% Notes:
% Optional notes, references.
% --- Measured memory per image (bytes) ---
bytesPerFullImage = 37.75 * 1e6; % full OD image

View File

@ -1,4 +1,15 @@
function ret = getBkgOffsetFromCorners(img, x_fraction, y_fraction)
%% getBkgOffsetFromCorners
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Brief description of the script functionality.
%
% Notes:
% Optional notes, references.
% image must be a 2D numerical array
[dim1, dim2] = size(img);

View File

@ -1,5 +1,14 @@
function [full_od_imgs, full_bkg_imgs, raw_scan_parameter_values, raw_file_list, scan_parameter_names, scan_reference_values] = processRawData(options)
%% Reads HDF5 files, computes OD images, supports disk-backed storage in blocks
%% processRawData
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Reads HDF5 files, computes OD images, supports disk-backed storage in blocks.
%
% Notes:
% Optional notes, references.
fprintf('\n[INFO] Processing raw data files at %s ...\n', options.folderPath);

View File

@ -1,43 +1,42 @@
function [optrefimages] = removeFringesInImage(absimages, refimages, bgmask)
% removefringesInImage - Fringe removal and noise reduction from absorption images.
% Creates an optimal reference image for each absorption image in a set as
% a linear combination of reference images, with coefficients chosen to
% minimize the least-squares residuals between each absorption image and
% the optimal reference image. The coefficients are obtained by solving a
% linear set of equations using matrix inverse by LU decomposition.
%
% Application of the algorithm is described in C. F. Ockeloen et al, Improved
% detection of small atom numbers through image processing, arXiv:1007.2136 (2010).
%
% Syntax:
% [optrefimages] = removefringesInImage(absimages,refimages,bgmask);
%
% Required inputs:
% absimages - Absorption image data,
% typically 16 bit grayscale images
% refimages - Raw reference image data
% absimages and refimages are both cell arrays containing
% 2D array data. The number of refimages can differ from the
% number of absimages.
%
% Optional inputs:
% bgmask - Array specifying background region used,
% 1=background, 0=data. Defaults to all ones.
% Outputs:
% optrefimages - Cell array of optimal reference images,
% equal in size to absimages.
%
% Dependencies: none
%
% Authors: Shannon Whitlock, Caspar Ockeloen
% Reference: C. F. Ockeloen, A. F. Tauschinsky, R. J. C. Spreeuw, and
% S. Whitlock, Improved detection of small atom numbers through
% image processing, arXiv:1007.2136
% Email:
% May 2009; Last revision: 11 August 2010
% Process inputs
%% removefringesInImage
% Authors: Shannon Whitlock, Caspar Ockeloen
% Date: May 2009 (Last revision: 11 August 2010)
% Version: Unknown
%
% Description:
% Fringe removal and noise reduction from absorption images.
% Creates an optimal reference image for each absorption image in a set as
% a linear combination of reference images, with coefficients chosen to
% minimize the least-squares residuals between each absorption image and
% the optimal reference image. The coefficients are obtained by solving a
% linear set of equations using matrix inverse by LU decomposition.
%
% Application of the algorithm is described in C. F. Ockeloen et al, Improved
% detection of small atom numbers through image processing, arXiv:1007.2136 (2010).
%
% Inputs:
% REQUIRED:
% absimages - Absorption image data,
% typically 16 bit grayscale images
% refimages - Raw reference image data
% absimages and refimages are both cell arrays containing
% 2D array data. The number of refimages can differ from the
% number of absimages.
%
% OPTIONAL:
% bgmask - Array specifying background region used,
% 1=background, 0=data. Defaults to all ones.
% Outputs:
% optrefimages - Cell array of optimal reference images,
% equal in size to absimages.
%
% Notes:
% Syntax - [optrefimages] = removefringesInImage(absimages,refimages,bgmask);
% Dependencies - none
% Reference - C. F. Ockeloen, A. F. Tauschinsky, R. J. C. Spreeuw, and
% S. Whitlock, Improved detection of small atom numbers through
% image processing, arXiv:1007.2136
% Set variables, and flatten absorption and reference images
nimgs = size(absimages,3);

View File

@ -1,5 +1,11 @@
function [selectedPath, folderPath] = selectDataSourcePath(dataSources, options)
% Helper function to select a run/folder for analysis
%% selectDataSourcePath
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Helper function to select a run/folder for analysis.
%
% Inputs:
% dataSources - cell array of structs with fields: sequence, date, runs
@ -8,7 +14,10 @@ function [selectedPath, folderPath] = selectDataSourcePath(dataSources, options)
% Outputs:
% selectedPath - actual folder to use (raw or FullOD)
% folderPath - constructed path from dataSources (always raw folder)
%
% Notes:
% Optional notes, references.
allPaths = {}; % initialize candidate paths
lookup = struct('rawPath', {}, 'fullODPath', {});

View File

@ -1,13 +1,14 @@
function ret = subtractBackgroundOffset(img, fraction)
% Remove the background from the image.
% :param dataArray: The image
% :type dataArray: xarray DataArray
% :param x_fraction: The fraction of the pixels used in x axis
% :type x_fraction: float
% :param y_fraction: The fraction of the pixels used in y axis
% :type y_fraction: float
% :return: The image after removing background
% :rtype: xarray DataArray
%% subtractBackgroundOffset
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Remove the background from the image.
%
% Notes:
% Optional notes, references.
x_fraction = fraction(1);
y_fraction = fraction(2);

View File

@ -1,5 +1,11 @@
function compareMultipleDatasets(scanValsCell, meanValsCell, stderrValsCell, varargin)
% compareMultipleDatasets compares multiple datasets with error bars.
%% compareMultipleDatasets
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Compares multiple datasets with error bars.
%
% Inputs:
% scanValsCell - cell array of x-values for each dataset
@ -10,6 +16,9 @@ function compareMultipleDatasets(scanValsCell, meanValsCell, stderrValsCell, var
% 'FigNum', 'FontName', 'MarkerSize', 'LineWidth', 'CapSize',
% 'YLim', 'Labels', 'Title', 'XLabel', 'YLabel',
% 'SkipSaveFigures', 'SaveFileName', 'SaveDirectory'
%
% Notes:
% Optional notes, references.
% --- Parse inputs ---
p = inputParser;

View File

@ -1,7 +1,16 @@
function plotAndCompareG2Cumulants(results1, results2, varargin)
%% plotAndCompareG2Cumulants: Compare first four cumulants of g²(θ) for two datasets
%% plotAndCompareG2Cumulants
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Compare first four cumulants of g²(θ) for two datasets.
%
% Inputs:
% results1, results2 : g2_analysis_results objects
%
% Notes:
% Dataset 1 = Solid line
% Dataset 2 = Dashed line
% Marker shape encodes θ value (consistent across datasets)

View File

@ -1,13 +1,21 @@
function plotAndCompareG2Mean(results1, results2, varargin)
%% plotAndCompareG2Mean: Compare first cumulant (mean) of g²(θ) for two datasets
%% plotAndCompareG2Mean
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Compare first cumulant (mean) of g²(θ) for two datasets.
% Plots mean ± standard deviation of g² values at the desired θ
%
% Inputs:
% results1, results2 : g2_analysis_results objects
%
% Notes:
% Dataset 1 = Solid line
% Dataset 2 = Dashed line
% Marker shape encodes θ value (consistent across datasets)
% Dataset colors are distinct
%
% Plots mean ± standard deviation of g² values at the desired θ
% --- Parse name-value pairs ---
p = inputParser;

View File

@ -1,5 +1,11 @@
function plotAverageSpectra(scan_parameter_values, spectral_analysis_results, varargin)
%% plotAverageSpectra: Plot averaged power, radial, and angular spectra for a scan
%% plotAverageSpectra
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Plot averaged power, radial, and angular spectra for a scan
%
% Inputs:
% scan_parameter_values - array of scan parameter values
@ -9,6 +15,12 @@ function plotAverageSpectra(scan_parameter_values, spectral_analysis_results, va
% Name-Value Pair Arguments:
% 'ScanParameterName', 'FigNum', 'ColormapPS', 'Font',
% 'SaveFileName', 'SaveDirectory', 'SkipSaveFigures'
%
% Notes:
% Dataset 1 = Solid line
% Dataset 2 = Dashed line
% Marker shape encodes θ value (consistent across datasets)
% Dataset colors are distinct
% --- Extract data from struct ---
kx = spectral_analysis_results.kx;

View File

@ -1,16 +1,18 @@
function plotCumulants(scan_vals, cumulant_data, varargin)
%% plotCumulants: Plots the first four cumulants vs. a scan parameter
%% plotCumulants
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% plotCumulants(scan_vals, {mean_vals, var_vals, skew_vals, fourth_order_vals}, ...
% 'Title', 'My Title', ...
% 'FigNum', 1, ...
% 'FontName', 'Arial', ...
% 'MarkerSize', 6, ...
% 'LineWidth', 1.5, ...
% 'SkipSaveFigures', false, ...
% 'SaveFileName', 'cumulants.fig', ...
% 'SaveDirectory', pwd);
% Description:
% Plots the first four cumulants vs. a scan parameter
%
% Inputs:
% scan_vals - array of scan parameter values
% cumulant_data - cell array of cumulants:
%
% Notes:
% Optional notes, references.
% --- Parse optional name-value pairs ---
p = inputParser;

View File

@ -1,15 +1,23 @@
function plotDetectedPatches(img, patchProps, results, params, xStart, yStart, figTitle)
% plotDetectedPatches
%% plotDetectedPatches
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Plots the image, DoG-detected patch ellipses, and extracted shape boundaries
% with optional text overlay for Dice score and patch count.
%
% INPUTS:
% Inputs:
% img - original 2D image
% patchProps - struct array from detectPatches
% results - struct array from extractAndClassifyShapes
% params - parameter struct
% xStart, yStart - offsets for cropped regions
% figTitle - title string (e.g., 'BayesOpt Candidate')
%
% Notes:
% Optional notes, references.
if nargin < 7
figTitle = '';

View File

@ -1,5 +1,22 @@
function plotG2Cumulants(results, varargin)
%% plotG2Cumulants: Plot first four cumulants of g²(θ) vs scan parameter
%% plotG2Cumulants
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Plot first four cumulants of g²(θ) vs scan parameter
%
% Inputs:
% img - original 2D image
% patchProps - struct array from detectPatches
% results - struct array from extractAndClassifyShapes
% params - parameter struct
% xStart, yStart - offsets for cropped regions
% figTitle - title string (e.g., 'BayesOpt Candidate')
%
% Notes:
% Optional notes, references.
% --- Parse name-value pairs ---
p = inputParser;

View File

@ -1,12 +1,11 @@
function plotG2Curves(results, varargin)
%% plotG2Curves: Plot raw g²(θ) curves with mean, SEM, and highlights
%% plotG2Curves
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% plotG2Curves(results, ...
% 'Title','g² Curves','XLabel','\theta / \pi','YLabel','g^2(\theta)', ...
% 'FontName','Arial','FontSize',14,'FigNum',1,'TileTitlePrefix','Control Parameter', ...
% 'TileTitleSuffix','°','HighlightEvery',10,'SkipSaveFigures',false, ...
% 'SaveFileName','G2Curves.fig','SaveDirectory','results');
% Description:
% Plot raw g²(θ) curves with mean, SEM, and highlights
%
% Inputs:
% results - struct with fields:
@ -15,6 +14,9 @@ function plotG2Curves(results, varargin)
% g2_mean - [N_params × Nθ] mean
% g2_error - [N_params × Nθ] SEM
% scan_parameter_values- vector of scan parameters
%
% Notes:
% Optional notes, references.
% --- Parse name-value pairs ---
p = inputParser;

View File

@ -1,13 +1,14 @@
function plotG2CurvesMultiParam(results, scan_parameter_values, scan_reference_values, param1ValuesToPlot, param2ValuesToPlot, varargin)
%% plotG2CurvesMultiParam: Plot g²(θ) curves for selected param1 and param2 values in a phase diagram
%% plotG2CurvesMultiParam
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% plotG2CurvesMultiParam(results, scan_parameter_values, scan_reference_values, ...
% param1ValuesToPlot, param2ValuesToPlot, ...
% 'Title','g² Curves','FontName','Arial','FontSize',14,'FigNum',1, ...
% 'Param1Name','BField','Param2Name','Alpha', ...
% 'HighlightEvery',10,'SkipSaveFigures',false, ...
% 'SaveFileName','G2CurvesPhaseDiagram.fig','SaveDirectory','results');
% Description:
% Plot g²(θ) curves for selected param1 and param2 values in a phase diagram
%
% Notes:
% Optional notes, references.
% --- Parse name-value pairs ---
p = inputParser;

View File

@ -1,8 +1,14 @@
function plotG2Features(results, varargin)
%% plotG2Features: Plot Fourier amplitudes, contrast, and symmetry fractions
%% plotG2Features
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% plotG2Features(results, 'Title','Analysis Results','XLabel','Scan Parameter', ...)
% Description:
% Plot Fourier amplitudes, contrast, and symmetry fractions.
%
% Notes:
% Optional notes, references.
% --- Parse name-value pairs ---
p = inputParser;

View File

@ -1,11 +1,14 @@
function plotG2MeanCurves(g2_mean_all, g2_error_all, theta_values, scan_parameter_values, scan_parameter_units, varargin)
%% plotG2: Plots g2 angular correlations with optional parameters
%% plotG2MeanCurves
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% plotG2(g2_mean_all, g2_error_all, theta_values, unique_scan_parameter_values, scan_parameter, ...
% 'Title', 'My Title', 'XLabel', 'B (G)', 'YLabel', '$g^{(2)}$', ...
% 'FigNum', 1, 'FontName', 'Arial', 'Colormap', @Colormaps.coolwarm, ...
% 'SaveFileName', 'myplot.fig', 'SaveDirectory', 'results')
% Description:
% Plots mean g2 angular correlations with optional parameters.
%
% Notes:
% Optional notes, references.
% --- Parse name-value pairs ---
p = inputParser;

View File

@ -1,12 +1,15 @@
function plotG2MeanHeatmap(results, theta_query, scan_reference_values, varargin)
%% plotG2MeanHeatmap: Plots a heatmap of mean g² values at a specified theta across the phase diagram
%% plotG2MeanHeatmap
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% plotG2MeanHeatmap(results, pi/6, scan_parameter_values, scan_reference_values, ...
% 'FigNum', 1, 'Colormap', @jet, 'CLim', [], 'ColorScale', 'linear', ...
% 'XLabel', 'Param1', 'YLabel', 'Param2', ...
% 'Title', 'Mean g²', 'SaveFileName', 'g2MeanHeatmap.fig', ...
% 'SaveDirectory', 'results', 'SkipSaveFigures', false);
% Description:
% Plots a heatmap of mean g² values at a specified theta across the phase
% diagram.
%
% Notes:
% Optional notes, references.
% --- Parse optional inputs ---
p = inputParser;

View File

@ -1,23 +1,14 @@
function plotG2PDF(results, theta_query, varargin)
%% plotG2PDF: Plots 2D heatmap of PDFs of g²(θ) values for different scan parameters
%% plotG2PDF
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% plotG2PDF(results, pi/6, ...
% 'PlotType', 'histogram', ...
% 'NumberOfBins', 50, ...
% 'NormalizeHistogram', true, ...
% 'Title', 'g² PDF', ...
% 'XLabel', 'Scan Parameter α', ...
% 'YLabel', 'g²(\theta = \pi/6)', ...
% 'FigNum', 1, ...
% 'FontName', 'Arial', ...
% 'SkipSaveFigures', false, ...
% 'SaveFileName', 'G2PDF.fig', ...
% 'SaveDirectory', 'results', ...
% 'NumPoints', 200, ...
% 'DataRange', [], ...
% 'XLim', [], ...
% 'Colormap', @jet);
% Description:
% Plots 2D heatmap of PDFs of g²(θ) values for different scan parameters.
%
% Notes:
% Optional notes, references.
% --- Parse optional inputs ---
p = inputParser;

View File

@ -1,14 +1,14 @@
function plotHeatmap(results, scan_parameter_values, scan_reference_values, fieldName, varargin)
%% plotHeatmap: Plots a heatmap for a field in a struct array.
%% plotHeatmap
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% plotHeatmap(results, scan_parameter_values, scan_reference_values, 'energy', ...
% 'FigNum', 1, 'Colormap', parula, 'CLim', [0 1], ...
% 'ColorScale', 'log', ...
% 'XLabel', 'Param1', 'YLabel', 'Param2', ...
% 'Title', 'My Title', 'SaveFileName', 'heatmap.fig', ...
% 'SaveDirectory', 'results', 'SkipSaveFigures', false, ...
% 'PlotDirectly', false);
% Description:
% Plots a heatmap for a field in a struct array.
%
% Notes:
% Optional notes, references.
% --- Parse optional inputs ---
p = inputParser;

View File

@ -1,12 +1,14 @@
function plotMeanWithSE(scan_values, data_values, varargin)
%% plotMeanWithSE: Plots mean ± standard error vs a scan parameter.
%% plotMeanWithSE
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% plotMeanWithSE(scan_values, data_values, ...
% 'Title', 'My Title', 'XLabel', 'Parameter', 'YLabel', 'Mean Value', ...
% 'FigNum', 1, 'FontName', 'Arial', 'YLim', [0 1], ...
% 'SaveFileName', 'mean_with_se.fig', 'SaveDirectory', 'results', ...
% 'SkipSaveFigures', false);
% Description:
% Plots mean ± standard error vs a scan parameter.
%
% Notes:
% Optional notes, references.
% --- Parse optional name-value pairs ---
p = inputParser;

View File

@ -1,11 +1,19 @@
function plotMultiplePCAResults(pcaResults, scan_parameter_values, scan_reference_values, varargin)
%% plotMultiplePCAResults: Plots PCA results for multiple PCs
%% plotMultiplePCAResults
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Plots PCA results for multiple PCs.
%
% Inputs:
% pcaResults - struct returned by computePCAfromImages
% scan_parameter_values, scan_reference_values
% varargin - name-value pairs (same as plotG2 plus 'FigNumRange','MaxPCToPlot')
%
% Notes:
% Optional notes, references.
% --- Parse name-value pairs ---
p = inputParser;

View File

@ -1,23 +1,14 @@
function plotPDF(dataCell, referenceValues, varargin)
%% plotPDF: Plots 2D heatmap of PDFs for grouped data (Histogram or KDE)
%% plotPDF
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% Plotter.plotPDF(dataCell, referenceValues, ...
% 'PlotType', 'histogram', ... % 'histogram' (default) or 'kde'
% 'NumberOfBins', 50, ... % number of histogram bins
% 'NormalizeHistogram', true, ... % normalize hist counts to probability density
% 'Title', 'My Title', ...
% 'XLabel', 'Scan Parameter', ...
% 'YLabel', 'Data Values', ...
% 'FigNum', 1, ...
% 'FontName', 'Arial', ...
% 'SkipSaveFigures', true, ...
% 'SaveFileName', 'SavedPDFs', ...
% 'SaveDirectory', 'results', ...
% 'NumPoints', 200, ...
% 'DataRange', [min max], ...
% 'XLim', [xmin xmax], ...
% 'Colormap', @jet);
% Description:
% Plots 2D heatmap of PDFs for grouped data (Histogram or KDE).
%
% Notes:
% Optional notes, references.
% --- Parse optional inputs ---
p = inputParser;

View File

@ -1,11 +1,19 @@
function plotSinglePCAResults(pcaResults, scan_parameter_values, scan_reference_values, varargin)
%% plotPCAResults: Plots PCA results
%% plotSinglePCAResults
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Description:
% Plots PCA results.
%
% Inputs:
% pcaResults - struct returned by computePCAfromImages
% scan_parameter_values, scan_reference_values
% varargin - name-value pairs (same as plotG2 plus 'FigNumRange','MaxPCToPlot')
%
% Notes:
% Optional notes, references.
% --- Parse name-value pairs ---
p = inputParser;

View File

@ -1,9 +1,11 @@
function saveFigure(fig, varargin)
%% saveFigure saves a MATLAB figure as a .fig file in a specified directory.
%% saveFigure
% Author: Karthik
% Date: 2025-09-12
% Version: 1.0
%
% Usage:
% saveFigure(fig)
% saveFigure(fig, 'SaveFileName', 'myplot.fig', 'SaveDirectory', 'results', 'SkipSaveFigures', false)
% Description:
% Saves a MATLAB figure as a .fig file in a specified directory.
%
% Inputs:
% fig - Figure handle to save
@ -13,7 +15,12 @@ function saveFigure(fig, varargin)
% 'SaveDirectory' - Directory to save into (default: current working directory)
% 'SkipSaveFigures' - If true, skips saving (default: false)
%
% Example:
% Notes:
% Usage -
% saveFigure(fig)
% saveFigure(fig, 'SaveFileName', 'myplot.fig', 'SaveDirectory', 'results', 'SkipSaveFigures', false)
%
% Example -
% fig = figure;
% plot(1:10, rand(1,10));
% saveFigure(fig, 'SaveFileName', 'test.fig', 'SaveDirectory', 'plots');

View File

@ -0,0 +1,93 @@
%% ===== BEC-Droplets Settings =====
% Specify data location to run analysis on
dataSources = {
struct('sequence', 'Evaporative_Cooling', ...
'date', '2025/08/13', ...
'runs', [30]) % 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/202508';
options.measurementName = 'BECToDroplets';
scriptFullPath = mfilename('fullpath');
options.saveDirectory = fileparts(scriptFullPath);
% Camera / imaging settings
options.cam = 3; % 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 = [840, 972];
options.span = [100, 100];
options.fraction = [0.1, 0.1];
options.pixel_size = 5.86e-6; % in meters
options.magnification = 2.2218;
options.ImagingMode = 'LowIntensity';
options.PulseDuration = 25e-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 = 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 = true;
options.skipSaveData = false;
options.skipSaveFigures = true;
options.skipSaveProcessedOD = true;
options.skipLivePlot = true;
options.showProgressBar = true;
% Extras
options.font = 'Bahnschrift';
switch options.measurementName
case 'BECToDroplets'
options.scan_parameter = 'z_offset';
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);
Analyzer.runInteractiveODImageViewer(od_imgs, scan_parameter_values, file_list, options);

View File

@ -89,5 +89,5 @@ end
[options.selectedPath, options.folderPath] = Helper.selectDataSourcePath(dataSources, options);
[od_imgs, scan_parameter_values, scan_reference_values, file_list] = Helper.collectODImages(options);
%%
Analyzer.runInteractiveODImageViewer(od_imgs, scan_parameter_values, file_list, options);