prysm.propagation#

Numerical optical propagation.

Files: - fft FFT-based pupil <-> focal propagation - dft matrix-DFT / chirp-Z propagation with arbitrary sampling - angular_spectrum plane-to-plane free space propagation, Fresnel/Talbot metrics - coronagraph focal-plane-mask and Babinet/Lyot propagation - wavefront the Wavefront type, object oriented interface

fft, dft, angular_spectrum, coronagraph operate on arrays. Wavefront chains through the wavefront object for a more “fluent” API and less bookkeeping

prysm.propagation.focus(wavefunction, Q)#

Propagate a pupil plane to a PSF plane.

Parameters:
  • wavefunction (ndarray) – the pupil wavefunction

  • Q (float) – oversampling / padding factor

Returns:

psf – point spread function

Return type:

ndarray

prysm.propagation.focus_adjoint(wavefunction, Q)#

Apply the adjoint of focus.

Parameters:
  • wavefunction (ndarray) – gradient at the PSF plane

  • Q (float) – oversampling / padding factor used for the forward propagation

Returns:

gradient at the pupil plane

Return type:

ndarray

prysm.propagation.unfocus(wavefunction, Q)#

Propagate a PSF plane to a pupil plane.

Parameters:
  • wavefunction (ndarray) – the pupil wavefunction

  • Q (float) – oversampling / padding factor

Returns:

pupil – field in the pupil plane

Return type:

ndarray

prysm.propagation.unfocus_adjoint(wavefunction, Q)#

Apply the adjoint of unfocus.

Parameters:
  • wavefunction (ndarray) – gradient at the pupil plane

  • Q (float) – oversampling / padding factor used for the forward propagation

Returns:

gradient at the PSF plane

Return type:

ndarray

prysm.propagation.Q_for_sampling(input_diameter, prop_dist, wavelength, output_dx)#

Value of Q for a given output sampling, given input sampling.

Parameters:
  • input_diameter (float) – diameter of the input array in millimeters

  • prop_dist (float) – propagation distance along the z distance, millimeters

  • wavelength (float) – wavelength of light, microns

  • output_dx (float) – sampling in the output plane, microns

Returns:

requesite Q

Return type:

float

prysm.propagation.pupil_sample_to_psf_sample(pupil_sample, samples, wavelength, efl)#

Convert pupil sample spacing to PSF sample spacing. fλ/D or Q.

Parameters:
  • pupil_sample (float) – sample spacing in the pupil plane

  • samples (int) – number of samples present in both planes (must be equal)

  • wavelength (float) – wavelength of light, in microns

  • efl (float) – effective focal length of the optical system in mm

Returns:

the sample spacing in the PSF plane

Return type:

float

prysm.propagation.psf_sample_to_pupil_sample(psf_sample, samples, wavelength, efl)#

Convert PSF sample spacing to pupil sample spacing.

Parameters:
  • psf_sample (float) – sample spacing in the PSF plane

  • samples (int) – number of samples present in both planes (must be equal)

  • wavelength (float) – wavelength of light, in microns

  • efl (float) – effective focal length of the optical system in mm

Returns:

the sample spacing in the pupil plane

Return type:

float

prysm.propagation.coordinates_for_focus(pupil_dx, pupil_samples, focal_dx, focal_samples, wavelength, efl, focal_shift=(0, 0))#

Coordinate / frequency vectors for an MDFT-based pupil ↔ focal propagation.

The Fraunhofer kernel is exp(-2πi · x_pupil · x_focal / (λ · efl)). This returns the input pupil coordinates (x, y) and the spatial frequencies (fx, fy) that pair with them, where fx = x_focal / (λ · efl).

For end users, prefer prepare_executor, which wraps this and bakes the optical normalization into the executor. If you do build the executor by hand, multiply its result by pupil_dx * focal_dx / (wavelength * efl).

Parameters:
  • pupil_dx (float) – pupil-plane sample spacing, mm

  • pupil_samples (int or (int, int)) – pupil samples; a single int is treated as square, a tuple as (rows, cols)

  • focal_dx (float) – focal-plane sample spacing, microns

  • focal_samples (int or (int, int)) – focal samples; a single int is treated as square, a tuple as (rows, cols)

  • wavelength (float) – wavelength of light, microns

  • efl (float) – effective focal length, mm

  • focal_shift ((float, float)) – (x, y) translation of the focal grid center, microns

Returns:

  • x, y (ndarray) – pupil coordinates along the column and row axes, mm

  • fx, fy (ndarray) – spatial frequencies along the column and row axes, 1/mm

prysm.propagation.prepare_executor(pupil_dx, pupil_samples, focal_dx, focal_samples, wavelength, efl, focal_shift=(0, 0), kind='mdft')#

Build a reusable MDFT or CZT operator for a pupil ↔ focal propagation.

Wraps coordinates_for_focus and the executor constructor in one call. The optical normalization scalar pupil_dx * focal_dx / (wavelength * efl) is baked into the executor’s norm, so applying the executor produces a unitary-equivalent propagated field. The returned operator is in the focus orientation:

  • Focus: executor(pupil_data) produces focal data

  • Unfocus: executor.adjoint(focal_data) produces pupil data

The pupil and focal sample spacings are also stashed on the returned operator as executor.pupil_dx and executor.focal_dx for callers that need them (e.g. to label an output Wavefront).

Parameters:
  • pupil_dx – See coordinates_for_focus.

  • pupil_samples – See coordinates_for_focus.

  • focal_dx – See coordinates_for_focus.

  • focal_samples – See coordinates_for_focus.

  • wavelength – See coordinates_for_focus.

  • efl – See coordinates_for_focus.

  • focal_shift – See coordinates_for_focus.

  • kind ({'mdft', 'czt'}, optional) – Executor type to build. Default ‘mdft’.

Returns:

operator suitable for passing to focus_dft, unfocus_dft, etc.

Return type:

MDFT or CZT

prysm.propagation.prepare_multiresolution(pupil_dx, pupil_samples, focal_dx, focal_samples, wavelength, efl, num_levels, scaling=4.0, fine_samples=None, window=(0.2, 0.7), kind='mdft')#

Build a MultiResolutionExecutor for focal-plane-mask propagation.

The coarsest level is specified exactly as for prepare_executor and should span the full field of view (focal_dx * focal_samples large enough to reach the edge of the propagated field) at or above Nyquist, so no spatial frequencies are truncated. Each finer level divides the sample spacing and the field of view by scaling, zooming into the singular core of the mask.

Parameters:
  • pupil_dx – coarsest-level geometry; see coordinates_for_focus. focal_dx and focal_samples describe level 0 only.

  • pupil_samples – coarsest-level geometry; see coordinates_for_focus. focal_dx and focal_samples describe level 0 only.

  • focal_dx – coarsest-level geometry; see coordinates_for_focus. focal_dx and focal_samples describe level 0 only.

  • focal_samples – coarsest-level geometry; see coordinates_for_focus. focal_dx and focal_samples describe level 0 only.

  • wavelength – coarsest-level geometry; see coordinates_for_focus. focal_dx and focal_samples describe level 0 only.

  • efl – coarsest-level geometry; see coordinates_for_focus. focal_dx and focal_samples describe level 0 only.

  • num_levels (int) – number of resolution levels. One level reduces to an ordinary single executor (no hand-off windows).

  • scaling (float, optional) – ratio of consecutive levels’ sample spacings and fields of view. Default 4.

  • fine_samples (int, optional) – focal_samples for every level past the coarsest. Their field of view shrinks with scaling, so fewer samples than the coarsest level still oversample. Defaults to focal_samples.

  • window ((float, float), optional) – inner and outer radii of the hand-off transition, as fractions of each level’s focal-plane half-width. The transition tapers from one to zero across this annulus. Default (0.2, 0.7).

  • kind ({'mdft', 'czt'}, optional) – executor type. Default ‘mdft’.

Return type:

MultiResolutionExecutor

class prysm.propagation.MultiResolutionExecutor(executors, windows, xf, yf)#

Bases: object

A stack of arbitrary-sampling executors plus partition-of-unity windows.

Each level forward-propagates the pupil to a focal grid of progressively finer sampling and smaller field of view, so the singular core of a focal plane mask (e.g. a vortex phase ramp) is sampled densely while the coarsest level still spans the full field of view and captures every spatial frequency. The per-level windows form a partition of unity over the focal plane; summing each level’s masked, inverse-propagated contribution reconstructs the full diffraction integral with the singular region integrated at the finest resolution.

Build instances with prepare_multiresolution. Hand them to to_fpm_and_back_multiresolution along with a focal-plane-mask callable.

executors#

per-level pupil to focal operators, coarsest first

Type:

list of MDFT or CZT

windows#

per-level real partition-of-unity windows, summing to one over the focal plane

Type:

list of ndarray

xf, yf

per-level focal-plane coordinate meshgrids, microns; pass these to a focal-plane-mask callable to evaluate the mask on each level’s grid

Type:

list of ndarray

prysm.propagation.focus_dft(wavefunction, executor)#

Propagate a pupil field to the PSF plane via a precomputed executor.

Parameters:
  • wavefunction (ndarray) – the pupil-plane field; shape must match what the executor was built for.

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

Returns:

focal-plane field

Return type:

ndarray

prysm.propagation.focus_dft_adjoint(wavefunction, executor)#

Apply the adjoint of focus_dft.

Parameters:
  • wavefunction (ndarray) – gradient at the PSF plane

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

Returns:

gradient at the pupil plane

Return type:

ndarray

prysm.propagation.unfocus_dft(wavefunction, executor)#

Propagate an image-plane field to the pupil via a precomputed executor.

Parameters:
  • wavefunction (ndarray) – the focal-plane field

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

Returns:

pupil-plane field

Return type:

ndarray

prysm.propagation.unfocus_dft_adjoint(wavefunction, executor)#

Apply the adjoint of unfocus_dft.

Parameters:
  • wavefunction (ndarray) – gradient at the pupil plane

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

Returns:

gradient at the focal plane

Return type:

ndarray

prysm.propagation.angular_spectrum(field, wvl, dx, z, Q=2, tf=None)#

Propagate a field via the angular spectrum method.

Parameters:
  • field (ndarray) – 2D array of complex electric field values

  • wvl (float) – wavelength of light, microns

  • z (float) – propagation distance, units of millimeters

  • dx (float) – cartesian sample spacing, units of millimeters

  • Q (float) – sampling factor used. Q>=2 for Nyquist sampling of incoherent fields

  • tf (ndarray) – if not None, clobbers all other arguments transfer function for the propagation

Returns:

2D ndarray of the output field, complex

Return type:

ndarray

prysm.propagation.angular_spectrum_adjoint(field, wvl, dx, z, Q=2, tf=None)#

Apply the adjoint of angular_spectrum.

Parameters:
  • field (ndarray) – gradient at the output plane of the angular spectrum propagation

  • wvl (float) – wavelength of light, microns

  • z (float) – propagation distance used for the forward propagation, millimeters

  • dx (float) – cartesian sample spacing, units of millimeters

  • Q (float) – sampling factor used for the forward propagation

  • tf (ndarray) – if not None, clobbers all other arguments transfer function used for the forward propagation

Returns:

gradient at the input plane

Return type:

ndarray

prysm.propagation.angular_spectrum_transfer_function(samples, wvl, dx, z)#

Precompute the transfer function of free space.

Parameters:
  • samples (int or tuple) – (y,x) or (r,c) samples in the output array

  • wvl (float) – wavelength of light, microns

  • dx (float) – intersample spacing, mm

  • z (float) – propagation distance, mm

Returns:

ndarray of shape samples containing the complex valued transfer function such that X = fft2(x); xhat = ifft2(X*tf) is signal x after free space propagation

Return type:

ndarray

prysm.propagation.fresnel_number(a, L, lambda_)#

Compute the Fresnel number.

Notes

if the fresnel number is << 1, paraxial assumptions hold for propagation

Parameters:
  • a (float) – characteristic size (“radius”) of an aperture

  • L (float) – distance of observation

  • lambda (float) – wavelength of light, same units as a

Returns:

the fresnel number for these parameters

Return type:

float

prysm.propagation.talbot_distance(a, lambda_)#

Compute the talbot distance.

Parameters:
  • a (float) – period of the grating, units of microns

  • lambda (float) – wavelength of light, units of microns

Returns:

talbot distance, units of microns

Return type:

float

prysm.propagation.to_fpm_and_back(wavefunction, fpm, executor, return_more=False)#

Propagate to a focal plane mask, apply it, and return.

Composition of focus_dft, multiplication by fpm, and unfocus_dft. The same MDFT executor is used for both legs (its adjoint provides the inverse). To invoke Babinet’s principle, pass fpm=1 - fpm.

Parameters:
  • wavefunction (ndarray) – complex pupil-plane field to propagate

  • fpm (ndarray) – the focal plane mask

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

  • return_more (bool, optional) – if True, return (new_wavefront, field_at_fpm, field_after_fpm) else return new_wavefront

Returns:

next pupil; optionally also field at fpm and field after fpm

Return type:

ndarray, [ndarray, ndarray]

prysm.propagation.to_fpm_and_back_adjoint(wavefunction, fpm, executor, return_more=False, return_fpm_grad=False, field_at_fpm=None)#

Apply the adjoint of to_fpm_and_back.

Parameters:
  • wavefunction (ndarray) – gradient at the next pupil plane (output of the forward call)

  • fpm (ndarray) – the focal plane mask used in the forward propagation

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

  • return_more (bool, optional) – if True, return (Eabar, Ebbar, intermediate) else return Eabar

  • return_fpm_grad (bool, optional) – if True, also return the gradient with respect to fpm. Requires field_at_fpm from the matching forward propagation.

  • field_at_fpm (ndarray, optional) – focal-plane field before the FPM from the forward propagation

Returns:

gradient at the input pupil; optionally also the intermediate gradients and/or the gradient with respect to fpm

Return type:

ndarray or tuple of ndarray

prysm.propagation.to_fpm_and_back_multiresolution(wavefunction, fpm, executor)#

Propagate to a focal plane mask and back at multiple resolutions.

The multi-resolution analogue of to_fpm_and_back. Each level of executor forward-propagates the pupil to its focal grid, applies the mask times the level’s partition-of-unity window, and inverse-propagates; the level contributions are summed. This densely samples the singular core of a mask such as a vortex phase ramp without truncating any spatial frequency.

Parameters:
  • wavefunction (ndarray) – complex pupil-plane field to propagate

  • fpm (callable) – fpm(xf, yf) -> ndarray, the focal plane mask evaluated on focal-plane coordinate grids (microns). See vortex_phase_mask.

  • executor (MultiResolutionExecutor) – stack of executors and hand-off windows from prepare_multiresolution

Returns:

field at the next pupil (Lyot) plane

Return type:

ndarray

prysm.propagation.to_fpm_and_back_multiresolution_adjoint(wavefunction, fpm, executor)#

Apply the adjoint of to_fpm_and_back_multiresolution.

Parameters:
  • wavefunction (ndarray) – gradient at the next pupil (Lyot) plane

  • fpm (callable) – the focal plane mask callable used in the forward propagation

  • executor (MultiResolutionExecutor) – stack of executors and hand-off windows from prepare_multiresolution

Returns:

gradient at the input pupil plane

Return type:

ndarray

prysm.propagation.vortex_phase_mask(charge)#

Build a focal-plane-mask callable for a charge-charge optical vortex.

The returned callable evaluates exp(i * charge * theta), the azimuthal phase ramp of a vortex coronagraph, on focal-plane coordinate grids. Pass it to to_fpm_and_back_multiresolution, whose per-level grids resolve the on-axis phase singularity.

Parameters:

charge (int) – topological charge of the vortex; even charges null a clear circular aperture in the downstream Lyot plane

Returns:

fpm(xf, yf) -> ndarray, with xf and yf focal-plane coordinate grids

Return type:

callable

prysm.propagation.prepare_measured_fpm(measurement, dx, center=(0, 0), charge=None, fill=None, order=1)#

Wrap a measured complex focal-plane-mask map as an fpm callable.

A high-resolution metrology map of a physically realized mask (e.g. a fabricated vortex, with its real surface, etch-depth, and amplitude errors) lives on its own uniform grid. The multi-resolution executor evaluates the focal-plane mask on a different grid at every level, so the map must be resampled on demand. This returns a callable fpm(xf, yf) that bilinearly (or higher-order) interpolates the measured complex transmission at the requested focal coordinates and falls back to an ideal continuation outside the measured extent — letting to_fpm_and_back_multiresolution propagate the as-built mask to assess real manufacturing errors.

The measurement is assumed centered per the make_xy_grid / fftrange convention: array index n // 2 along each axis maps to focal coordinate center. The coarse levels span a far larger field of view than a real measurement, and the finest levels zoom below its resolution; the partition windows confine each level to the annulus its sampling resolves, so simple interpolation per level is appropriate.

Parameters:
  • measurement (ndarray) – complex transmission (amplitude times exp(1j * phase)) of the realized mask. For a measured phase map phi in radians, pass np.exp(1j * phi).

  • dx (float) – sample spacing of the measurement, in the focal-plane coordinate units of the executor (microns for prepare_multiresolution).

  • center ((float, float), optional) – (x, y) focal coordinate of the measurement’s center sample, microns. The mask singularity should sit here. Default (0, 0).

  • charge (int, optional) – if given, focal points outside the measured extent fall back to an ideal charge-charge vortex phase, the natural continuation of a vortex mask beyond the measured region. Ignored if fill is given.

  • fill (scalar or callable, optional) – value, or fpm(xf, yf) callable, for points outside the measured extent. Overrides charge. Defaults to an ideal vortex if charge is given, else 1 (no effect outside the measured region).

  • order (int, optional) – spline order for the interpolation, passed to map_coordinates. 1 (bilinear, default) is local and overshoot-free; 3 is smoother for clean maps.

Returns:

fpm(xf, yf) -> complex ndarray, suitable for to_fpm_and_back_multiresolution

Return type:

callable

prysm.propagation.babinet(wavefunction, lyot, fpm, executor, return_more=False)#

Propagate through a Lyot-style coronagraph using Babinet’s principle.

Parameters:
  • wavefunction (ndarray) – complex pupil-plane field to propagate

  • lyot (ndarray or None) – the Lyot stop; if None, equivalent to ones_like(wavefunction)

  • fpm (ndarray) – the focal plane mask (1 inside the spot); the Babinet complement 1 - fpm is formed internally (see Soummer et al 2007)

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

  • return_more (bool) – if True, return each plane in the propagation else return new_wavefront

Notes

if the substrate’s reflectivity or transmissivity is not unity, and/or the mask’s density is not infinity, babinet’s principle works as follows:

suppose we’re modeling a Lyot focal plane mask; rr = radial coordinates of the image plane, in lambda/d units mask = rr < 5 # 1 inside FPM, 0 outside (babinet-style)

now create some scalars for background transmission and mask transmission

tau = 0.9 # background tmask = 0.1 # mask

mask = tau - tau*mask + rmask*mask

the mask variable now contains 0.9 outside the spot, and 0.1 inside

Returns:

field after lyot, [field at fpm, field after fpm, field at lyot]

Return type:

ndarray, [ndarray, ndarray, ndarray]

prysm.propagation.babinet_adjoint(wavefunction, lyot, fpm, executor, field_at_fpm=None, field_at_lyot=None, return_fpm_grad=False, return_lyot_grad=False)#

Apply the adjoint of babinet.

Parameters:
  • wavefunction (ndarray) – gradient at the field-after-lyot plane (output of the forward call)

  • lyot (ndarray or None) – the Lyot stop; if None, equivalent to ones_like(wavefunction)

  • fpm (ndarray) – the focal plane mask used in the forward propagation

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

  • field_at_fpm (ndarray, optional) – focal-plane field before the FPM from the matching forward call. Required when return_fpm_grad is True.

  • field_at_lyot (ndarray, optional) – pupil-plane field before the Lyot stop from the matching forward call. Required when return_lyot_grad is True.

  • return_fpm_grad (bool, optional) – if True, also return the gradient with respect to the original fpm argument passed to babinet.

  • return_lyot_grad (bool, optional) – if True, also return the gradient with respect to lyot.

Returns:

adjoint-propagated gradient; optionally followed by FPM and/or Lyot gradients in the order requested by the keyword names

Return type:

ndarray or tuple of ndarray

class prysm.propagation.Wavefront(cmplx_field, wavelength, dx, space='pupil')#

Bases: object

(Complex) representation of a wavefront.

Create a new Wavefront instance.

Parameters:
  • cmplx_field (ndarray) – complex-valued array with both amplitude and phase error

  • wavelength (float) – wavelength of light, microns

  • dx (float) – inter-sample spacing, mm (space=pupil) or um (space=psf)

  • space (str, {'pupil', 'psf'}) – what sort of space the field occupies

classmethod from_amp_and_phase(amplitude, phase, wavelength, dx)#

Create a Wavefront from amplitude and phase.

Parameters:
  • amplitude (ndarray) – array containing the amplitude

  • phase (ndarray, optional) – array containing the optical path error with units of nm if None, assumed zero

  • wavelength (float) – wavelength of light with units of microns

  • dx (float) – sample spacing with units of mm

classmethod phase_screen(phase, wavelength, dx)#

Create a new complex phase screen.

Parameters:
  • phase (ndarray) – phase or optical path error, units of nm

  • wavelength (float) – wavelength of light with units of microns

  • dx (float) – sample spacing with units of mm

classmethod thin_lens(f, wavelength, x, y)#

Create a thin lens, used in focusing beams.

Users are encouraged to not use thin lens + free space propagation to take beams to their focus. In nearly all cases, a different propagation scheme is significantly more computational efficient. For example, just using the wf.focus() method. If you have access to the (unwrapped) phase, it is also cheaper to compute the quadratic phase you want and add that before wf.from_amp_and_phase) instead of multiplying by a thin lens.

Parameters:
  • f (float) – focal length of the lens, millimeters

  • wavelength (float) – wavelength of light, microns

  • x (ndarray) – x coordinates that define the space of the lens, mm

  • y (ndarray) – y coordinates that define the space of the beam, mm

Returns:

a wavefront object having quadratic phase which, when multiplied by another wavefront acts as a thin lens

Return type:

Wavefront

property intensity#

Intensity, abs(w)^2.

property phase#

Phase, angle(w). Possibly wrapped for large OPD.

property real#

re(w).

property imag#

im(w).

copy()#

Return a (deep) copy of this instance.

from_amp_and_phase_adjoint_phase(wf_bar)#

Adjoint of from_amp_and_phase with respect to phase.

Parameters:

wf_bar (Wavefront) – the gradient propagated to wf

Returns:

gradient with respect to the phase of wf_in

Return type:

ndarray

from_amp_and_phase_adjoint_amp(wf_bar, phase=None)#

Adjoint of from_amp_and_phase with respect to amplitude.

The forward field is P = amplitude * S, with S the unit-modulus phasor exp(prefix * phase). dP/d(amplitude) = S, so the amplitude gradient is real(conj(wf_bar) * S).

Parameters:
  • wf_bar (Wavefront) – the gradient propagated to wf

  • phase (ndarray, optional) – the phase used in the forward from_amp_and_phase, units of nm. If given, S is reconstructed exactly. If None, S is recovered from self.data as P / abs(P), which is exact where the amplitude is nonzero and yields zero gradient where the amplitude vanishes.

Returns:

gradient with respect to the amplitude of wf_in

Return type:

ndarray

phase_screen_adjoint_phase(wf_bar)#

Adjoint of phase_screen with respect to phase.

phase_screen is from_amp_and_phase with unit amplitude, so the gradient has the same form as from_amp_and_phase_adjoint_phase.

Parameters:

wf_bar (Wavefront) – the gradient propagated to wf

Returns:

gradient with respect to the phase of the screen

Return type:

ndarray

classmethod thin_lens_adjoint(f, wavelength, x, y, wf_bar)#

Adjoint of thin_lens with respect to the focal length f.

thin_lens maps the scalar focal length f to a quadratic phase screen. This is the transpose of that map: given the gradient flowing back to the screen, it returns the (scalar) gradient with respect to f, so the focal length can be treated as a differentiable design parameter.

Parameters:
  • f (float) – focal length of the lens used in the forward thin_lens, millimeters

  • wavelength (float) – wavelength of light, microns

  • x (ndarray) – x coordinates that define the space of the lens, mm

  • y (ndarray) – y coordinates that define the space of the beam, mm

  • wf_bar (Wavefront or ndarray) – gradient with respect to the lens screen produced by thin_lens

Returns:

gradient of the loss with respect to the focal length f

Return type:

scalar

intensity_adjoint(intensity_bar)#

Adjoint of intensity.

Parameters:

intensity_bar (Wavefront) – the gradient propagated to the intensity step

Returns:

gradient with respect to the complex wavefront before intensity was calculated

Return type:

ndarray

pad2d(Q, value=0, mode='constant', out_shape=None, inplace=True)#

Pad the wavefront.

Parameters:
  • array (ndarray) – source array

  • Q (float, optional) – oversampling factor; ratio of input to output array widths

  • value (float, optioanl) – value with which to pad the array

  • mode (str, optional) – mode, passed directly to np.pad

  • out_shape (tuple) – output shape for the array. Overrides Q if given. in_shape * Q ~= out_shape (up to integer rounding)

  • inplace (bool, optional) – if True, mutate this wf and return it, else create a new wf with cropped data

Returns:

wavefront with padded data

Return type:

Wavefront

crop(out_shape, inplace=True)#

Crop the wavefront to the centermost (out_shape).

Parameters:
  • out_shape (int or tuple of (int, int)) – the output shape (aka number of pixels) to crop to.

  • inplace (bool, optional) – if True, mutate this wf and return it, else create a new wf with cropped data if out-of-place, will share memory with self via overlap of data

Returns:

cropped wavefront

Return type:

Wavefront

free_space(dz=nan, Q=1, tf=None)#

Perform a plane-to-plane free space propagation.

Uses angular spectrum and the free space kernel.

Parameters:
  • dz (float) – inter-plane distance, millimeters

  • Q (float) – padding factor. Q=1 does no padding, Q=2 pads 1024 to 2048.

  • tf (ndarray) – if not None, clobbers all other arguments transfer function for the propagation

Returns:

the wavefront at the new plane

Return type:

Wavefront

free_space_adjoint(dz=nan, Q=1, tf=None)#

Apply the adjoint of free_space.

self carries the gradient at the output plane; the returned Wavefront carries the gradient at the input plane.

Parameters:
  • dz (float) – inter-plane distance used for the forward propagation, millimeters

  • Q (float) – padding factor used for the forward propagation

  • tf (ndarray) – if not None, clobbers all other arguments transfer function used for the forward propagation

Returns:

gradient at the input plane

Return type:

Wavefront

focus(efl, Q=2)#

Perform a “pupil” to “psf” plane propgation.

Uses an FFT with no quadratic phase.

Parameters:
  • efl (float) – focusing distance, millimeters

  • Q (float) – padding factor. Q=1 does no padding, Q=2 pads 1024 to 2048. To avoid aliasng, the array must be padded such that Q is at least 2 this may happen organically if your data does not span the array.

Returns:

the wavefront at the focal plane

Return type:

Wavefront

focus_adjoint(efl, Q=2)#

Apply the adjoint of focus.

self carries the gradient at the PSF plane; the returned Wavefront carries the gradient at the pupil plane.

Parameters:
  • efl (float) – focusing distance used for the forward propagation, millimeters

  • Q (float) – padding factor used for the forward propagation

Returns:

gradient at the pupil plane

Return type:

Wavefront

unfocus(efl, Q=2)#

Perform a “psf” to “pupil” plane propagation.

uses an FFT with no quadratic phase.

Parameters:
  • efl (float) – un-focusing distance, millimeters

  • Q (float) – padding factor. Q=1 does no padding, Q=2 pads 1024 to 2048. To avoid aliasng, the array must be padded such that Q is at least 2 this may happen organically if your data does not span the array.

Returns:

the wavefront at the pupil plane

Return type:

Wavefront

unfocus_adjoint(efl, Q=2)#

Apply the adjoint of unfocus.

self carries the gradient at the pupil plane; the returned Wavefront carries the gradient at the PSF plane.

Parameters:
  • efl (float) – un-focusing distance used for the forward propagation, millimeters

  • Q (float) – padding factor used for the forward propagation

Returns:

gradient at the PSF plane

Return type:

Wavefront

prepare_executor(efl, dx, samples, shift=(0, 0), kind='mdft')#

Build a reusable MDFT/CZT focus executor for this wavefront.

Wraps prepare_executor (which itself wraps coordinates_for_focus and the executor constructor). The interpretation of (dx, samples) depends on the wavefront’s space:

  • If self.space == ‘pupil’: self.dx and self.data.shape are the pupil-side parameters; dx (microns) and samples describe the focal plane.

  • If self.space == ‘psf’: self.dx and self.data.shape are the focal-side parameters; dx (mm) and samples describe the pupil plane.

The returned executor is in the focus orientation and works for either direction — pass it to focus_dft or unfocus_dft (which uses executor.adjoint for MDFT).

Parameters:
  • efl (float) – focal length, mm

  • dx (float) – sample spacing of the other plane (focal: microns; pupil: mm)

  • samples (int or (int, int)) – sample count of the other plane

  • shift ((float, float)) – (x, y) translation of the focal grid, microns

  • kind ({'mdft', 'czt'}, optional) – executor type to build. Default ‘mdft’.

Return type:

MDFT or CZT

focus_dft(executor)#

Pupil → PSF propagation via a precomputed executor.

Parameters:

executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

Returns:

the wavefront at the psf plane (dx from executor.focal_dx)

Return type:

Wavefront

focus_dft_adjoint(executor)#

Apply the adjoint of focus_dft.

self carries the gradient at the psf plane; the returned Wavefront carries the gradient at the pupil plane.

Parameters:

executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

Returns:

gradient at the pupil plane (dx from executor.pupil_dx)

Return type:

Wavefront

unfocus_dft(executor)#

PSF → pupil propagation via a precomputed executor.

Parameters:

executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

Returns:

wavefront at the pupil plane (dx from executor.pupil_dx)

Return type:

Wavefront

unfocus_dft_adjoint(executor)#

Apply the adjoint of unfocus_dft.

Parameters:

executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

Returns:

gradient at the focal plane (dx from executor.focal_dx)

Return type:

Wavefront

to_fpm_and_back(fpm, executor, return_more=False)#

Propagate to a focal plane mask, apply it, and return.

Parameters:
  • fpm (Wavefront or ndarray) – the focal plane mask

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

  • return_more (bool, optional) – if True, return (new_wavefront, field_at_fpm, field_after_fpm) else return new_wavefront

Returns:

new wavefront, [field at fpm, field after fpm]

Return type:

Wavefront, Wavefront, Wavefront

to_fpm_and_back_adjoint(fpm, executor, return_more=False, return_fpm_grad=False, field_at_fpm=None)#

Apply the adjoint of the to_fpm_and_back propagation.

self carries the gradient at the next pupil (output of the forward to_fpm_and_back); the returned Wavefront carries the gradient at the original input pupil.

Parameters:
  • fpm (Wavefront or ndarray) – the focal plane mask used in the forward propagation

  • executor (MDFT) – same operator as the forward call.

  • return_more (bool, optional) – if True, return (Eabar, Ebbar, intermediate) as Wavefronts else return Eabar

  • return_fpm_grad (bool, optional) – if True, also return the gradient with respect to fpm. Requires field_at_fpm from the matching forward propagation.

  • field_at_fpm (Wavefront or ndarray, optional) – focal-plane field before the FPM from the forward propagation

Returns:

gradient at the input pupil; optionally also the intermediate gradients and/or the gradient with respect to fpm

Return type:

Wavefront or tuple of Wavefront

babinet(lyot, fpm, executor, return_more=False)#

Propagate through a Lyot-style coronagraph using Babinet’s principle.

Parameters:
  • lyot (Wavefront or ndarray) – the Lyot stop; if None, equivalent to ones_like(self.data)

  • fpm (Wavefront or ndarray) – the focal plane mask (1 inside the spot); the Babinet complement 1 - fpm is formed internally (see Soummer et al 2007)

  • executor (MDFT) – bidirectional transform operator.

  • return_more (bool) – if True, return each plane in the propagation else return new_wavefront

Notes

if the substrate’s reflectivity or transmissivity is not unity, and/or the mask’s density is not infinity, babinet’s principle works as follows:

suppose we’re modeling a Lyot focal plane mask; rr = radial coordinates of the image plane, in lambda/d units mask = rr < 5 # 1 inside FPM, 0 outside (babinet-style)

now create some scalars for background transmission and mask transmission

tau = 0.9 # background tmask = 0.1 # mask

mask = tau - tau*mask + rmask*mask

the mask variable now contains 0.9 outside the spot, and 0.1 inside

Returns:

field after lyot, [field at fpm, field after fpm, field at lyot]

Return type:

Wavefront, Wavefront, Wavefront, Wavefront

babinet_adjoint(lyot, fpm, executor, field_at_fpm=None, field_at_lyot=None, return_fpm_grad=False, return_lyot_grad=False)#

Apply the adjoint of babinet.

Parameters:
  • lyot (Wavefront or ndarray) – the Lyot stop; if None, equivalent to ones_like(self.data)

  • fpm (Wavefront or ndarray) – the focal plane mask used in the forward propagation

  • executor (MDFT or CZT) – (semi-)arbitrary sampling fourier transform executor

  • field_at_fpm (Wavefront or ndarray, optional) – focal-plane field before the FPM from the matching forward call. Required when return_fpm_grad is True.

  • field_at_lyot (Wavefront or ndarray, optional) – pupil-plane field before the Lyot stop from the matching forward call. Required when return_lyot_grad is True.

  • return_fpm_grad (bool, optional) – if True, also return the gradient with respect to the original fpm argument passed to babinet.

  • return_lyot_grad (bool, optional) – if True, also return the gradient with respect to lyot.

Returns:

adjoint-propagated gradient; optionally followed by FPM and/or Lyot gradients in the order requested by the keyword names

Return type:

Wavefront or tuple of Wavefront

prysm.propagation.phase_prefix(wavelength)#

Phase prefix or scale factor such that mul w/ OPD in nm produces radians.