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:
parent
b6a49ff0f7
commit
ad048ac2ef
@ -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();
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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} = ''
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(:);
|
||||
|
||||
@ -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);
|
||||
|
||||
568
Data-Analyzer/+FitModels/DensityProfileBEC2DModel.m
Normal file
568
Data-Analyzer/+FitModels/DensityProfileBEC2DModel.m
Normal 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
|
||||
202
Data-Analyzer/+FitModels/TwoGaussian2DModel.m
Normal file
202
Data-Analyzer/+FitModels/TwoGaussian2DModel.m
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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', {});
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 = '';
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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');
|
||||
|
||||
93
Data-Analyzer/+Scripts/AtomNumberAndTemperature/plotImages.m
Normal file
93
Data-Analyzer/+Scripts/AtomNumberAndTemperature/plotImages.m
Normal 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);
|
||||
@ -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);
|
||||
Loading…
x
Reference in New Issue
Block a user