Working version of the influence of aberrations on a PSF
This commit is contained in:
		
							parent
							
								
									66576da594
								
							
						
					
					
						commit
						612bae7fa1
					
				@ -13,24 +13,27 @@ plotZernike(3, -1, NumberOfGridPoints) % Coma (Z3^-1, y-direction)
 | 
				
			|||||||
plotZernike(4, 0, NumberOfGridPoints)  % Spherical Aberration (Z4^0)
 | 
					plotZernike(4, 0, NumberOfGridPoints)  % Spherical Aberration (Z4^0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%% Compute and plot Aberrated PSF, Image
 | 
					%% Compute and plot Aberrated PSF, Image
 | 
				
			||||||
NumberOfGridPoints   = 1024;                        % Number of grid points per side
 | 
					NumberOfGridPoints   = 256;                         % Number of grid points per side
 | 
				
			||||||
PupilRadius          = 0.010;                       % Radius of pupil [m]
 | 
					PupilRadius          = 10E-3;                       % Radius of pupil [m]
 | 
				
			||||||
Length               = 0.5;                         % Total size of the grid [m]
 | 
					Length               = 32E-6;                       % Total size of the grid [m]
 | 
				
			||||||
GridSpacing          = Length / NumberOfGridPoints; % Grid spacing [m]
 | 
					GridSpacing          = Length / NumberOfGridPoints; % Grid spacing [m]
 | 
				
			||||||
Wavelength           = 421e-9;                      % Optical wavelength [m]
 | 
					Wavelength           = 421E-9;                      % Optical wavelength [m]
 | 
				
			||||||
ImageDistance        = 0.7;                         % Image distance [m]
 | 
					FocalLength          = 3*PupilRadius;               % Focal Length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
% Generate PSF
 | 
					% Generate PSF
 | 
				
			||||||
C                    = [0.3, 0.2, 0.1, -0.1, 0.4];  % Zernike coefficients
 | 
					C                    = [1.5, 0.0, 0.1, -0.1, 0.5];  % Zernike coefficients
 | 
				
			||||||
[X, Y, PSF]          = generateAberratedPSF(C, PupilRadius, NumberOfGridPoints, GridSpacing);
 | 
					PSF                  = generateAberratedPSF(C, Wavelength, PupilRadius, NumberOfGridPoints, GridSpacing, FocalLength);
 | 
				
			||||||
plotAberratedPSF(X, Y, PSF);
 | 
					
 | 
				
			||||||
 | 
					xvals                = (-NumberOfGridPoints/2 : NumberOfGridPoints/2-1) * GridSpacing * 1E6;
 | 
				
			||||||
 | 
					yvals                = (-NumberOfGridPoints/2 : NumberOfGridPoints/2-1) * GridSpacing * 1E6;
 | 
				
			||||||
 | 
					plotImage(xvals, yvals, PSF, 'PSF');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
% Generate object
 | 
					% Generate object
 | 
				
			||||||
Object               = generateObject(Wavelength, ImageDistance, NumberOfGridPoints, GridSpacing);
 | 
					% Object               = generateObject(Wavelength, NumberOfGridPoints, GridSpacing, FocalLength);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
% Convolve the object with the PSF to simulate imaging
 | 
					% Convolve the object with the PSF to simulate imaging
 | 
				
			||||||
Image                = convolveObjectWithPSF(abs(Object).^2, PSF, 1);
 | 
					% Image                = convolveObjectWithPSF(abs(Object).^2, PSF);
 | 
				
			||||||
 | 
					% plotImage(xvals, yvals, Image, 'Image of Object formed by convolving with the PSF');
 | 
				
			||||||
%% Functions
 | 
					%% Functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function Z = computeZernikePolynomials(n, m, r, theta)
 | 
					function Z = computeZernikePolynomials(n, m, r, theta)
 | 
				
			||||||
@ -46,19 +49,19 @@ function Z = computeZernikePolynomials(n, m, r, theta)
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    if n == 2 && m == 0
 | 
					    if n == 2 && m == 0
 | 
				
			||||||
        % Defocus (Z2^0)
 | 
					        % Defocus (Z2^0)
 | 
				
			||||||
        Z = 2 * r.^2 - 1;
 | 
					        Z = sqrt(3) * (2 * r.^2 - 1);
 | 
				
			||||||
    elseif n == 2 && m == 2
 | 
					    elseif n == 2 && m == 2
 | 
				
			||||||
        % Astigmatism (Z2^2)
 | 
					        % Vertical Astigmatism (Z2^2)
 | 
				
			||||||
        Z = r.^2 .* cos(2 * theta);
 | 
					        Z = sqrt(6) * r.^2 .* cos(2 * theta);
 | 
				
			||||||
    elseif n == 3 && m == 1
 | 
					    elseif n == 3 && m == 1
 | 
				
			||||||
        % Coma (Z3^1)
 | 
					        % Horizontal Coma (Z3^1)
 | 
				
			||||||
        Z = (3 * r.^3 - 2 * r) .* cos(theta);
 | 
					        Z = sqrt(8) * (3 * r.^3 - 2 * r) .* cos(theta);
 | 
				
			||||||
    elseif n == 3 && m == -1
 | 
					    elseif n == 3 && m == -1
 | 
				
			||||||
        % Coma (Z3^-1)
 | 
					        % Vertical Coma (Z3^-1)
 | 
				
			||||||
        Z = (3 * r.^3 - 2 * r) .* sin(theta);
 | 
					        Z = sqrt(8) * (3 * r.^3 - 2 * r) .* sin(theta);
 | 
				
			||||||
    elseif n == 4 && m == 0
 | 
					    elseif n == 4 && m == 0
 | 
				
			||||||
        % Spherical Aberration (Z4^0)
 | 
					        % Spherical Aberration (Z4^0)
 | 
				
			||||||
        Z = 6 * r.^4 - 6 * r.^2 + 1;
 | 
					        Z = sqrt(5) * (6 * r.^4 - 6 * r.^2 + 1);
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        % Default to zero if no known Zernike polynomial matches
 | 
					        % Default to zero if no known Zernike polynomial matches
 | 
				
			||||||
        Z = 0;
 | 
					        Z = 0;
 | 
				
			||||||
@ -94,7 +97,7 @@ function plotZernike(n, m, NumberOfGridPoints)
 | 
				
			|||||||
    shading interp;
 | 
					    shading interp;
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function [X, Y, PSF] = generateAberratedPSF(C, PupilRadius, NumberOfGridPoints, GridSpacing)
 | 
					function PSF = generateAberratedPSF(C, Wavelength, PupilRadius, NumberOfGridPoints, GridSpacing, FocalLength)
 | 
				
			||||||
    % C is the vector of Zernike coefficients [C_defocus, C_astigmatism, C_coma, C_spherical, ...]
 | 
					    % C is the vector of Zernike coefficients [C_defocus, C_astigmatism, C_coma, C_spherical, ...]
 | 
				
			||||||
    % NumberOfGridPoints is the number of points for the grid (NxN grid)
 | 
					    % NumberOfGridPoints is the number of points for the grid (NxN grid)
 | 
				
			||||||
    % PupilRadius is the radius of the pupil aperture
 | 
					    % PupilRadius is the radius of the pupil aperture
 | 
				
			||||||
@ -103,72 +106,65 @@ function [X, Y, PSF] = generateAberratedPSF(C, PupilRadius, NumberOfGridPoints,
 | 
				
			|||||||
    [X, Y] = meshgrid((-NumberOfGridPoints/2 : NumberOfGridPoints/2-1) * GridSpacing);
 | 
					    [X, Y] = meshgrid((-NumberOfGridPoints/2 : NumberOfGridPoints/2-1) * GridSpacing);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    % Convert (x, y) to polar coordinates (r, theta)
 | 
					    % Convert (x, y) to polar coordinates (r, theta)
 | 
				
			||||||
    [theta, r] = cart2pol(X, Y);
 | 
					    [theta, ~] = cart2pol(X, Y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    % Pupil function: 1 inside the pupil radius, 0 outside
 | 
					    % Pupil function
 | 
				
			||||||
    P = generateCircularMask(X, Y, 2 * PupilRadius);  % 2D mask
 | 
					    P = generatePupil(Wavelength, PupilRadius, NumberOfGridPoints, GridSpacing, FocalLength);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    % Wavefront error from Zernike polynomials
 | 
					    % Wavefront error from Zernike polynomials
 | 
				
			||||||
    W = C(1) * computeZernikePolynomials(2, 0, r, theta) + ...  % Defocus (Z2^0)
 | 
					    W = C(1) * computeZernikePolynomials(2, 0, P, theta) + ...  % Defocus (Z2^0)
 | 
				
			||||||
        C(2) * computeZernikePolynomials(2, 2, r, theta) + ...  % Astigmatism (Z2^2)
 | 
					        C(2) * computeZernikePolynomials(2, 2, P, theta) + ...  % Astigmatism (Z2^2)
 | 
				
			||||||
        C(3) * computeZernikePolynomials(3, 1, r, theta) + ...  % Coma (Z3^1, x-direction)
 | 
					        C(3) * computeZernikePolynomials(3, 1, P, theta) + ...  % Coma (Z3^1, x-direction)
 | 
				
			||||||
        C(4) * computeZernikePolynomials(3, -1, r, theta) + ... % Coma (Z3^-1, y-direction)
 | 
					        C(4) * computeZernikePolynomials(3, -1, P, theta) + ... % Coma (Z3^-1, y-direction)
 | 
				
			||||||
        C(5) * computeZernikePolynomials(4, 0, r, theta);       % Spherical Aberration (Z4^0)
 | 
					        C(5) * computeZernikePolynomials(4, 0, P, theta);       % Spherical Aberration (Z4^0)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    W(P>1)       = 0;
 | 
				
			||||||
 | 
					    E            = exp(1i*2*pi*W); % Complex amplitude
 | 
				
			||||||
 | 
					    E(P>1)       = 0;              % Impose aperture size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    % Fourier transform of the pupil function with aberrations
 | 
					    % Fourier transform of the pupil function with aberrations
 | 
				
			||||||
    PSF = abs(calculateExtendedFFT2(P .* exp(-1i * 2*pi * W), GridSpacing)).^2;
 | 
					    PSF          = abs(calculateFFT2(E)).^2;
 | 
				
			||||||
 | 
					    PSF          = PSF/sum(PSF(:));
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function plotAberratedPSF(X, Y, PSF)
 | 
					function plotImage(xvals, yvals, image, titlestring)
 | 
				
			||||||
    % C: Zernike coefficients [C_defocus, C_astigmatism, C_coma_x, C_coma_y, C_spherical]
 | 
					    figure
 | 
				
			||||||
    % PupilRadius: Radius of the pupil aperture
 | 
					 | 
				
			||||||
    % NumberOfGridPoints: Number of points for plotting
 | 
					 | 
				
			||||||
    % Generate PSF using the updated modelPSF function
 | 
					 | 
				
			||||||
    PSF         = PSF / max(PSF(:));
 | 
					 | 
				
			||||||
    figure(1)
 | 
					 | 
				
			||||||
    clf
 | 
					    clf
 | 
				
			||||||
    set(gcf,'Position',[50 50 950 750])
 | 
					    set(gcf,'Position',[50 50 950 750])
 | 
				
			||||||
    surf(X, Y, PSF, 'EdgeColor', 'none');
 | 
					    imagesc(xvals, yvals, image);
 | 
				
			||||||
    xlim([-0.05 0.05])
 | 
					 | 
				
			||||||
    ylim([-0.05 0.05])
 | 
					 | 
				
			||||||
    view(2);  % 2D view
 | 
					 | 
				
			||||||
    shading interp;
 | 
					 | 
				
			||||||
    colorbar;
 | 
					    colorbar;
 | 
				
			||||||
    colormap jet;
 | 
					    colormap jet;
 | 
				
			||||||
    title('PSF', 'FontSize', 16);
 | 
					    title(titlestring, 'FontSize', 16);
 | 
				
			||||||
    xlabel('X', 'FontSize', 16);
 | 
					    xlabel('X', 'FontSize', 16);
 | 
				
			||||||
    ylabel('Y', 'FontSize', 16);
 | 
					    ylabel('Y', 'FontSize', 16);
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function C = convolveObjectWithPSF(A, B, GridSpacing)
 | 
					function P_Norm = generatePupil(Wavelength, PupilRadius, NumberOfGridPoints, GridSpacing, FocalLength)
 | 
				
			||||||
    N = size(A, 1);
 | 
					    [X,Y]       = meshgrid((-NumberOfGridPoints/2 : NumberOfGridPoints/2-1) * ((Wavelength * FocalLength) / (NumberOfGridPoints * GridSpacing)));
 | 
				
			||||||
    C = calculateExtendedInverseFFT2(calculateExtendedFFT2(A, GridSpacing) .* calculateExtendedFFT2(B, GridSpacing), 1/(N*GridSpacing));
 | 
					    P           = sqrt(X.^2 + Y.^2);
 | 
				
			||||||
 | 
					    P_Norm      = P/PupilRadius;  % Pupil normalized by aperture radius
 | 
				
			||||||
 | 
					    assert(max(P_Norm(:))>=sqrt(2),'Sampling is not sufficient to reconstruct the entire wavefront.');
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function z = generateCircularMask(x, y, D)
 | 
					function G = calculateFFT2(g)
 | 
				
			||||||
    r         = sqrt(x.^2+y.^2);
 | 
					    G = fftshift(fft2(ifftshift(g)));
 | 
				
			||||||
    z         = double(r<D/2);
 | 
					 | 
				
			||||||
    z(r==D/2) = 0.5;
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function G = calculateExtendedFFT2(g, Delta)
 | 
					%{
 | 
				
			||||||
    G = fftshift(fft2(fftshift(g))) * Delta^2;
 | 
					
 | 
				
			||||||
 | 
					function g = calculateInverseFFT2(G)
 | 
				
			||||||
 | 
					    g = ifftshift(ifft2(fftshift(G)));
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function g = calculateExtendedInverseFFT2(G, Delta_f)
 | 
					function obj = generateObject(Wavelength, NumberOfGridPoints, GridSpacing, FocalLength)
 | 
				
			||||||
    N = size(G, 1);
 | 
					 | 
				
			||||||
    g = ifftshift(ifft2(ifftshift(G))) * (N * Delta_f)^2;
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function ret = generateRectangle(x, D)
 | 
					 | 
				
			||||||
    if nargin == 1, D = 1; end
 | 
					 | 
				
			||||||
     x = abs(x);
 | 
					 | 
				
			||||||
     ret = double(x<D/2);
 | 
					 | 
				
			||||||
    ret(x == D/2) = 0.5;
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function obj = generateObject(Wavelength, ImageDistance, NumberOfGridPoints, GridSpacing)
 | 
					 | 
				
			||||||
    % Image-plane coordinates
 | 
					    % Image-plane coordinates
 | 
				
			||||||
    [U, V] = meshgrid((-NumberOfGridPoints/2 : NumberOfGridPoints/2-1) * ((Wavelength * ImageDistance) / (NumberOfGridPoints * GridSpacing)));
 | 
					    [U, V] = meshgrid((-NumberOfGridPoints/2 : NumberOfGridPoints/2-1) * ((Wavelength * FocalLength) / (NumberOfGridPoints * GridSpacing)));
 | 
				
			||||||
    obj    = (generateRectangle((U-1.4e-4)/5e-5) + generateRectangle(U/5e-5)+ generateRectangle((U+1.4e-4)/5e-5)) .* generateRectangle(V/2e-4);
 | 
					    obj    = ;
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function C = convolveObjectWithPSF(A, B)
 | 
				
			||||||
 | 
					    C = calculateInverseFFT2(calculateFFT2(A) .* calculateFFT2(B));
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user