Calculations/Data-Analyzer/+Analyzer/extractFullAngularSpectralDistribution.m

100 lines
3.6 KiB
Matlab

function results = extractFullAngularSpectralDistribution(od_imgs, options)
%% extractFullAngularSpectralDistribution
% Author: Karthik
% Date: 2025-10-09
% Version: 1.0
%
% Description:
% Computes the angular spectral distribution S(θ) from OD images,
% extending θ from 0 → 2π using the computeAngularSpectralDistribution function.
%
% Inputs:
% od_imgs - cell array of OD images
% options - struct containing relevant parameters:
% pixel_size, magnification, zoom_size,
% k_min, k_max, N_angular_bins,
% Angular_Threshold, Angular_Sigma
%
% Outputs:
% results - struct containing θ values and angular spectra
%
% Notes:
% This function is a minimal variant of conductSpectralAnalysis,
% stopping right after angular spectral extraction.
%% ===== Unpack options =====
pixel_size = options.pixel_size;
magnification = options.magnification;
zoom_size = options.zoom_size;
k_min = options.k_min;
k_max = options.k_max;
N_angular_bins = options.N_angular_bins;
Angular_Threshold = options.Angular_Threshold;
Angular_Sigma = options.Angular_Sigma;
skipPreprocessing = options.skipPreprocessing;
skipMasking = options.skipMasking;
skipIntensityThresholding = options.skipIntensityThresholding;
skipBinarization = options.skipBinarization;
%% ===== Initialization =====
N_shots = length(od_imgs);
fft_imgs = cell(1, N_shots);
S_theta_all = cell(1, N_shots);
S_theta_norm_all = cell(1, N_shots);
theta_vals = [];
%% ===== Main loop =====
for k = 1:N_shots
IMG = od_imgs{k};
% Skip empty or low-intensity images
if ~(max(IMG(:)) > 1)
IMGFFT = NaN(size(IMG));
else
% Compute FFT (with same preprocessing pipeline)
[IMGFFT, ~] = Calculator.computeFourierTransform(IMG, ...
skipPreprocessing, skipMasking, skipIntensityThresholding, skipBinarization);
end
% Image dimensions
[Ny, Nx] = size(IMG);
dx = pixel_size / magnification;
dy = dx;
% Reciprocal-space sampling
dvx = 1 / (Nx * dx);
dvy = 1 / (Ny * dy);
vx = (-floor(Nx/2):ceil(Nx/2)-1) * dvx;
vy = (-floor(Ny/2):ceil(Ny/2)-1) * dvy;
% Convert to wavenumber axes [µm⁻¹]
kx_full = 2 * pi * vx * 1E-6;
ky_full = 2 * pi * vy * 1E-6;
% Crop FFT and wavenumber axes around center
mid_x = floor(Nx/2);
mid_y = floor(Ny/2);
fft_imgs{k} = IMGFFT(mid_y-zoom_size:mid_y+zoom_size, mid_x-zoom_size:mid_x+zoom_size);
kx = kx_full(mid_x - zoom_size : mid_x + zoom_size);
ky = ky_full(mid_y - zoom_size : mid_y + zoom_size);
% ===== Compute angular spectrum (0 → 2π) =====
[theta_vals, S_theta] = Calculator.computeAngularSpectralDistribution( ...
fft_imgs{k}, kx, ky, k_min, k_max, N_angular_bins, ...
Angular_Threshold, Angular_Sigma, [], 2*pi);
% Normalize angular spectrum and compute weight
S_theta_norm = S_theta / max(S_theta);
% Store results
S_theta_all{k} = S_theta;
S_theta_norm_all{k} = S_theta_norm;
end
%% ===== Package results =====
results = struct();
results.theta_vals = theta_vals;
results.S_theta_all = S_theta_all;
results.S_theta_norm_all = S_theta_norm_all;
end