pyoptics.imaging

Simple imaging: coherent imaging, point spread function (PSF), optical transfer function (OTF), modulation transfer function (MTF) and Strehl ratio.

All functions here describe a scalar imaging system in the paraxial picture. The pupil is sampled on the frequency grid that belongs to the image plane grid x, y (utils.freq_grid() with normal_order=True). The pupil edge lies at |k_perp| = k*NA. Normalized pupil coordinates are (P_x, P_y) = (k_x, k_y)/(k*NA), so that the pupil is the unit disk P_x**2 + P_y**2 <= 1; Fringe Zernikes with R_norm = 1 evaluated on P_x, P_y thus describe the usual pupil aberrations.

Pupil masks may be given as arrays sampled on the frequency grid or as callables mask(P_x, P_y); the mask may be real-valued (apodization) or complex. Phases (in radians, i.e. 2*pi*W for a wavefront error W in waves) may be given in the same two ways. With the convention exp(i(k.r - omega*t)), a positive phase corresponds to a wavefront that runs ahead.

Sampling: the PSF is band limited to |k_perp| <= k*NA, the intensity PSF and hence the OTF to 2*k*NA. The grid spacing should thus fulfil dx <= wavelength/(4*NA) to sample the OTF without aliasing. The pupil is sampled with spacing 2*pi/L (L: size of the image plane window), i.e. with about L*NA/wavelength samples across its radius; the larger the window, the better the pupil (and with it the PSF) is resolved.

get_psf() can evaluate the PSF on a separate output grid x_out, y_out (e.g. a fine grid around the core or an off-axis window) by a chirp-z transform of the pupil, without zero padding: x, y then only set the pupil sampling.

References

    1. Goodman, “Introduction to Fourier Optics”, 4th ed., W. H. Freeman (2017).

M. Born and E. Wolf, “Principles of Optics”, 7th ed., Cambridge University Press (1999).

V. N. Mahajan, “Optical Imaging and Aberrations, Part II: Wave Diffraction Optics”, 2nd ed., SPIE Press (2011).

G. D. Boreman, “Modulation Transfer Function in Optical and Electro-Optical Systems”, SPIE Press (2001).

Functions

get_mtf

Modulation transfer function |OTF|.

get_otf

Optical transfer function of an incoherent imaging system.

get_psf

Amplitude point spread function of an imaging system.

image

Coherent image of an object through a 4f system.

marechal_strehl

Approximate Strehl ratio from the RMS phase error sigma (radians).

pupil_coordinates

Normalized pupil coordinates on the frequency grid of x, y.

pupil_function

Sampled pupil function P = mask*exp(i*phase) inside the unit disk.

rms_phase

Root mean square of the pupil phase with the piston removed.

strehl_ratio

Strehl ratio of an aberrated pupil.

pyoptics.imaging.image(obj, x, y, NA, k)[source]

Coherent image of an object through a 4f system.

The spectrum of the object is truncated at the cut-off k*NA (no aberrations, no obliquity factor).

Parameters:
obj2d array

Object field in the focal plane (may be complex).

x, y1d arrays

Coordinates of the object.

NAnumber

Numerical aperture.

knumber

Wavenumber.

Returns:
image2d array

Complex image field.

pyoptics.imaging.pupil_coordinates(x, y, NA, k)[source]

Normalized pupil coordinates on the frequency grid of x, y.

Parameters:
x, yarrays

Linear image plane coordinates.

NAnumber

Image-side numerical aperture.

knumber

Wavenumber (2*pi/wavelength).

Returns:
P_x, P_yarrays

(k_x, k_y)/(k*NA) in normal (centered) order, shape (Ny, Nx). The pupil is the unit disk.

pyoptics.imaging.pupil_function(x, y, NA, k, pupil_mask=None, phase=None)[source]

Sampled pupil function P = mask*exp(i*phase) inside the unit disk.

Parameters:
x, yarrays

Linear image plane coordinates.

NAnumber

Image-side numerical aperture.

knumber

Wavenumber.

pupil_maskarray or callable, optional

Amplitude transmission of the pupil (e.g. a central obscuration or an apodization), sampled on the frequency grid or a callable pupil_mask(P_x, P_y). It is always multiplied with the circular pupil of radius k*NA. Defaults to None (clear circular pupil).

phasearray or callable, optional

Pupil phase in radians, as array or callable phase(P_x, P_y). Defaults to None (no aberrations).

Returns:
Parray

Complex pupil function on the centered frequency grid, shape (Ny, Nx).

pyoptics.imaging.get_psf(x, y, NA, k, pupil_mask=None, phase=None, normalization='peak', x_out=None, y_out=None)[source]

Amplitude point spread function of an imaging system.

The PSF is the (inverse) Fourier transform of the pupil function, located at the center x = y = 0 of the grid (for a centered grid, see fft).

Parameters:
x, yarrays

Linear image plane coordinates.

NAnumber

Image-side numerical aperture.

knumber

Wavenumber.

pupil_mask, phasearrays or callables, optional

See pupil_function().

normalization{“peak”, “energy”, None}, optional

“peak” (default): scale such that the aberration-free PSF of the same pupil mask has the amplitude 1 at its center, so that |psf[Ny//2, Nx//2]|**2 is the Strehl ratio. “energy”: scale such that sum(|psf|**2)*dx*dy = 1 on the grid x, y (with x_out, y_out the same scale factor is used, so the PSF energy on the full plane is 1). None: plain inverse DFT of the pupil.

x_out, y_outarrays, optional

Linear, equidistant output coordinates. If given, the PSF is evaluated there by a chirp-z transform (fft.zoom_inv_FT()) of the pupil sampled on the frequency grid of x, y: any center, extent and sampling, e.g. a fine grid over the Airy disk without padding. The PSF is periodic with the window size of x, y. Defaults to None (PSF on x, y).

Returns:
psfarray

Complex amplitude PSF, shape (Ny, Nx) or (len(y_out), len(x_out)). The intensity PSF is |psf|**2.

pyoptics.imaging.get_otf(x, y, NA, k, pupil_mask=None, phase=None)[source]

Optical transfer function of an incoherent imaging system.

The OTF is the Fourier transform of the intensity PSF, i.e. the normalized autocorrelation of the pupil function.

Parameters:
x, yarrays

Linear image plane coordinates.

NAnumber

Image-side numerical aperture.

knumber

Wavenumber.

pupil_mask, phasearrays or callables, optional

See pupil_function().

Returns:
otfarray

Complex OTF normalized to OTF(0) = 1 on the centered frequency grid, i.e. at the frequencies utils.freq_grid(x, y, wavenumbers=False, normal_order=True). It vanishes beyond the cut-off frequency 2*NA/wavelength.

pyoptics.imaging.get_mtf(x, y, NA, k, pupil_mask=None, phase=None)[source]

Modulation transfer function |OTF|.

Parameters:
x, yarrays

Linear image plane coordinates.

NAnumber

Image-side numerical aperture.

knumber

Wavenumber.

pupil_mask, phasearrays or callables, optional

See pupil_function().

Returns:
mtfarray

On the frequency grid of get_otf().

pyoptics.imaging.rms_phase(x, y, NA, k, pupil_mask=None, phase=None)[source]

Root mean square of the pupil phase with the piston removed.

The mean and the variance are weighted with the pupil amplitude |P|.

Parameters:
Same as pupil_function().
Returns:
sigmanumber

RMS phase error in radians (multiply by wavelength/(2*pi) for the RMS wavefront error).

pyoptics.imaging.strehl_ratio(x, y, NA, k, pupil_mask=None, phase=None)[source]

Strehl ratio of an aberrated pupil.

Computed as the intensity at the Gaussian image point (the grid center) relative to the aberration-free system with the same pupil mask, |sum(P)|**2/sum(|P|)**2. This is Born & Wolf’s definition; with tilt in the phase the PSF maximum moves away from the center and can be larger.

Parameters:
Same as pupil_function().
Returns:
Snumber

Strehl ratio in [0, 1].

pyoptics.imaging.marechal_strehl(sigma, approximation='exponential')[source]

Approximate Strehl ratio from the RMS phase error sigma (radians).

Parameters:
sigmanumber or array

RMS phase error with piston removed, e.g. from rms_phase(), or 2*pi*W_rms/wavelength for a wavefront error W_rms.

approximation{“exponential”, “marechal”, “quadratic”}, optional

“exponential” (default): exp(-sigma**2) (Mahajan), good up to sigma of about 1 rad for many aberrations. “marechal”: (1 - sigma**2/2)**2. “quadratic”: 1 - sigma**2, the leading order valid for small sigma.

Returns:
Snumber or array