Calculations/Estimations/ModellingImagingAberrations.m

128 lines
4.3 KiB
Matlab

%% Zernike Polynomials
resolution = 100; % Resolution
plotZernike(2, 0, resolution) % Defocus (Z2^0)
%%
plotZernike(2, 2, resolution) % Astigmatism (Z2^2)
%%
plotZernike(3, 1, resolution) % Coma (Z3^1, x-direction)
%%
plotZernike(3, -1, resolution) % Coma (Z3^-1, y-direction)
%%
plotZernike(4, 0, resolution) % Spherical Aberration (Z4^0)
%% Aberrated PSF
C = [0.0, 0.0, 0.0, 0.0, 0.0]; % Zernike coefficients
pupil_radius = 0.5; % Pupil radius (normalized)
plotAberratedPSF(C, pupil_radius, resolution);
function Z = computeZernikePolynomials(n, m, r, theta)
% Zernike polynomial function for radial and angular coordinates (r, theta)
% Input:
% n - radial order
% m - azimuthal frequency
% r - radial coordinate (normalized to unit circle, 0 <= r <= 1)
% theta - angular coordinate (angle in radians)
%
% Output:
% Z - Zernike polynomial value at (r, theta)
if n == 2 && m == 0
% Defocus (Z2^0)
Z = 2 * r.^2 - 1;
elseif n == 2 && m == 2
% Astigmatism (Z2^2)
Z = r.^2 .* cos(2 * theta);
elseif n == 3 && m == 1
% Coma (Z3^1)
Z = (3 * r.^3 - 2 * r) .* cos(theta);
elseif n == 3 && m == -1
% Coma (Z3^-1)
Z = (3 * r.^3 - 2 * r) .* sin(theta);
elseif n == 4 && m == 0
% Spherical Aberration (Z4^0)
Z = 6 * r.^4 - 6 * r.^2 + 1;
else
% Default to zero if no known Zernike polynomial matches
Z = 0;
end
end
function plotZernike(n, m, resolution)
% n: radial order
% m: azimuthal frequency
% resolution: number of points for plotting
% Create a grid of (r, theta) coordinates
[theta, r] = meshgrid(linspace(0, 2*pi, resolution), linspace(0, 1, resolution));
% Calculate the Zernike polynomial for the given (n, m)
Z = computeZernikePolynomials(n, m, r, theta);
% Convert polar to Cartesian coordinates for plotting
[X, Y] = pol2cart(theta, r);
% Plot the Zernike polynomial using a surface plot
figure(1)
clf
set(gcf,'Position',[50 50 950 750])
surf(X, Y, Z, 'EdgeColor', 'none');
colormap jet;
colorbar;
title(sprintf('Zernike Polynomial Z_{%d}^{%d}', n, m), 'Interpreter', 'tex', 'FontSize', 16);
xlabel('X', 'FontSize', 16);
ylabel('Y', 'FontSize', 16);
zlabel('Zernike Value', 'FontSize', 16);
axis equal;
shading interp;
end
function [theta, r, PSF] = modelPSF(C, pupil_radius, resolution)
% C is the vector of Zernike coefficients [C_defocus, C_astigmatism, C_coma, C_spherical, ...]
% resolution is the number of points for the grid (NxN grid)
% pupil_radius is the radius of the pupil aperture
% Create a grid of (r, theta) coordinates
[theta, r] = meshgrid(linspace(0, 2*pi, resolution), linspace(0, 1, resolution));
% Pupil function: 1 inside the pupil radius, 0 outside
P = double(r <= pupil_radius); % 2D mask
% Wavefront error from Zernike polynomials
W = C(1) * computeZernikePolynomials(2, 0, r, theta) + ... % Defocus (Z2^0)
C(2) * computeZernikePolynomials(2, 2, r, theta) + ... % Astigmatism (Z2^2)
C(3) * computeZernikePolynomials(3, 1, r, theta) + ... % Coma (Z3^1, x-direction)
C(4) * computeZernikePolynomials(3, -1, r, theta) + ... % Coma (Z3^-1, y-direction)
C(5) * computeZernikePolynomials(4, 0, r, theta); % Spherical Aberration (Z4^0)
% Fourier transform of the pupil function with aberrations
PSF = abs(fftshift(fft2(P .* exp(1i * W)))).^2; % Intensity distribution
end
function plotAberratedPSF(C, pupil_radius, resolution)
% C: Zernike coefficients [C_defocus, C_astigmatism, C_coma_x, C_coma_y, C_spherical]
% pupil_radius: Radius of the pupil aperture
% resolution: Number of points for plotting
% Generate PSF using the updated modelPSF function
[theta, r, PSF] = modelPSF(C, pupil_radius, resolution);
% Convert polar to Cartesian coordinates for plotting
[X, Y] = pol2cart(theta, r);
figure(1)
clf
set(gcf,'Position',[50 50 950 750])
surf(X, Y, PSF, 'EdgeColor', 'none');
view(2); % 2D view
axis equal tight;
shading interp;
colorbar;
colormap jet;
title('PSF', 'FontSize', 16);
xlabel('X', 'FontSize', 16);
ylabel('Y', 'FontSize', 16);
end