Optics backends#
Optical systems behind one interface.
The spatial PSF machinery (toycoronagraph.psf, toycoronagraph.spatial) only asks an optical system for the image of a point source: its throughput, its total light, and its intensity on blocks of the image pixel grid. So a different coronagraph, or a starshade, can be added as a new backend without touching that machinery:
@register_backend('my_system')
class MySystemBackend:
rotationally_symmetric = False # True allows the fast 'rotate' mode
bandlimit = None # cycles per lambda/D of the intensity vs. source
# position, if known (also needed by 'rotate')
def __init__(self, optics): ...
def source(self, x, y): ... # returns an object with .throughput, .total,
# .block(center, shape) and .frame()
def unocculted(self): ... # optional: the star without the starlight-suppression
# element (same kind of object; the contrast_peak unit)
and then Optics(‘my_system’, img_pixel, psf_range, ((‘name’, value), …), module=’my.package’). The module is imported when the kind is not registered yet (e.g. in parallel worker processes). Two systems come with the package: Optics.vortex (hcipy; VortexBackend below) and Optics.lazuli (the Lazuli space telescope computed with prysm; toycoronagraph.lazuli, imported only when used).
Conventions shared by every backend:
* positions are in lambda/D, with the star at the origin; image pixel (row, col) is at
x = (col - c) * pixel_scale, y = (row - c) * pixel_scale with c = (img_pixel - 1) / 2;
* intensities are in the package's units (hcipy intensity / normal_factor, as in
radial_psf_series): each pixel holds the fraction of the source's light entering the
aperture, so kernels, frames and totals are directly comparable;
* throughput is the source's total light relative to the same source without the
starlight-suppression element.
- class toycoronagraph.optics.Optics(kind, img_pixel, psf_range, params=(), module='toycoronagraph.optics')[source]#
Bases:
objectDescription of an optical system and of the image sampling (hashable, picklable).
- Variables:
kind (str) – Name of a registered backend, e.g. ‘vortex’.
img_pixel (int) – Number of pixels on one edge of the image.
psf_range (float) – Half-width of the image in lambda/D.
params (tuple) – The backend’s parameters as sorted (name, value) pairs.
module (str) – Module that registers the backend (imported if needed).
- classmethod vortex(charge, img_pixel, psf_range, lyot_mask_size=0.95)[source]#
An ideal vortex coronagraph with a circular aperture and a circular Lyot stop.
- Parameters:
charge (int) – Vortex charge (topological charge of the focal-plane mask).
img_pixel (int) – Number of pixels on one edge of the image.
psf_range (float) – Half-width of the image, in lambda/D.
lyot_mask_size (float) – Lyot stop diameter relative to the aperture diameter.
- Returns:
kind ‘vortex’ with params ((‘charge’, int), (‘lyot_mask_size’, float)).
- Return type:
- classmethod lazuli(charge, img_pixel, psf_range, wavelengths, weights, scene_wavelength, scene_diameter, pupil_samples, lyot_mask_size=0.95, opd='')[source]#
The Lazuli space telescope, alone or with an ideal vortex coronagraph, computed with prysm (toycoronagraph.lazuli; observe.optics_for builds it from a [[coronagraph]] table).
- Parameters:
charge (int) – 0 for the telescope alone; else the vortex charge (even).
img_pixel (int) – Number of pixels on one edge of the image.
psf_range (float) – Half-width of the image, in scene lambda/D (scene_wavelength / scene_diameter).
wavelengths (sequence of float) – Wavelengths of the PSF, in m.
weights (sequence of float) – Relative weight of each wavelength (normalised here to sum 1).
scene_wavelength (float) – The scene’s wavelength in m ([observation] wavelength); with scene_diameter it sets the lambda/D unit of source positions and of psf_range.
scene_diameter (float) – The scene’s telescope diameter in m ([observation] diameter).
pupil_samples (int) – Pupil samples across the aperture (the OPD map’s size when there is one).
lyot_mask_size (float) – Lyot stop diameter relative to the aperture (used with a charge).
opd (str) – OPD map file (see lazuli.read_opd); “” for none. Stored as an absolute path, with the SHA-1 of the file (opd_sha1), so cached PSFs follow the map’s content.
- Returns:
kind ‘lazuli’ (module ‘toycoronagraph.lazuli’); the wavelengths and weights are stored as tuples (hashable).
- Return type:
- param(name)[source]#
The value of one backend parameter.
- Parameters:
name (str) – Parameter name, e.g. ‘charge’.
- Returns:
The value stored in params (KeyError if there is none).
- property pixel_scale#
Image pixel size, in lambda/D per pixel (2*psf_range/img_pixel).
- Type:
float
- property centre#
Pixel coordinate of the star on both axes, (img_pixel-1)/2.
- Type:
float
- settings()[source]#
Flat dict of plain values (for .npz files and cache checks).
- Returns:
optics_kind, optics_module, img_pixel, psf_range, and ‘optics_<name>’ for every backend parameter.
- Return type:
dict
- classmethod from_settings(settings)[source]#
Rebuild from settings() (or from a saved spatial PSF model).
- Parameters:
settings (dict) – Holds the keys of settings(); other keys are ignored. Values may be numpy arrays (as loaded from .npz): 0-d ones become Python scalars (.item()), 1-D ones tuples (e.g. the wavelengths of Optics.lazuli). optics_module defaults to ‘toycoronagraph.optics’.
- Returns:
The described system (params sorted by name).
- Return type:
- exception toycoronagraph.optics.SamplingWarning[source]#
Bases:
UserWarningThe pupil is sampled too coarsely for the PSFs’ far wings near the image edge (see MIN_SAMPLING).
- toycoronagraph.optics.register_backend(kind)[source]#
Class decorator registering a backend under the given kind.
- Parameters:
kind (str) – Name used as Optics.kind.
- Returns:
The decorator; it returns the class unchanged.
- Return type:
callable
- toycoronagraph.optics.get_backend(optics)[source]#
The backend of an Optics, built once per process (each parallel worker keeps its own).
- Parameters:
optics (Optics) – The system; its module is imported if its kind is not registered yet.
- Returns:
The backend instance (e.g. VortexBackend).
- Raises:
ValueError – If the kind is still unknown after importing optics.module.
- class toycoronagraph.optics.PupilPlaneSource(backend, exit_field, throughput)[source]#
Bases:
objectA point source behind a pupil-plane system: holds the field leaving the last pupil (e.g. after the Lyot stop) and focuses it onto any block of the image pixel grid.
- Variables:
throughput (float) – The source’s light leaving the system relative to the same source without the starlight-suppression element.
- Parameters:
backend – The backend (needs optics, normal_factor, pupil_grid and prop).
exit_field (hcipy.Wavefront) – Field leaving the last pupil, on backend.pupil_grid.
throughput (float) – See the class attributes.
- property total#
Total light over the whole (infinite) focal plane (Parseval), in the package’s pixel units.
- Type:
float
- block(center, shape)[source]#
Intensity on a block of the image pixel grid (pixel size optics.pixel_scale).
- Parameters:
center (tuple) – (x, y) of the block’s centre, in lambda/D from the star.
shape (tuple) – (ny, nx) size of the block, in pixels.
- Returns:
(ny, nx) float64 intensity (rows = y, columns = x), in the package’s units.
- Return type:
np.ndarray
- class toycoronagraph.optics.VortexBackend(optics)[source]#
Bases:
objectIdeal vortex coronagraph: circular aperture, vortex focal-plane mask, circular Lyot stop.
Rotationally symmetric, and a source enters only through a tilt across the pupil, so the intensity is band-limited in the source position at D/lambda: ‘rotate’ mode is valid.
- Variables:
optics (Optics) – The system (kind ‘vortex’, params charge and lyot_mask_size).
pupil_grid – hcipy pupil grid, 2*img_pixel samples across 1.5 aperture diameters.
aperture – Circular aperture of diameter 1 on pupil_grid (4x supersampled edges).
prop (FraunhoferPropagator) – Pupil to the (img_pixel, img_pixel) image grid in lambda/D.
lyot_stop (Apodizer) – Circular Lyot stop of diameter lyot_mask_size.
coro (VortexCoronagraph) – The vortex mask (with its own internal propagation).
normal_factor (float) – Divisor turning hcipy intensities into the package’s units.
- Parameters:
optics (Optics) – An Optics of kind ‘vortex’ (e.g. Optics.vortex(…)).
- wavefront(x, y)[source]#
A point source at (x, y) lambda/D, as a tilted wavefront on the aperture.
- Parameters:
x (float) – Source position, in lambda/D from the star (x along columns, y along rows).
y (float) – Source position, in lambda/D from the star (x along columns, y along rows).
- Returns:
The aperture field with the source’s tilt, on pupil_grid.
- Return type:
hcipy.Wavefront
- source(x, y)[source]#
A point source at (x, y) lambda/D, propagated through the vortex and the Lyot stop.
- Parameters:
x (float) – Source position, in lambda/D from the star.
y (float) – Source position, in lambda/D from the star.
- Returns:
Its throughput is the light after the Lyot stop with the vortex relative to the light after the Lyot stop without it.
- Return type: