Adjusted parameters, new script to run Fourier analysis on simulated data
This commit is contained in:
parent
ef2eab89ec
commit
e256caa0dc
296
Dipolar-Gas-Simulator/+Scripts/conductFourierAnalysis.m
Normal file
296
Dipolar-Gas-Simulator/+Scripts/conductFourierAnalysis.m
Normal file
@ -0,0 +1,296 @@
|
||||
function [spectral_weight, g2, theta_vals] = conductFourierAnalysis(folder_path, run_index, N_bins, Threshold, Sigma, SuppressPlotFlag)
|
||||
|
||||
arguments
|
||||
folder_path (1,:) char
|
||||
run_index (1,:) {mustBeNumeric,mustBeReal}
|
||||
N_bins (1,:) {mustBeNumeric,mustBeReal}
|
||||
Threshold (1,:) {mustBeNumeric,mustBeReal}
|
||||
Sigma (1,:) {mustBeNumeric,mustBeReal}
|
||||
SuppressPlotFlag (1,:) logical = true
|
||||
end
|
||||
|
||||
set(0,'defaulttextInterpreter','latex')
|
||||
set(groot, 'defaultAxesTickLabelInterpreter','latex'); set(groot, 'defaultLegendInterpreter','latex');
|
||||
|
||||
% Load data
|
||||
Data = load(fullfile(fullfile(folder_path, sprintf('Run_%03i', run_index)), 'psi_gs.mat'), 'psi', 'Transf', 'Observ', 'Params');
|
||||
|
||||
Params = Data.Params;
|
||||
Transf = Data.Transf;
|
||||
Observ = Data.Observ;
|
||||
|
||||
if isgpuarray(Data.psi)
|
||||
psi = gather(Data.psi);
|
||||
else
|
||||
psi = Data.psi;
|
||||
end
|
||||
if isgpuarray(Data.Observ.residual)
|
||||
Observ.residual = gather(Data.Observ.residual);
|
||||
else
|
||||
Observ.residual = Data.Observ.residual;
|
||||
end
|
||||
|
||||
alpha = Params.theta;
|
||||
|
||||
% Axes scaling and coordinates in micrometers
|
||||
x = Transf.x * Params.l0 * 1e6;
|
||||
y = Transf.y * Params.l0 * 1e6;
|
||||
z = Transf.z * Params.l0 * 1e6;
|
||||
|
||||
dz = z(2)-z(1);
|
||||
|
||||
% Calculate frequency increment (frequency axes)
|
||||
Nx = length(x); % grid size along X
|
||||
Ny = length(y); % grid size along Y
|
||||
dx = mean(diff(x)); % real space increment in the X direction (in micrometers)
|
||||
dy = mean(diff(y)); % real space increment in the Y direction (in micrometers)
|
||||
dvx = 1 / (Nx * dx); % reciprocal space increment in the X direction (in micrometers^-1)
|
||||
dvy = 1 / (Ny * dy); % reciprocal space increment in the Y direction (in micrometers^-1)
|
||||
|
||||
% Create the frequency axes
|
||||
vx = (-Nx/2:Nx/2-1) * dvx; % Frequency axis in X (micrometers^-1)
|
||||
vy = (-Ny/2:Ny/2-1) * dvy; % Frequency axis in Y (micrometers^-1)
|
||||
|
||||
% Calculate maximum frequencies
|
||||
% kx_max = pi / dx;
|
||||
% ky_max = pi / dy;
|
||||
|
||||
% Generate reciprocal axes
|
||||
% kx = linspace(-kx_max, kx_max * (Nx-2)/Nx, Nx);
|
||||
% ky = linspace(-ky_max, ky_max * (Ny-2)/Ny, Ny);
|
||||
|
||||
% Create the Wavenumber axes
|
||||
kx = 2*pi*vx; % Wavenumber axis in X
|
||||
ky = 2*pi*vy; % Wavenumber axis in Y
|
||||
|
||||
% Compute probability density |psi|^2
|
||||
n = abs(psi).^2;
|
||||
|
||||
nxy = squeeze(trapz(n*dz,3));
|
||||
|
||||
skipPreprocessing = true;
|
||||
skipMasking = true;
|
||||
skipIntensityThresholding = true;
|
||||
skipBinarization = true;
|
||||
|
||||
%% Extract Spectral Weight and g2
|
||||
|
||||
IMG = nxy;
|
||||
|
||||
[IMGFFT, ~] = computeFourierTransform(IMG, skipPreprocessing, skipMasking, skipIntensityThresholding, skipBinarization);
|
||||
|
||||
[theta_vals, S_theta] = computeNormalizedAngularSpectralDistribution(IMGFFT, 10, 35, N_bins, Threshold, Sigma);
|
||||
|
||||
spectral_weight = trapz(theta_vals, S_theta);
|
||||
|
||||
g2 = zeros(1, N_bins); % Preallocate
|
||||
|
||||
for dtheta = 0:N_bins-1
|
||||
profile = S_theta;
|
||||
profile_shifted = circshift(profile, -dtheta, 2);
|
||||
|
||||
num = mean(profile .* profile_shifted);
|
||||
denom = mean(profile)^2;
|
||||
|
||||
g2(dtheta+1) = num / denom - 1;
|
||||
end
|
||||
|
||||
if ~SuppressPlotFlag
|
||||
figure(1);
|
||||
clf
|
||||
set(gcf,'Position',[500 100 1000 800])
|
||||
t = tiledlayout(2, 2, 'TileSpacing', 'compact', 'Padding', 'compact'); % 1x4 grid
|
||||
font = 'Bahnschrift';
|
||||
% Display the cropped OD image
|
||||
ax1 = nexttile;
|
||||
plotxy = pcolor(x,y,IMG');
|
||||
set(plotxy, 'EdgeColor', 'none');
|
||||
% Define normalized positions (relative to axis limits)
|
||||
x_offset = 0.025; % 5% offset from the edges
|
||||
y_offset = 0.025; % 5% offset from the edges
|
||||
% Top-right corner (normalized axis coordinates)
|
||||
hText = text(1 - x_offset, 1 - y_offset, ...
|
||||
['\alpha = ', num2str(rad2deg(alpha), '%.1f'), '^\circ'], ...
|
||||
'Color', 'white', 'FontWeight', 'bold', ...
|
||||
'Interpreter', 'tex', 'FontSize', 20, ...
|
||||
'Units', 'normalized', ...
|
||||
'HorizontalAlignment', 'right', ...
|
||||
'VerticalAlignment', 'top');
|
||||
axis square;
|
||||
hcb = colorbar;
|
||||
hcb.Label.Interpreter = 'latex';
|
||||
colormap(gca, Helper.Colormaps.plasma())
|
||||
set(gca, 'FontSize', 14); % For tick labels only
|
||||
hL = ylabel(hcb, 'Column Density');
|
||||
hXLabel = xlabel('$x$ ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14);
|
||||
hYLabel = ylabel('$y$ ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14);
|
||||
hTitle = title('$|\Psi(x,y)|^2$', 'Interpreter', 'latex', 'FontSize', 14) ;
|
||||
set(hText, 'FontName', font)
|
||||
set([hXLabel, hYLabel, hL], 'FontSize', 14)
|
||||
set(hTitle, 'FontName', font, 'FontSize', 16, 'FontWeight', 'bold'); % Set font and size for title
|
||||
|
||||
|
||||
% Plot the power spectrum
|
||||
nexttile;
|
||||
imagesc(kx, ky, log(1 + abs(IMGFFT).^2));
|
||||
axis square;
|
||||
hcb = colorbar;
|
||||
colormap(gca, Helper.Colormaps.plasma())
|
||||
set(gca, 'FontSize', 14); % For tick labels only
|
||||
set(gca,'YDir','normal')
|
||||
hXLabel = xlabel('k_x', 'Interpreter', 'tex');
|
||||
hYLabel = ylabel('k_y', 'Interpreter', 'tex');
|
||||
hTitle = title('Power Spectrum - S(k_x,k_y)', 'Interpreter', 'tex');
|
||||
set([hXLabel, hYLabel], 'FontName', font)
|
||||
set([hXLabel, hYLabel], 'FontSize', 14)
|
||||
set(hTitle, 'FontName', font, 'FontSize', 16, 'FontWeight', 'bold'); % Set font and size for title
|
||||
|
||||
% Plot the angular distribution
|
||||
nexttile
|
||||
plot(theta_vals/pi, S_theta,'Linewidth',2);
|
||||
set(gca, 'FontSize', 14); % For tick labels only
|
||||
hXLabel = xlabel('\theta/\pi [rad]', 'Interpreter', 'tex');
|
||||
hYLabel = ylabel('Normalized magnitude (a.u.)', 'Interpreter', 'tex');
|
||||
hTitle = title('Angular Spectral Distribution - S(\theta)', 'Interpreter', 'tex');
|
||||
set([hXLabel, hYLabel], 'FontName', font)
|
||||
set([hXLabel, hYLabel], 'FontSize', 14)
|
||||
set(hTitle, 'FontName', font, 'FontSize', 16, 'FontWeight', 'bold'); % Set font and size for title
|
||||
grid on
|
||||
|
||||
nexttile
|
||||
plot(theta_vals/pi, g2, 'o-', 'LineWidth', 1.2, 'MarkerSize', 5);
|
||||
set(gca, 'FontSize', 14);
|
||||
ylim([-1.5 3.0]); % Set y-axis limits here
|
||||
hXLabel = xlabel('$\delta\theta / \pi$', 'Interpreter', 'latex');
|
||||
hYLabel = ylabel('$g^{(2)}(\delta\theta)$', 'Interpreter', 'latex');
|
||||
hTitle = title('Autocorrelation', 'Interpreter', 'tex');
|
||||
set([hXLabel, hYLabel], 'FontName', font)
|
||||
set([hXLabel, hYLabel], 'FontSize', 14)
|
||||
set(hTitle, 'FontName', font, 'FontSize', 16, 'FontWeight', 'bold'); % Set font and size for title
|
||||
grid on;
|
||||
end
|
||||
end
|
||||
|
||||
%% Helper Functions
|
||||
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)
|
||||
|
||||
if ~skipPreprocessing
|
||||
% Preprocessing: Denoise
|
||||
filtered = imgaussfilt(I, 10);
|
||||
IMGPR = I - filtered; % adjust sigma as needed
|
||||
else
|
||||
IMGPR = I;
|
||||
end
|
||||
|
||||
if ~skipMasking
|
||||
[rows, cols] = size(IMGPR);
|
||||
[X, Y] = meshgrid(1:cols, 1:rows);
|
||||
% Elliptical mask parameters
|
||||
cx = cols / 2;
|
||||
cy = rows / 2;
|
||||
|
||||
% Shifted coordinates
|
||||
x = X - cx;
|
||||
y = Y - cy;
|
||||
|
||||
% Ellipse semi-axes
|
||||
rx = 0.4 * cols;
|
||||
ry = 0.2 * rows;
|
||||
|
||||
% Rotation angle in degrees -> radians
|
||||
theta_deg = 30; % Adjust as needed
|
||||
theta = deg2rad(theta_deg);
|
||||
|
||||
% Rotated ellipse equation
|
||||
cos_t = cos(theta);
|
||||
sin_t = sin(theta);
|
||||
|
||||
x_rot = (x * cos_t + y * sin_t);
|
||||
y_rot = (-x * sin_t + y * cos_t);
|
||||
|
||||
ellipseMask = (x_rot.^2) / rx^2 + (y_rot.^2) / ry^2 <= 1;
|
||||
|
||||
% Apply cutout mask
|
||||
IMGPR = IMGPR .* ellipseMask;
|
||||
end
|
||||
|
||||
if ~skipIntensityThresholding
|
||||
% Apply global intensity threshold mask
|
||||
intensity_thresh = 0.20;
|
||||
intensity_mask = IMGPR > intensity_thresh;
|
||||
IMGPR = IMGPR .* intensity_mask;
|
||||
end
|
||||
|
||||
if ~skipBinarization
|
||||
% Adaptive binarization and cleanup
|
||||
IMGPR = imbinarize(IMGPR, 'adaptive', 'Sensitivity', 0.0);
|
||||
IMGPR = imdilate(IMGPR, strel('disk', 2));
|
||||
IMGPR = imerode(IMGPR, strel('disk', 1));
|
||||
IMGPR = imfill(IMGPR, 'holes');
|
||||
F = fft2(double(IMGPR)); % Compute 2D Fourier Transform
|
||||
IMGFFT = abs(fftshift(F))'; % Shift zero frequency to center
|
||||
else
|
||||
F = fft2(double(IMGPR)); % Compute 2D Fourier Transform
|
||||
IMGFFT = abs(fftshift(F))'; % Shift zero frequency to center
|
||||
end
|
||||
end
|
||||
|
||||
function [theta_vals, S_theta] = computeNormalizedAngularSpectralDistribution(IMGFFT, r_min, r_max, num_bins, threshold, sigma)
|
||||
% Apply threshold to isolate strong peaks
|
||||
IMGFFT(IMGFFT < threshold) = 0;
|
||||
|
||||
% Prepare polar coordinates
|
||||
[ny, nx] = size(IMGFFT);
|
||||
[X, Y] = meshgrid(1:nx, 1:ny);
|
||||
cx = ceil(nx/2);
|
||||
cy = ceil(ny/2);
|
||||
R = sqrt((X - cx).^2 + (Y - cy).^2);
|
||||
Theta = atan2(Y - cy, X - cx); % range [-pi, pi]
|
||||
|
||||
% Choose radial band
|
||||
radial_mask = (R >= r_min) & (R <= r_max);
|
||||
|
||||
% Initialize the angular structure factor array
|
||||
S_theta = zeros(1, num_bins); % Pre-allocate for 180 angle bins
|
||||
% Define the angle values for the x-axis
|
||||
theta_vals = linspace(0, pi, num_bins);
|
||||
|
||||
% Loop through each angle bin
|
||||
for i = 1:num_bins
|
||||
angle_start = (i-1) * pi / num_bins;
|
||||
angle_end = i * pi / num_bins;
|
||||
|
||||
% Define a mask for the given angle range
|
||||
angle_mask = (Theta >= angle_start & Theta < angle_end);
|
||||
|
||||
bin_mask = radial_mask & angle_mask;
|
||||
|
||||
% Extract the Fourier components for the given angle
|
||||
fft_angle = IMGFFT .* bin_mask;
|
||||
|
||||
% Integrate the Fourier components over the radius at the angle
|
||||
S_theta(i) = sum(sum(abs(fft_angle).^2)); % sum of squared magnitudes
|
||||
end
|
||||
|
||||
% Create a 1D Gaussian kernel
|
||||
half_width = ceil(3 * sigma);
|
||||
x = -half_width:half_width;
|
||||
gauss_kernel = exp(-x.^2 / (2 * sigma^2));
|
||||
gauss_kernel = gauss_kernel / sum(gauss_kernel); % normalize
|
||||
|
||||
% Apply convolution (circular padding to preserve periodicity)
|
||||
S_theta = conv([S_theta(end-half_width+1:end), S_theta, S_theta(1:half_width)], gauss_kernel, 'same');
|
||||
S_theta = S_theta(half_width+1:end-half_width); % crop back to original size
|
||||
|
||||
% Normalize to 1
|
||||
S_theta = S_theta / max(S_theta);
|
||||
end
|
||||
|
@ -48,7 +48,7 @@ function run_hybrid_worker(batchParams, batchIdx)
|
||||
OptionsStruct.MaxIterationsForGD = 15000;
|
||||
OptionsStruct.TimeStepSize = 1E-3; % in s
|
||||
OptionsStruct.MinimumTimeStepSize = 1E-6; % in s
|
||||
OptionsStruct.TimeCutOff = 2E5; % in s
|
||||
OptionsStruct.TimeCutOff = 1E6; % in s
|
||||
OptionsStruct.EnergyTolerance = 5E-10;
|
||||
OptionsStruct.ResidualTolerance = 1E-05;
|
||||
OptionsStruct.NoiseScaleFactor = 0.010;
|
||||
@ -77,4 +77,4 @@ function run_hybrid_worker(batchParams, batchIdx)
|
||||
end
|
||||
|
||||
delete(pool);
|
||||
end
|
||||
end
|
@ -1066,3 +1066,69 @@ else
|
||||
disp('The state is not modulated');
|
||||
end
|
||||
|
||||
%% Plot Spectral weight and g2 across transition for simulated data
|
||||
N_atoms = 5E5;
|
||||
a_s = 95.62;
|
||||
phi_deg = 0.0;
|
||||
alpha_vals = [0.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0];
|
||||
|
||||
N_alpha = length(alpha_vals);
|
||||
N_bins = 90;
|
||||
Threshold = 75;
|
||||
Sigma = 2;
|
||||
|
||||
spectral_weights = zeros(size(alpha_vals));
|
||||
g2_all = zeros(N_alpha, N_bins);
|
||||
theta_vals_all = zeros(N_alpha, N_bins);
|
||||
|
||||
JobNumber = 1;
|
||||
SuppressPlotFlag = true;
|
||||
|
||||
for i = 1:N_alpha
|
||||
folderName = sprintf('aS_%03d_theta_%03d_phi_%03d_N_%d', a_s, alpha_vals(i), phi_deg, N_atoms);
|
||||
SaveDirectory = fullfile('D:/Results - Numerics/Data_Full3D/PhaseTransition/DTS/', folderName);
|
||||
[spectral_weight, g2, theta_vals] = Scripts.conductFourierAnalysis(SaveDirectory, JobNumber, N_bins, Threshold, Sigma, SuppressPlotFlag);
|
||||
spectral_weights(i) = spectral_weight; % Store the spectral weight for the current alpha value
|
||||
g2_all(i, :) = g2; % Store the g2 results for the current alpha value
|
||||
theta_vals_all(i, :) = theta_vals;
|
||||
end
|
||||
|
||||
figure(2);
|
||||
set(gcf,'Position',[100 100 950 750])
|
||||
font = 'Bahnschrift';
|
||||
plot(alpha_vals, spectral_weights, 'o--', ...
|
||||
'LineWidth', 1.5, 'MarkerSize', 6);
|
||||
set(gca, 'FontSize', 14); % For tick labels only
|
||||
hXLabel = xlabel('\alpha (degrees)', 'Interpreter', 'tex');
|
||||
hYLabel = ylabel('Spectral Weight', 'Interpreter', 'tex');
|
||||
hTitle = title('Change across transition', 'Interpreter', 'tex');
|
||||
set([hXLabel, hYLabel], 'FontName', font)
|
||||
set([hXLabel, hYLabel], 'FontSize', 14)
|
||||
set(hTitle, 'FontName', font, 'FontSize', 16, 'FontWeight', 'bold'); % Set font and size for title
|
||||
grid on
|
||||
|
||||
figure(3);
|
||||
set(gcf,'Position',[100 100 950 750])
|
||||
font = 'Bahnschrift';
|
||||
legend_entries = cell(N_alpha, 1);
|
||||
theta_vals = theta_vals_all(1, :);
|
||||
cmap = sky(N_alpha); % Generate a colormap with enough unique colors
|
||||
hold on
|
||||
|
||||
for i = 1:N_alpha
|
||||
plot(theta_vals/pi, g2_all(i, :), ...
|
||||
'o-', 'Color', cmap(i,:), 'LineWidth', 1.2, ...
|
||||
'MarkerSize', 5);
|
||||
legend_entries{i} = sprintf('$\\alpha = %g^\\circ$', alpha_vals(i));
|
||||
end
|
||||
set(gca, 'FontSize', 14);
|
||||
ylim([-1.5 10.0]); % Set y-axis limits here
|
||||
hXLabel = xlabel('$\delta\theta / \pi$', 'Interpreter', 'latex');
|
||||
hYLabel = ylabel('$g^{(2)}(\delta\theta)$', 'Interpreter', 'latex');
|
||||
hTitle = title('Transition from Droplets to Stripes', 'Interpreter', 'tex');
|
||||
legend(legend_entries, 'Interpreter', 'latex', 'Location', 'bestoutside');
|
||||
set([hXLabel, hYLabel], 'FontName', font)
|
||||
set([hXLabel, hYLabel], 'FontSize', 14)
|
||||
set(hTitle, 'FontName', font, 'FontSize', 16, 'FontWeight', 'bold'); % Set font and size for title
|
||||
grid on;
|
||||
|
||||
|
@ -46,13 +46,13 @@ function run_on_cluster(batchParams, batchIdx)
|
||||
OptionsStruct.MaxIterationsForGD = 15000;
|
||||
OptionsStruct.TimeStepSize = 1E-3;
|
||||
OptionsStruct.MinimumTimeStepSize = 1E-6;
|
||||
OptionsStruct.TimeCutOff = 5E5;
|
||||
OptionsStruct.TimeCutOff = 2E5;
|
||||
OptionsStruct.EnergyTolerance = 5E-08;
|
||||
OptionsStruct.ResidualTolerance = 1E-05;
|
||||
OptionsStruct.NoiseScaleFactor = 0.010;
|
||||
|
||||
OptionsStruct.PlotLive = false;
|
||||
OptionsStruct.JobNumber = k;
|
||||
OptionsStruct.JobNumber = 0;
|
||||
OptionsStruct.RunOnGPU = true;
|
||||
OptionsStruct.SaveData = true;
|
||||
OptionsStruct.SaveDirectory = saveDir;
|
||||
|
Loading…
Reference in New Issue
Block a user