Scene#

The scene: the image before the coronagraph, built from source modules.

scene = Scene.from_file("eps_eri.toml")                     # from a parameter file
scene = Scene(wavelength=500e-9, diameter=6.0, sampling=4, fov=2.0,
              star=Star(distance=3.22, radius=0.73))          # or in Python
scene.add(Wind(mdot=6e-13))                                  # any Source module, yours too
images = scene.render()                                      # {name: image}, and scene.total

Each component is rendered by its module (centred on the star, on its own grid, in its own unit), put per pixel (Jy, or the fraction of the star’s flux), resampled onto the scene grid with the flux conserved, and converted to the scene’s internal unit (units.choose_internal): “Jy/arcsec^2” when the star’s flux is known (or every component is physical), else “contrast_pixel” (the fraction of the star’s flux per pixel). Point sources (planets) are not images: they are kept as positions and fluxes (Scene.points).

Conventions: images are (N, N) float64 arrays with the star at pixel ((N-1)/2, (N-1)/2); rows are +y (upwards, as in FITS; plotted with origin=”lower”), columns +x; angles are measured from +x towards +y. The shared quantities (grid, wavelength, star) are resolved once by toycoronagraph.params.

Also here: the plotting helpers shared with toycoronagraph.observe (show_image, mark_points, point_labels, blank_panel, radial_profile, plot_profiles) and the scene FITS writer (write_scene, image_hdu).

class toycoronagraph.scene.Grid(size, pixel_scale, wavelength, diameter)[source]#

Bases: object

The simulated image: size x size pixels of pixel_scale arcsec, star at pixel (size-1)/2.

Variables:
  • size (int) – Pixels on one edge of the (square) image.

  • pixel_scale (float) – Pixel size in arcsec.

  • wavelength (float) – Observing wavelength in m.

  • diameter (float) – Telescope aperture diameter D in m.

property lambda_d#

lambda/D in arcsec.

Type:

float

property sampling#

Pixels per lambda/D.

Type:

float

property visual_range#

Image width in lambda/D (twice the Optics psf_range).

Type:

float

property pixel_area#

Area of one pixel in arcsec^2.

Type:

float

property peak_norm#

The peak of an ideal circular aperture’s PSF (no coronagraph, no Lyot stop) as a fraction of the star’s light per pixel, pi/4 (pixel_scale / lambda_d)^2: the contrast_peak reference of input images (final images use their coronagraph’s own, Coronagraph.peak_norm).

Type:

float

property extent#

[left, right, bottom, top] pixel edges in arcsec from the star (for imshow’s extent).

Type:

list

coordinates()[source]#

Offsets from the star of the pixel centres.

Returns:

(x, y), each a (size, size) float64 array in arcsec; rows are y (upwards, as in FITS), columns x (np.meshgrid order: x varies along axis 1, y along axis 0).

Return type:

tuple

pixel(radius, angle)[source]#

Pixel position of a point given in polar coordinates around the star.

Parameters:
  • radius (float or np.ndarray) – Distance from the star in arcsec.

  • angle (float or np.ndarray) – Angle in rad, from +x towards +y.

Returns:

(row, column) as floats (not rounded; arrays if the inputs are), rows = +y.

Return type:

tuple

axis(unit='arcsec', distance=None)[source]#

Scale factor and label for plot axes in another unit.

Parameters:
  • unit (str) – “arcsec”, “mas”, “lambda/D”, “au” or “pixel”.

  • distance (float) – The star’s distance in pc; needed for “au” (1 arcsec at d pc is d au).

Returns:

(factor, label): multiply arcsec by factor (float) to get unit; label is unit (str).

Return type:

tuple

Raises:

ParamError – “au” without a distance, or an unknown unit.

class toycoronagraph.scene.Star(distance=None, radius=None, temperature=None, flux_jy=None)[source]#

Bases: object

The star / system. Any field may be None (unknown).

Variables:
  • distance (float) – Distance in pc.

  • radius (float) – Stellar radius in R_sun.

  • temperature (float) – Effective temperature in K (blackbody flux, with radius and distance).

  • flux_jy (float) – Flux density in Jy at the scene’s wavelength (overrides the blackbody).

flux_at(wavelength)[source]#

The star’s flux density at a wavelength.

Parameters:

wavelength (float) – Wavelength in m.

Returns:

flux_jy if set, else the blackbody flux in Jy (needs temperature, radius and distance); None if neither is known.

Return type:

float or None

toycoronagraph.scene.resample(values, scale_in, scale_out, size_out)[source]#

Resample per-pixel values onto another grid centred on the same star, conserving the flux.

The values must be per pixel (fluxes, not surface brightnesses): each input pixel’s flux is shared among the output pixels it overlaps, in proportion to the overlap area (integer factors give block sums). The 2-D overlap is separable, so it is one 1-D weight matrix w applied to both axes: w @ values @ w.T. Light outside the output grid is dropped.

Parameters:
  • values (np.ndarray) – (n_in, n_in) per-pixel values, star at pixel (n_in-1)/2.

  • scale_in (float) – Input pixel size in arcsec.

  • scale_out (float) – Output pixel size in arcsec.

  • size_out (int) – Output pixels on one edge.

Returns:

(size_out, size_out) float64 per-pixel values, star at pixel (size_out-1)/2.

Return type:

np.ndarray

class toycoronagraph.scene.Scene(star=None, **settings)[source]#

Bases: object

Components (source modules) on one grid, in one unit; see the module docstring.

Variables:
  • sections (dict) – Parameter sections {section: {key: value}} given by the user.

  • components (list) – The params.Component of each source module (enabled or not).

  • coronagraphs (list) – [[coronagraph]] tables of the parameters (used by observe()).

  • params (Params or None) – Checked parameters; built from the above by build() (None until then, and reset by add()).

Set by build():

grid (Grid): The scene grid.
star (Star): The resolved star.

Set by render():

images (dict or None): {component name: (N, N) float64 image in internal_unit}; None until
    rendered (and after add()).
points (dict): Point-source components {name: (positions, fluxes)}: positions a list of
    (radius arcsec, angle rad), fluxes a 1-D array of each source's flux per pixel area, in
    internal_unit (multiply by grid.pixel_area for Jy, or for the fraction of the star's flux).
total (np.ndarray): (N, N) sum of `images` (zeros if there is none; point sources are not in it).
internal_unit (str): "Jy/arcsec^2" or "contrast_pixel".
star_flux (float or None): The star's flux density in Jy at the wavelength (None: unknown).
families (dict): {name: "physical" or "relative"} of every image and point-source component.
units (dict): {name: the unit the module gave its image in} (images only).
origins (dict): {name: where the image came from, e.g. a file name} (images only).
component_of (dict): {name: the params.Component it came from} (images and point sources).
notes (list): Notes and warnings (str) from the parameters and the rendering.
Parameters:
  • star (Star or dict) – The star (distance pc, radius R_sun, temperature K or flux_jy Jy); None fields are left out (so the sources or defaults may provide them).

  • settings – [observation] / [grid] keys (wavelength, diameter, size, pixel_scale, sampling, fov, …), and other sections as dicts (method={…}, checks={…}, …).

Raises:

ParamError – A setting that is neither an [observation] / [grid] key nor a section given as a dict.

classmethod from_file(path)[source]#

A scene from a parameter file (see toycoronagraph.params).

Parameters:

path (str) – The .toml parameter file.

Returns:

Not rendered yet.

Return type:

Scene

classmethod from_params(p)[source]#

A scene from loaded parameters.

Parameters:

p (Params) – From toycoronagraph.params.load (its sections, components and coronagraphs are used).

Returns:

Not rendered yet.

Return type:

Scene

add(source, name='auto', scale=1.0, enabled=True, method='auto')[source]#

Add a component; the parameters and the images are built again when next needed.

Parameters:
  • source (Source) – A source module instance (toycoronagraph.sources).

  • name (str) – Component name (FITS extension, plots); “auto”: the module’s kind (ring, ring_2, …).

  • scale (float) – Factor applied to the component’s image or fluxes.

  • enabled (bool) – Whether the component is rendered.

  • method (str) – “auto”, “circular” or “spatial”: this component’s method in observe().

Returns:

source (to keep a handle on it).

Return type:

Source

build()[source]#

Resolve the grid, wavelength and star with what the sources provide (every disagreement is checked).

Sets self.params (if None), self.grid and self.star.

Raises:

ParamError – Conflicting or missing parameters (from Params.resolve).

render(verbose=True)[source]#

Render every enabled component onto the grid, in the internal unit.

Each module’s image is put per pixel (units.per_pixel), resampled onto the grid if it has another pixel size or field ([grid] resample), scaled by the component’s scale and converted to the internal unit. Point-source modules give positions and fluxes instead.

Parameters:

verbose (bool) – Print the notes and a one-line summary of the scene.

Returns:

{component name: (N, N) float64 image in self.internal_unit}; also sets self.total, self.points, self.internal_unit, self.star_flux, self.families, self.units, self.origins, self.component_of and self.notes (see the class docstring).

Return type:

dict

Raises:
  • ParamError – An image covers another field than the grid while [grid] resample = false.

  • UnitError – The components cannot be put in one unit (units.choose_internal).

in_unit(image, unit, star_flux=None)[source]#

An image of this scene in another output unit (see units.convert_image).

Parameters:
  • image (np.ndarray) – (N, N) image in self.internal_unit.

  • unit (str) – “Jy/arcsec^2”, “Jy/pixel”, “contrast_pixel” or “contrast_peak” (relative to the ideal aperture’s PSF peak, Grid.peak_norm); None or “auto”: unchanged.

  • star_flux (float or Star) – The star’s flux in Jy, or a Star (its flux at the scene’s wavelength), to convert a contrast scene to a brightness (and back) without rendering again; None: self.star_flux.

Returns:

(N, N) image in unit (the same array if no conversion is needed).

Return type:

np.ndarray

Raises:

UnitError – The conversion needs the star’s flux and it is unknown.

plot(log=None, unit=None, axis=None, path=None, show=True, dpi=None, log_range=None, star_flux=None, **kwargs)[source]#

Plot each component and the total side by side (rendering the scene first if needed).

The total panel is added when there are several images or point sources; point sources are marked on it with their flux.

Parameters:
  • log (bool) – Log colour scale. None here and below: the [display] setting (see display_setting).

  • unit (str) – Output unit (see in_unit); “auto”: the internal unit.

  • axis (str) – Axis unit (see Grid.axis).

  • path (str) – Save the figure there; None: not saved.

  • show (bool) – Show the figure (else it is closed).

  • dpi (int) – Resolution of the saved file.

  • log_range (float) – Log scale: decades shown below each panel’s peak.

  • star_flux (float or Star) – See in_unit.

  • **kwargs – Passed to matplotlib’s imshow for every panel, e.g. cmap=”magma”.

Returns:

The figure.

Return type:

matplotlib.figure.Figure

plot_profiles(log=None, unit=None, axis=None, path=None, show=True, dpi=None, star_flux=None, extra=None, log_range=None, **kwargs)[source]#

Azimuthal mean of each component (and of the total, if several) against the distance from the star.

Parameters:
  • log (bool) – Log-log axes (else linear, both from 0). None here and below: the [display] setting.

  • unit (str) – Output unit (see in_unit); “auto”: the internal unit.

  • axis (str) – Distance unit (see Grid.axis).

  • path (str) – Save the figure there; None: not saved.

  • show (bool) – Show the figure (else it is closed).

  • dpi (int) – Resolution of the saved file.

  • star_flux (float or Star) – See in_unit.

  • extra (dict) – More curves {label: (radius in arcsec, values in unit)}, dashed.

  • log_range (float) – Log axes show log_range + PROFILE_DECADES decades below the highest point.

  • **kwargs – Passed to matplotlib’s plot for every curve, e.g. lw=2.

Returns:

The figure.

Return type:

matplotlib.figure.Figure

write(path, overwrite=False)[source]#

Save the components as a scene FITS file (readable with kind = “scene_fits”; see write_scene).

Point sources are not written (Result.save adds them as a POINTS table).

Parameters:
  • path (str) – The FITS file to write.

  • overwrite (bool) – Replace an existing file (else astropy raises OSError).

toycoronagraph.scene.display_setting(params, key, value)[source]#

A plot setting: the value given to the plot, else [display] <key> of the parameters.

Parameters:
  • params (Params or None) – The scene’s parameters; None: the declared [display] defaults.

  • key (str) – The [display] key: “unit”, “log”, “log_range”, “axis” or “dpi”.

  • value – The value given to the plot; None: not given.

Returns:

The setting.

toycoronagraph.scene.finish(fig, path, show, dpi)[source]#

The end of every plot: save the figure (if path is given), then show it or close it.

Parameters:
  • fig (matplotlib.figure.Figure) – The figure.

  • path (str) – Save the figure there; None: not saved.

  • show (bool) – Show the figure (else it is closed).

  • dpi (int) – Resolution of the saved file.

Returns:

The figure.

Return type:

matplotlib.figure.Figure

toycoronagraph.scene.show_image(ax, fig, data, grid, axis='arcsec', distance=None, log=False, log_range=5, label='', cmap='gnuplot', vmin=None, vmax=None, **kwargs)[source]#

Show an image on its grid (origin=”lower”: rows are +y), with a colour bar.

Log scale: log10 of the positive pixels (others are blank, drawn in the darkest colour), from the 99.99th percentile (a lone extreme pixel, e.g. a wind’s star pixel, does not set the scale) down log_range decades. Linear scale of non-negative data: from 0.

Parameters:
  • ax (matplotlib.axes.Axes) – Where to draw.

  • fig (matplotlib.figure.Figure) – The figure (for the colour bar).

  • data (np.ndarray) – (N, N) image on grid.

  • grid (Grid) – The image’s grid.

  • axis (str) – Axis unit (see Grid.axis).

  • distance (float) – The star’s distance in pc (for axis “au”).

  • log (bool) – Log colour scale.

  • log_range (float) – Log scale: decades shown below the top.

  • label (str) – Colour bar label (e.g. the unit); “log10 “ is put in front on a log scale.

  • cmap (str or Colormap) – The colour map.

  • vmin (float) – Lower colour limit (log10 of the value on a log scale); None: automatic.

  • vmax (float) – Upper colour limit (log10 of the value on a log scale); None: automatic.

  • **kwargs – Passed to matplotlib’s imshow, e.g. interpolation=”nearest”.

Returns:

The axis factor (arcsec -> axis units), e.g. for mark_points.

Return type:

float

toycoronagraph.scene.point_labels(points, unit, pixel_area, shown=None, star_flux=None)[source]#

Labels of point sources for mark_points: each source’s flux in Jy, or as a fraction of the star’s.

Parameters:
  • points (dict) – {name: (positions, fluxes)}: positions a list of (radius arcsec, angle rad), fluxes each source’s flux per pixel area in unit (scalar or 1-D array).

  • unit (str) – The internal unit, “Jy/arcsec^2” or “contrast_pixel”.

  • pixel_area (float) – Pixel area in arcsec^2.

  • shown (str) – The unit of the plot: a contrast unit labels fractions of the star’s flux, a Jy unit fluxes in Jy (converted with star_flux when needed and known); None: unit’s.

  • star_flux (float) – The star’s flux in Jy (None: unknown; the labels then stay in unit’s family).

Returns:

{name: (positions, labels)}, labels a list of str such as “planet 5e-05 Jy”.

Return type:

dict

toycoronagraph.scene.mark_points(ax, points, factor=1.0)[source]#

Mark point sources with a cyan cross and a label.

Parameters:
  • ax (matplotlib.axes.Axes) – Where to draw (axes in arcsec times factor, y upwards).

  • points (dict) – {name: (positions, labels)}: positions a list of (radius arcsec, angle rad from +x towards +y), labels a list of str (see point_labels).

  • factor (float) – Axis factor from arcsec (see Grid.axis / show_image).

toycoronagraph.scene.blank_panel(ax, grid, axis='arcsec', distance=None)[source]#

An empty (black) panel on the grid’s axes, e.g. for point sources, which have no image.

Parameters:
  • ax (matplotlib.axes.Axes) – Where to draw.

  • grid (Grid) – The grid giving the axis limits.

  • axis (str) – Axis unit (see Grid.axis).

  • distance (float) – The star’s distance in pc (for axis “au”).

Returns:

The axis factor (arcsec -> axis units).

Return type:

float

toycoronagraph.scene.radial_profile(image, grid)[source]#

Azimuthal mean in 1-pixel-wide rings around the star.

Each pixel goes to the ring of its distance from the star rounded to whole pixels; empty rings are left out.

Parameters:
  • image (np.ndarray) – (N, N) image on grid.

  • grid (Grid) – The image’s grid.

Returns:

(radius, mean): 1-D float64 arrays of the same length; radius is the mean distance of each ring’s pixels from the star in arcsec (0 for the star pixel of an odd grid), mean the ring’s mean value (in the image’s unit).

Return type:

tuple

toycoronagraph.scene.plot_profiles(ax, curves, grid, axis='arcsec', distance=None, log=True, label='', extra=None, styles=None, log_range=8, legend=True, **kwargs)[source]#

Plot radial profiles (radial_profile) of images against the distance from the star.

Curves named “total” or “input” are drawn thicker. A curve’s style: these defaults, then its entry in styles, then kwargs (every curve). Log: log-log axes, at most log_range decades below the highest point (points at radius 0 or with a non-positive mean are left out; linear axes if no point is left, e.g. a run without components); linear: both axes start at 0.

Parameters:
  • ax (matplotlib.axes.Axes) – Where to draw.

  • curves (dict) – {label: (N, N) image on grid}.

  • grid (Grid) – The images’ grid.

  • axis (str) – Distance unit (see Grid.axis).

  • distance (float) – The star’s distance in pc (for axis “au”).

  • log (bool) – Log-log axes.

  • label (str) – The values’ unit, for the y label (”” for none).

  • extra (dict) – More curves {label: (radius in arcsec, values)}, drawn dashed.

  • styles (dict) – {curve label: matplotlib line keywords (e.g. color, ls, lw)}; None: the defaults.

  • log_range (float) – Log axes: decades shown below the highest point.

  • legend (bool) – Draw the legend.

  • **kwargs – Passed to matplotlib’s plot for every curve, over styles, e.g. lw=2.

toycoronagraph.scene.image_hdu(name, image, unit, grid)[source]#

A FITS image extension of a scene or final image.

Header: EXTNAME (name in capitals), BUNIT, PIXSCALE (arcsec), WAVELEN (m), and a linear WCS of arcsec offsets from the star (CRPIX = (N+1)/2: pixel (N-1)/2 counted from 0).

Parameters:
  • name (str) – The extension name (upper-cased).

  • image (np.ndarray) – (N, N) image, written as float64.

  • unit (str) – Its unit (BUNIT).

  • grid (Grid) – Its grid.

Returns:

The extension.

Return type:

astropy.io.fits.ImageHDU

toycoronagraph.scene.write_scene(path, images, unit, grid, star=None, overwrite=False, extra=None)[source]#

Write a multi-extension scene FITS file.

The primary HDU holds the grid (PIXSCALE arcsec, WAVELEN m, DIAMETER m), the star’s known fields (DISTANCE pc, RADIUS R_sun, TEMPERAT K, FLUX_JY Jy) and the extra header cards; then one image extension per component (see image_hdu).

Parameters:
  • path (str) – The FITS file to write.

  • images (dict) – {component name: (N, N) image in unit}.

  • unit (str) – The images’ unit (BUNIT).

  • grid (Grid) – Their grid.

  • star (Star) – The star; None: no star cards.

  • overwrite (bool) – Replace an existing file (else astropy raises OSError).

  • extra (dict) – More primary header cards {key: value or (value, comment)}.