prysm v0.20¶
Summary¶
Version 20 of prysm is the largest breaking release the library has ever had. Your programs will be more a bit verbose when written in this style, but they will be more clear, contain fewer bugs, and run faster. This version marks prysm transitioning from an extremely object oriented style to a data oriented style. The result is that code is more direct, and there is less of it. Side benefits are that by deferring the caches that used to help keep prysm fast to the user level, the user is in control over their program’s memory usage. A new high level object oriented API may be produced at some point, likely in a separate package.
This version will produce one more zero point release (0.21) for cleanup after longer experience in this style, after which version 1 will be released. In addition to the breaking changes, this release brings landmark additions:
2D-Q polynomials also known as Forbes polynomials, Chebyshev, Legendre, and Hopkins polynomials,
Sophistocated, highly optimized tools for segmented apertures.
Tilted plane projections for DMs and other oblique elements
Realistic detector noise modeling
Bayer focal plane routines
As perhaps a motivational comment, the official model of the Low Order Wavefront Sensing and Control (LOWFS/C) system on the Roman Coronagraph Instrument was ported from prysm v0.19 to v0.20, and runs 12x faster on CPU and 6x faster on GPU. A total of two new lines of code were gained in aggregate. The port took approximately two person-hours. The model now runs in 430 microseconds per wavelength through the 7-plane model; over twice faster than the actual realtime WFSC system!
The remainder of this page will be divided by logical unit of function, then sub-divided between breaking changes and new features.
Changes¶
Contents
bayer¶
This is a new submodule, for working with bayer imaging systems. It provides a complete toolkit for both forward modeling and processing of bayer images, real or synthetic. The following functions are included:
wb_prescale()
for performing white-balance pre-scaling to mosaiced data in-place.wb_scale()
for performing white-balance scaling to RGB data in-place.composite_bayer()
for compositing dense color plane data into a bayer mosaic. This function is used to synthesize “raw” bayer imagery in a forward model.decomposite_bayer()
for “sifting” bayer subplanes from a mosaiced image.recomposite_bayer()
the inverse operation of decomposite_bayer, for taking bayer subplanes and re-mosaicing them.composite_bayer
works with fully dense data with (m, n) pixels per color plane.recomposite_bayer
works with sparse data with (m/2, n/2) pixels per color plane.demosaic_malvar()
for performing Malvar-He-Cutler demosaicing.
conf¶
All
Labels
related code has been removed. There is no substitute.Unit munging has been removed; wavelengths are no longer astropy units but are floats with units of microns again.
The following parameters have been removed from
Config
:Q
wavelength
interpolation
unit_format
show_units
phase_xy_unit
phase_z_unit
image_xy_unit
image_z_unit
mtf_xy_unit
mtf_z_unit
ptf_xy_unit
ptf_z_unit
pupil_labels
interferogram_labels
convolvable_labels
mtf_labels
ptf_labels
psd_labels
convolution¶
This module has been substantially rewritten. Up to version 0.19, a Convolvable
object was the key to the convolution API, which was capable of forming prototypical FFT based convolution, as well as convolution with various analytic blurs, and convolution of datasets which were not equally sampled. The API has been significantly simplified and disentangled in this version.
Breaking:
Convolvable
no longer exists.the
deconv
method for Wiener-Helstrom deconvolution no longer exists
The new API is comprised of:
conv()
, for convolving an object with a PSF.apply_transfer_functions()
, for blurring an object with N transfer functions.
coordinates¶
GridCache
and its variable transformation functions have been deleted. The functionality is deferred to the user, who can quite naturally write code that reuses grids.make_xy_grid()
has had its signature changed from(samples_x, samples_y, radius=1)
to(shape, *, dx, diameter, grid=True)
. shape auto-broadcasts to 2D and dx/diameter are keyword only. grid controls returning vectors or a meshgrid.make_xy_grid
is now FFT-aligned (always containing a zero sample).make_rho_phi_grid()
has been removed, combinemake_xy_grid()
withcart_to_polar()
.New warping function suite used to work with non-normal incidence beams (e.g., DMs, OAPs)
degredations¶
The
Smear
class has been removed, and replaced withsmear_ft()
The
Jitter
class has been removed, and replaced withjitter_ft()
detector¶
The
Detector
class has been reworked, and its purpose changed. Previously, it existed to impart blur into a system as would be experienced given a particular pixel design. It now exists to model noise. Expect no API compatibility between v0.19 and v0.20.The
OLPF
class has been removed, and replaced witholpf_ft()
The
PixelAperture
class has been removed, and replaced withpixel_ft()
bindown_with_units()
was removed.bindown()
will now error if the array dimensions are not an integer multiple of the binning factor. It now supports ND data, with possible unique factors per dimension.tile()
has been added, which is the adjoint operation to bindown. It replicates the elements of an arrayfactor
times, and has the same ND support bindown now does.
fttools¶
The matrix DFT executor was mildly reworked. There is no more
norm
option. The code was modified such that a forward-reverse calculation that goes to any domain containing the majority of the spectrum of the signal and returns to the same input domain will be energy conserving automatically. This means thatidft2(dft2(x)) ~= x
geometry¶
The geometry module was rewritten. The object oriented mask interface and MaskCache
have been removed. All functions now take x, y
or r, t
args as appropriate, instead of samples
. The arguments now all have consistent units.
Higher side count regular polygon functions have been removed, use
regular_polygon()
directly:heptagon()
octagon()
nonagon()
decagon()
hendecagon()
dodecagon()
trisdecagon()
inverted_circle()
was removed, call~circle(...)
for equivalent output.
io¶
write_zygo_ascii()
no longer takes ahigh_phase_res
parameter. It did not do anything before and has been removed, as it is not likely prysm needs to support ancient version of MetroPro that are incompatible with that convention.the dat and datx readers no longer flip the phase and intensity data upside down. They used to do this due to prysm explicitly having an origin in lower left convention, but v0.20 has no enforced convention for array orientation, and the flipud is an unexpected behavior in this paradigm.
mathops¶
The several quasi-identical classes to shim over numpy and scipy were removed and replaced with a single BackendShim
type. The engine
variable no longer exists. Users should overwrite prysm.backend.np._srcmodule
, as well as the same for fft, ndimage, etc.
interferogram¶
The interferogram module is largely unchanged. With the removal of astropy units, the user must manage their own units. Phase is loaded from dat/datx files in units of nm.
prysm.interferogram.Interferogram.fit_zernikes()
was removed, use lstsq from the polynomials submodule withInterferogram.data, Interferogram.x, Interferogram.y, Interferogram.r, Interferogram.t
directly, minding spatial axis normalization.prysm.interferogram.Interferogram.remove_piston_tiptilt_power()
andprysm.interferogram.Interferogram.remove_piston_tiptilt()
have been removed, callremove_piston()
, etc, in sequence.prysm.interferogram.Interferogram.mask()
now accepts arrays only.filter()
has returned to stay and uses a new 2D filter design method behind the scenes. The out-of-band rejection is approximately 50dB higher for typical sized arrays.
jacobi¶
See the new polynomials module.
objects¶
The changes to this module are similar to geometry. Functions no longer take a samples argument, but take x/y or r,t grids directly. Objects which have analytic fourier transforms retain functions to compute those.
Pinhole
has been removed, usepinhole()
andpinhole_ft()
SiemensStar
has been removed, usesiemensstar()
TiltedSquare
has been removed, usetiltedsquare()
SlantedEdge
has been removed, useslantededge()
Chirp
was removed without replacementGrating
was removed without replacementGratingArray
was removed without replacement
otf¶
The OTF module was maed data oriented instead of object oriented, in line with the rest of the changes to prysm in this release. Note that the three functions below accept both arrays, and RichData
-like objects with data and dx attributes, and return RichData
objects.
MTF
was removed, usemtf_from_psf()
PTF
was removed, useptf_from_psf()
OTF
was removed, useotf_from_psf()
polynomials¶
prysm’s support of polynomials has been unified under a single package. The polynomials package is now the fastest known for the supported polynomials, e.g. beating POPPY by more than a factor of 100 on large collections of Zernike polynomials. This speed introduces mild complexity into the API, which must be appreciated. For a complete tutorial see Ins and Outs of Polynomials.
prysm.polynomials/
- top level routines, common to any basis set:lstsq()
for least-squares fitting of 2D basis functions to data
sum_of_2d_modes()
for (weighted) summing 2D modes. This function does whatzernike_compose
orzernike_sum
does in other packages, once the user has the basis set in hand.
sum_of_xy_modes()
some polynomial bases, like the Legendre and Chebyshev polynomials, are separable in the x, y dimensions. This function reflects that, and reduces the time complexity from (m*n) per mode to (m+n) per mode. This can bring, for example, a 1000x speedup for 1024x1024 arrays.mode_1d_to_2d()
for broadcasting a separable 1D mode to a 2D array
separable_2d_sequence()
for computing a set of separable polynomials, such as the Legendre or Chebyshev polynomials, in 2D, with optimal time complexity.
/zernike
for Zernike polynomials. These functions are all re-exported at the root ofpolynomials/
:
Stand-alone functions for the first few terms have been removed, use zernike_nm with one of the naming convention functions to replace the behavior:
piston()
tip()
tilt()
defocus()
primary_astigmatism_00()
primary_astigmatism_45()
primary_coma_y()
primary_coma_x()
primary_spherical()
primary_trefoil_x()
primary_trefoil_y()
e.g.,
for primary_coma_y
, eitherzernike_nm(3, 1, ...)
orzernike_nm(*zernike_noll_to_nm(7), ...)
classes
FringeZernike
,NollZernike
,ANSI1TermZernike
,ANSI2TermZernike
have been removed. Combinezernike_nm()
with one of the naming functions to replace the phase synthesis behavior.
zernike_norm()
for computing the norm of a given Zernike polynomial, given the ANSI order (n, m).
zero_separation()
for computing the minimum zero separation on the domain [0,1] for a Zernike polynomial, given the ANSI order (n, m).
zernike_nm()
for computing a Zernike polynomial, given the ANSI order (n, m).
zernike_nm_sequence()
– use to compute a series of Zernike polynomials. Much faster thanzernike_nm()
in a loop. Returns a generator, which you may want to exhaust into a list or into a list, then an array.
nm_to_fringe()
for converting ANSI (n, m) indices to FRINGE indices, which begin with Z1 for piston.
nm_to_ansi_j()
for converting ANSI (n, m) indices to ANSI j indices (dual to mono index).
noll_to_nm()
for converting the Noll indexing scheme to ANSI (n, m).
fringe_to_nm()
for converting the FRINGE indexing scheme to ANSI (n, m).
zernikes_to_magnitude_angle_nmkey()
for converting a sequence of[(n1, m1, coef1), ...]
to a dictionary keyed by(n, |m|)
with the magnitude and angle as the value. This basically converts the “Cartesian” Zernike polynomials to a polar representation.
zernikes_to_magnitude_angle()
for doing the same aszernike_to_magnitude_angle_nmkey
, but with dict keys of the form “Primary Coma” and so on.
nm_to_name()
for converting ANSI (n, m) indices to a friendly name like “Primary Trefoil”.
top_n()
for identifying the largest N coefficients in a Zernike series.
barplot()
for making a barplot of Zernike polynomials, based on their mono index (Z1..Zn)
barplot_magnitudes()
for doing the same asbarplot
, but with labels of “Tilt”, “Power”, and so on.
/cheby
for Chebyshev polynomials. These functions are all re-exported at the root ofpolynomials/
:
cheby1()
, the Chebyshev polynomial of the first kind of order n
cheby2()
, the Chebyshev polynomial of the second kind of order n
cheby1_sequence()
, a sequence of Chebyshev polynomials of the first kind of orders ns; much faster thancheby1
in a loop.
cheby2_sequence()
, a sequence of Chebyshev polynomials of the second kind of orders ns; much faster thancheby2
in a loop.
/legendre
for Legendre polynomials. These functions are all re-exported at the root ofpolynomials/
:
legendre()
, the Legendre polynomial of order n
legendre_sequence()
, a sequence of Legendre polynomials of orders ns; much faster thanlegendre
in a loop.
/jacobi
for Jacobi polynomials. These functions are all re-exported at the root ofpolynomials/
:
jacobi()
, the Jacobi polynomial of order n with weight parameters alpha and beta
jacobi_sequence()
, a sequence of Jacobi polynomials of orders ns with weight parameters alpha and beta; much faster thanjacobi
in a loop.
/qpoly
for Q (Forbes) polynomials. These functions are all re-exported at the root ofpolynomials/
:
Qbfs()
, the Q best fit sphere polynomial of order n, at normalized radius x.
Qbfs_sequence()
, the Q best fit sphere polynomials of orders ns, at normalized radius x. Much faster thanQbfs
in a loop.
Qcon()
, the Q best fit sphere polynomial of order n, at normalized radius x.
Qcon_sequence()
, the Q conic polynomials of orders ns, at normalized radius x. Much faster thanQcon
in a loop.
Q2d()
, the 2D-Q polynomials of order (n, m). Note that the API is made the same as Zernike by intent, so the sign of m controls whether it is a cosine (+) or sine (-), not a and b coefficients.
Q2d_sequence()
, the 2D-Q polynomials of orders [(n1, m1), …]. Much faster thanQ2d
in a loop.
propagation¶
prop_pupil_plane_to_psf_plane()
andprop_pupil_plane_to_psf_plane_units()
have been removed, they were deprecated and marked for removal.Any argument which was
sample_spacing
is nowdx
.Any
coherent
argument was removed, all routines now explicitly work with fields (seeprysm.propagation.Wavefront.intensity()
).Any
norm
argument was removed.Units are no longer fed through astropy units, but are mm for pupil plane dimensions, um for image plane dimensions, and nm for OPD.
Angular spectrum (free space) propagation now allows the transfer function to be computed once and passed as the
tf
kwarg, accelerating repetitive calculations.See also:
~prysm.propagation.angular_spectrum_transfer_function
The
focus_units
andunfocus_units
functions were removed. Since prysm largely bookkeepsdx
now, they are superfluous.
psf¶
The PSF module has changed from being a core part of propagation usage to a module purely for computing criteria of PSFs, such as fwhm, centroid, etc.
PSF
has been removedall metrics and measurements have moved from being methods of PSF to top-level functions:
the Airy Disk can be synthesized with
airydisk()
, or its transfer function withairydisk_ft()
pupil¶
this entire submodule has been removed. To synthesize pupil functions which have given phase and amplitude, combine prysm.geometry with prysm.polynomials or other phase synthesis code. The function
from_amp_and_phase()
largely replicates the behavior of thePupil
constructor, with the user generating their own phase and amplitude arrays.
segmented¶
This is a new module for working with segmented systems. It contains routines for rasterizing segmented apertures and for working with per-segment phase errors. prysm’s segmented module is considerably faster than anything else in open source, and is approximately constant time in the number of segments. For the TMT aperture, it is more than 100x faster to rasterize the amplitude than POPPY. For more information, see This post. The Notable Telescope Apertures page also contains example usage.
rasterizes the pupil upon initialization and prepares local coordinate systems for each segment.
A future update will bring fast per-segment phase errors with a clean API.
qpoly¶
See the new polynomials module.
util¶
This module is likely to move to prysm.stats in a future release.
is_odd()
andis_power_of_2()
have been moved to the mathops module.
wavelengths¶
This data-only module has been changed to contain all quantities in units of microns, now that prysm no longer uses astropy.
zernike¶
See the new polynomials module.