128 lines
4.3 KiB
Mathematica
128 lines
4.3 KiB
Mathematica
|
%% 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
|