prysm.propagation#

Numerical optical propagation.

prysm.propagation.focus(wavefunction, Q)#

Propagate a pupil plane to a PSF plane.

Parameters:
  • wavefunction (numpy.ndarray) – the pupil wavefunction

  • Q (float) – oversampling / padding factor

Returns:

psf – point spread function

Return type:

numpy.ndarray

prysm.propagation.unfocus(wavefunction, Q)#

Propagate a PSF plane to a pupil plane.

Parameters:
  • wavefunction (numpy.ndarray) – the pupil wavefunction

  • Q (float) – oversampling / padding factor

Returns:

pupil – field in the pupil plane

Return type:

numpy.ndarray

prysm.propagation.focus_fixed_sampling(wavefunction, input_dx, prop_dist, wavelength, output_dx, output_samples, shift=(0, 0), method='mdft')#

Propagate a pupil function to the PSF plane with fixed sampling.

Parameters:
  • wavefunction (numpy.ndarray) – the pupil wavefunction

  • input_dx (float) – spacing between samples in the pupil plane, millimeters

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

  • wavelength (float) – wavelength of light

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

  • output_samples (int) – number of samples in the square output array

  • shift (tuple of float) – shift in (X, Y), same units as output_dx

  • method (str, {'mdft', 'czt'}) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

Returns:

data – 2D array of data

Return type:

numpy.ndarray

prysm.propagation.focus_fixed_sampling_backprop(wavefunction, input_dx, prop_dist, wavelength, output_dx, output_samples, shift=(0, 0), method='mdft')#

Propagate a pupil function to the PSF plane with fixed sampling.

Parameters:
  • wavefunction (numpy.ndarray) – the pupil wavefunction

  • input_dx (float) – spacing between samples in the pupil plane, millimeters

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

  • wavelength (float) – wavelength of light

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

  • output_samples (int) – number of samples in the square output array

  • shift (tuple of float) – shift in (X, Y), same units as output_dx

  • method (str, {'mdft', 'czt'}) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

Returns:

data – 2D array of data

Return type:

numpy.ndarray

prysm.propagation.unfocus_fixed_sampling(wavefunction, input_dx, prop_dist, wavelength, output_dx, output_samples, shift=(0, 0), method='mdft')#

Propagate an image plane field to the pupil plane with fixed sampling.

Parameters:
  • wavefunction (numpy.ndarray) – the image plane wavefunction

  • input_dx (float) – spacing between samples in the focal plane, microns

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

  • wavelength (float) – wavelength of light, microns

  • output_dx (float) – sample spacing in the output plane, mm

  • output_samples (int) – number of samples in the square output array

  • shift (tuple of float) – shift in (X, Y), same units as output_dx

  • method (str, {'mdft', 'czt'}) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

Returns:

  • x (numpy.ndarray) – x axis unit, 1D ndarray

  • y (numpy.ndarray) – y axis unit, 1D ndarray

  • data (numpy.ndarray) – 2D array of data

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.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.angular_spectrum(field, wvl, dx, z, Q=2, tf=None)#

Propagate a field via the angular spectrum method.

Parameters:
  • field (numpy.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 (numpy.ndarray) – if not None, clobbers all other arguments transfer function for the propagation

Returns:

2D ndarray of the output field, complex

Return type:

numpy.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:

numpy.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 (numpy.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 (numpy.ndarray) – array containing the amplitude

  • phase (numpy.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 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 (numpy.ndarray) – x coordinates that define the space of the lens, mm

  • y (numpy.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_backprop_phase(wf_bar)#

Gradient backpropagation through from_amp_and_phase -> phase.

Parameters:

wf_bar (Wavefront) – the gradient backpropagated up to wf

Returns:

gradient backpropagated to the phase of wf_in

Return type:

numpy.ndarray

intensity_backprop(intensity_bar)#

Gradient backpropagation through from_amp_and_phase -> phase.

Parameters:

intensity_bar (Wavefront) – the gradient backpropagated up to the intensity step

Returns:

gradient backpropagated to the complex wavefront before intensity was calculated

Return type:

numpy.ndarray

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

Pad the wavefront.

Parameters:
  • array (numpy.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 (numpy.ndarray) – if not None, clobbers all other arguments transfer function for the propagation

Returns:

the wavefront at the new 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

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

focus_fixed_sampling(efl, dx, samples, shift=(0, 0), method='mdft')#

Perform a “pupil” to “psf” propagation with fixed output sampling.

Uses matrix triple product DFTs to specify the grid directly.

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

  • dx (float) – output sample spacing, microns

  • samples (int) – number of samples in the output plane. If int, interpreted as square else interpreted as (x,y), which is the reverse of numpy’s (y, x) row major ordering

  • shift (tuple of float) – shift in (X, Y), same units as output_dx

  • method (str, {'mdft', 'czt'}) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

Returns:

the wavefront at the psf plane

Return type:

Wavefront

focus_fixed_sampling_backprop(efl, dx, samples, shift=(0, 0), method='mdft')#

Perform a “pupil” to “psf” propagation with fixed output sampling.

Uses matrix triple product DFTs to specify the grid directly.

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

  • dx (float) – pupil sampling, millimeters

  • samples (int) – number of samples in the pupil plane. If int, interpreted as square else interpreted as (x,y), which is the reverse of numpy’s (y, x) row major ordering

  • shift (tuple of float) – shift in (X, Y), same units as output_dx

  • method (str, {'mdft', 'czt'}) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

Returns:

the wavefront at the psf plane

Return type:

Wavefront

unfocus_fixed_sampling(efl, dx, samples, shift=(0, 0), method='mdft')#

Perform a “psf” to “pupil” propagation with fixed output sampling.

Uses matrix triple product DFTs to specify the grid directly.

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

  • dx (float) – output sample spacing, millimeters

  • samples (int) – number of samples in the output plane. If int, interpreted as square else interpreted as (x,y), which is the reverse of numpy’s (y, x) row major ordering

  • shift (tuple of float) – shift in (X, Y), same units as output_dx

  • method (str, {'mdft', 'czt'}) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

Returns:

wavefront at the pupil plane

Return type:

Wavefront

to_fpm_and_back(efl, fpm, fpm_dx=None, method='mdft', shift=(0, 0), return_more=False)#

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

This routine handles normalization properly for the user.

To invoke babinet’s principle, simply use to_fpm_and_back(fpm=1 - fpm).

Parameters:
  • efl (float) – focal length for the propagation

  • fpm (Wavefront or numpy.ndarray) – the focal plane mask

  • fpm_dx (float) – sampling increment in the focal plane, microns; do not need to pass if fpm is a Wavefront

  • method (str, {'mdft', 'czt'}, optional) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

  • shift (tuple of float, optional) – shift in the image plane to go to the FPM appropriate shift will be computed returning to the pupil

  • 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_backprop(efl, fpm, fpm_dx=None, method='mdft', shift=(0, 0), return_more=False)#

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

This routine handles normalization properly for the user.

To invoke babinet’s principle, simply use to_fpm_and_back(fpm=1 - fpm).

Parameters:
  • efl (float) – focal length for the propagation

  • fpm (Wavefront or numpy.ndarray) – the focal plane mask

  • fpm_dx (float) – sampling increment in the focal plane, microns; do not need to pass if fpm is a Wavefront

  • method (str, {'mdft', 'czt'}, optional) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

  • shift (tuple of float, optional) – shift in the image plane to go to the FPM appropriate shift will be computed returning to the pupil

  • 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

babinet(efl, lyot, fpm, fpm_dx=None, method='mdft', return_more=False)#

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

This routine handles normalization properly for the user.

Parameters:
  • efl (float) – focal length for the propagation

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

  • fpm (Wavefront or numpy.ndarray) – 1 - fpm one minus the focal plane mask (see Soummer et al 2007)

  • fpm_dx (float) – sampling increment in the focal plane, microns; do not need to pass if fpm is a Wavefront

  • method (str, {'mdft', 'czt'}) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

  • 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_backprop(efl, lyot, fpm, fpm_dx=None, method='mdft')#

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

Parameters:
  • efl (float) – focal length for the propagation

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

  • fpm (Wavefront or numpy.ndarray) – np.conj(1 - fpm) one minus the focal plane mask (see Soummer et al 2007)

  • fpm_dx (float) – sampling increment in the focal plane, microns; do not need to pass if fpm is a Wavefront

  • method (str, {'mdft', 'czt'}) – how to propagate the field, matrix DFT or Chirp Z transform CZT is usually faster single-threaded and has less memory consumption MDFT is usually faster multi-threaded and has more memory consumption

Returns:

back-propagated gradient

Return type:

Wavefront