Calculations/Data-Analyzer/StructuralPhaseTransition/SpectralAnalysisRoutines/analyzewithPCA.m

210 lines
7.2 KiB
Matlab
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

%% STEP 1: Extract Images
clear; close all; clc;
baseDir = 'D:/Results - Numerics/Data_Full3D/PhaseTransition/DTS/Point2';
JobNumber = 0;
runFolder = sprintf('Run_%03d', JobNumber);
savefileName = 'DropletsToStripes'; % Output file name
datafileName = './DropletsToStripes.mat';
reverseOrder = false; % Set this to true to reverse the theta ordering
TitleString = 'Droplets To Stripes';
%%
baseDir = 'D:/Results - Numerics/Data_Full3D/PhaseTransition/STD/Point2';
JobNumber = 0;
runFolder = sprintf('Run_%03d', JobNumber);
savefileName = 'StripesToDroplets'; % Output file name
datafileName = './StripesToDroplets.mat';
reverseOrder = true; % Set this to true to reverse the theta ordering
TitleString = 'Stripes To Droplets';
%%
folderList = dir(baseDir);
isValid = [folderList.isdir] & ~ismember({folderList.name}, {'.', '..'});
folderNames = {folderList(isValid).name};
nimgs = numel(folderNames);
% Extract theta values from folder names
PolarAngleVals = zeros(1, nimgs);
for k = 1:nimgs
tokens = regexp(folderNames{k}, 'theta_(\d{3})', 'tokens');
if isempty(tokens)
warning('No theta found in folder name: %s', folderNames{k});
PolarAngleVals(k) = NaN;
else
PolarAngleVals(k) = str2double(tokens{1}{1});
end
end
% Choose sort direction
sortDirection = 'ascend';
if reverseOrder
sortDirection = 'descend';
end
% Sort folderNames based on polar angle
[~, sortIdx] = sort(PolarAngleVals, sortDirection);
folderNames = folderNames(sortIdx);
PolarAngleVals = PolarAngleVals(sortIdx); % Optional: if you still want sorted list
imgs = cell(1, nimgs);
alphas = zeros(1, nimgs);
for k = 1:nimgs
folderName = folderNames{k};
SaveDirectory = fullfile(baseDir, folderName, runFolder);
% Extract alpha (theta) again from folder name
tokens = regexp(folderName, 'theta_(\d{3})', 'tokens');
alpha_val = str2double(tokens{1}{1});
alphas(k) = alpha_val;
matPath = fullfile(SaveDirectory, 'psi_gs.mat');
if ~isfile(matPath)
warning('Missing psi_gs.mat in %s', SaveDirectory);
continue;
end
try
Data = load(matPath, 'psi', 'Params', 'Transf', 'Observ');
catch ME
warning('Failed to load %s: %s', matPath, ME.message);
continue;
end
Params = Data.Params;
Transf = Data.Transf;
Observ = Data.Observ;
psi = Data.psi;
if isgpuarray(psi)
psi = gather(psi);
end
if isgpuarray(Observ.residual)
Observ.residual = gather(Observ.residual);
end
% Axes and projection
z = Transf.z * Params.l0 * 1e6;
dz = z(2)-z(1);
if k == 1
x = Transf.x * Params.l0 * 1e6;
y = Transf.y * Params.l0 * 1e6;
% 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)
% Create the Wavenumber axes
kx_full = 2*pi*vx; % Wavenumber axis in X
ky_full = 2*pi*vy; % Wavenumber axis in Y
end
n = abs(psi).^2;
nxy = squeeze(trapz(n * dz, 3));
imgs{k} = nxy;
end
%% STEP 2: Visualize images
figure(1);
set(gcf,'Position',[100 100 950 750])
font = 'Bahnschrift';
t = tiledlayout(4, 3, 'TileSpacing', 'compact', 'Padding', 'compact'); % 1x4 grid
for i = 1:nimgs
ax1 = nexttile;
imagesc(x, y, imgs{i}')
% 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
axis square;
hcb = colorbar;
colormap(ax1, Colormaps.plasma());
set(gca, 'FontSize', 14); % For tick labels only
hL = ylabel(hcb, 'Optical Density');
set(hL,'Rotation',-90);
set(gca,'YDir','normal')
% set(gca, 'YTick', linspace(y_min, y_max, 5)); % Define y ticks
% set(gca, 'YTickLabel', flip(linspace(y_min, y_max, 5))); % Flip only the labels
hXLabel = xlabel('x (µm)', 'Interpreter', 'tex');
hYLabel = ylabel('y (µm)', 'Interpreter', 'tex');
hTitle = title('Density', 'Interpreter', 'tex');
set([hXLabel, hYLabel, hL], 'FontName', font)
set([hXLabel, hYLabel, hL], 'FontSize', 14)
set(hTitle, 'FontName', font, 'FontSize', 16, 'FontWeight', 'bold'); % Set font and size for title
end
sgtitle('Ground States');
%% STEP 3: Reshape images into a 2D data matrix
% Each image will be a row vector, so size(X) = [numImages × numPixels]
% First, convert cell array to numeric 3D array
allImgs = cat(3, imgs{:}); % size: [Nx × Ny × numImages]
% Store image size for reshaping later
imgSize = size(allImgs(:,:,1)); % [Nx, Ny]
% Reshape into 2D matrix for PCA
X = reshape(allImgs, [], nimgs)'; % [numImages × (Nx*Ny)]
%% STEP 4: Perform PCA
[coeff, score, latent, tsquared, explained] = pca(X);
% coeff : principal component directions (eigenvectors) in pixel space
% score : projection of each image onto the principal components
% latent : eigenvalues (variance captured by each PC)
% explained : percentage variance explained by each PC
%% Visualize cumulative variance
figure(2);
set(gcf,'Position',[100 100 950 750])
cumVar = cumsum(explained);
plot(cumVar, 'o-', 'LineWidth', 1.5);
yline(95, '--r', '95% threshold');
xlabel('Number of Principal Components');
ylabel('Cumulative Variance (%)');
title('Minimum number of PCA components required for a basis');
grid on;
%% Visualize first few principal components
numPCsToShow = 7;
figure(3);
set(gcf,'Position',[100 100 950 750])
t = tiledlayout(3, 3, 'TileSpacing', 'compact', 'Padding', 'compact'); % 1x4 grid
for i = 1:numPCsToShow
pcImage = reshape(coeff(:,i), imgSize); % reshape back to image form
nexttile;
imagesc(pcImage)
axis image off; colormap(Colormaps.coolwarm());
title(sprintf('PC %d (%.1f%%)', i, explained(i)));
end
sgtitle('First Principal Components (Eigenimages)');
%% Visualize evolution of PCA scores
figure(4);
set(gcf,'Position',[100 100 950 750])
plot(alphas, score(:,1), '-o', 'LineWidth', 1.5, 'DisplayName', 'PC1 Score');
hold on;
plot(alphas, score(:,2), '-o', 'LineWidth', 1.5, 'DisplayName', 'PC2 Score');
% plot(alphas, score(:,3), '-o', 'LineWidth', 1.5, 'DisplayName', 'PC3 Score');
% plot(alphas, score(:,4), '-o', 'LineWidth', 1.5, 'DisplayName', 'PC4 Score');
% plot(alphas, score(:,5), '-o', 'LineWidth', 1.5, 'DisplayName', 'PC5 Score');
% plot(alphas, score(:,6), '-o', 'LineWidth', 1.5, 'DisplayName', 'PC6 Score');
% plot(alphas, score(:,7), '-o', 'LineWidth', 1.5, 'DisplayName', 'PC7 Score');
legend('Location', 'northeast');
xlabel('Polar Angle (°)'); ylabel('PC Score');
title('Evolution of PC Scores');
grid on;