AbstractInstrument#
- class esis.optics.abc.AbstractInstrument[source]#
Bases:
Indexable,Printable,Replaceable,Rollable,Yawable,PitchableAn interface describing the entire optical system.
Attributes
The angle between the grating normal and the direction of the incident light.
The angle between the grating normal and the direction of the diffracted light.
The names of the axes of this object,
tuple(self.shape).The name of the logical axis corresponding to changing camera channel.
A model of the camera and sensors.
A model of the central obscuration.
A default grid of field positions to trace through the system.
A model of the field stop.
A model of the thin-film filters.
A model of the front aperture plate.
A model of the diffraction grating array.
Extra keyword arguments used to plot the optical system.
The human-readable name of the instrument.
The number of dimensions of this object,
len(self.shape).pitch angle of this object
A model of the primary mirror.
A default grid of pupil positions to trace through the system.
roll angle of this object
The broadcasted shape of every array-like field of this object.
The total number of elements in this object, the product of the values of
shape.Convert this model into an instance of
optika.systems.SequentialSystem.the coordinate transformation between the global coordinate system and this object's local coordinate system
A default grid of wavelengths to trace through the system.
The maximum wavelength permitted through the system.
The minimum wavelength permitted through the system.
The value of
wavelengthconverted to physical units if needed.yaw angle of this object
Methods
__init__()align_grating([wavelength, position, field, ...])Focus the gratings and then point them back at the sensor.
dispersion(wavelength[, delta])Compute the wavelength interval imaged onto one pixel.
dispersion_doppler(wavelength[, delta])Compute the Doppler velocity interval imaged onto one pixel.
focus_grating([wavelength, field, pupil, ...])Move the gratings along the optic axis to their best focus.
isel(**item)Index every array-like field of this object along named axes given as keyword arguments.
moved_grating([z, yaw])Copy this instrument, putting its gratings somewhere else.
position_line([wavelength])Where the center of the field of view lands on the sensor.
replace(**changes)A copy of this object with the given fields replaced.
schematic_primary([ax, transformation, ...])Plot a schematic of the primary mirror along with the beam footprint.
to_string([prefix])Public-facing version of the
__repr__method that allows for defining a prefix string, which can be used to calculate how much whitespace to add to the beginning of each line of the result.Inheritance Diagram

- align_grating(wavelength=None, position=None, field=None, pupil=None, **kwargs)[source]#
Focus the gratings and then point them back at the sensor.
focus_grating()moves each grating along the optic axis, which also moves the image along the sensor. An instrument which was aligned as well as focused puts the image where it belongs, and this method does both, leaving the line within a hundredth of a pixel of the position asked for.Focusing alone comes closer than one might expect, because a grating whose radius is wrong both defocuses the image and displaces it, and moving the grating to correct the one largely corrects the other. For the as-built model it leaves a couple of pixels, which is still tens of kilometers per second of apparent Doppler shift.
The two are solved one after the other rather than together. Rotating a grating about \(y\) moves the image 915 microns per arcminute while changing the size of a spot by half a micron, so the rotation needed to place the line, of order ten arcseconds, does not disturb the focus. There is no trade to make between the two, and so no weighting between them to choose.
- Parameters:
wavelength (None | Quantity | AbstractScalar) – The wavelength of the line to place. If
None(the default),wavelength_physicalis used.position (None | AbstractCartesian2dVectorArray) – Where on the sensor to put it. If
None(the default),esis.optics.Sensor.position_imageis used.field (None | AbstractCartesian2dVectorArray) – The normalized field positions used to judge the focus. If
None(the default), a \(3 \times 3\) grid of cell centers spanning the field of view is used.pupil (None | AbstractCartesian2dVectorArray) – The normalized pupil positions used to judge the focus. Passed to
focus_grating().kwargs – Additional arguments passed to
focus_grating().
- Return type:
Examples
Align the as-built model and confirm the O V line lands where the sensor says it should.
import astropy.units as u import named_arrays as na import esis instrument = esis.flights.f1.optics.as_built_unfocused(num_distribution=0) aligned = instrument.align_grating() error = aligned.position_line() - aligned.camera.sensor.position_image na.nominal(error.length.to(u.um))
ScalarArray( ndarray=[0.55010484, 0.58132171, 0.58360151, 0.53344192] um, shape={'channel': 4}, )
- dispersion(wavelength, delta=<Quantity 0.5 Angstrom>)[source]#
Compute the wavelength interval imaged onto one pixel.
Measured from the raytrace: two wavelengths either side of the one asked for are traced along the optical axis, and the distance between where they land is divided into the width of a pixel.
The dispersion of this instrument varies across its passband by about a percent, so it is reported at a wavelength rather than as a single number for the instrument.
- Parameters:
wavelength (Quantity | AbstractScalar) – The wavelength to measure the dispersion at.
delta (Quantity) – The half-interval either side of
wavelengthto measure across.
- Return type:
Examples
The dispersion at the O V line.
import esis instrument = esis.flights.f1.optics.design_single(num_distribution=0) instrument.dispersion(esis.flights.f1.spectrum.O_V.wavelength)
ScalarArray( ndarray=36.67463684 mAngstrom / pix, shape={}, )
- dispersion_doppler(wavelength, delta=<Quantity 0.5 Angstrom>)[source]#
Compute the Doppler velocity interval imaged onto one pixel.
This is
dispersion()expressed as a velocity, and it therefore varies across the passband much more than the dispersion itself does, since it is divided by the wavelength. Over the ESIS passband the dispersion changes by about a percent while its Doppler equivalent changes by about ten times that, so the line it is quoted at matters.- Parameters:
wavelength (Quantity | AbstractScalar) – The wavelength to measure the dispersion at.
delta (Quantity) – The half-interval either side of
wavelengthto measure across.
- Return type:
Examples
The Doppler dispersion at the O V line.
import esis instrument = esis.flights.f1.optics.design_single(num_distribution=0) instrument.dispersion_doppler(esis.flights.f1.spectrum.O_V.wavelength)
ScalarArray( ndarray=17.45945819 km / (pix s), shape={}, )
- focus_grating(wavelength=None, field=None, pupil=None, bounds=(<Quantity -1. mm>, <Quantity 2. mm>), min_step_size=<Quantity 1. um>)[source]#
Move the gratings along the optic axis to their best focus.
The gratings image the field stop onto the sensor, so a grating whose radius of curvature differs from the one it was placed for (a measured, as-built radius replacing the design radius, for example) images the field stop to a different distance and defocuses the system unless it is moved to compensate.
This method finds, independently for every element of the grating (every channel, for example), the translation along \(z\) which minimizes the root-mean-square radius of the spots imaged onto the sensor, and returns a copy of this instrument with the gratings moved there. Everything else, including the sensor, stays where it was. The search is a vectorized Brent minimization (
named_arrays.optimize.minimum_brent()), so every channel is focused by the same handful of ray traces.- Parameters:
wavelength (None | Quantity | AbstractScalar) – The wavelengths at which to focus. If
None(the default),wavelength_physicalis used.field (None | AbstractCartesian2dVectorArray) – The normalized field positions of the traced rays. If
None(the default), a \(3 \times 3\) grid spanning the central half of the field of view is used.pupil (None | AbstractCartesian2dVectorArray) – The normalized pupil positions of the traced rays. If
None(the default), a \(21 \times 21\) grid is used.bounds (tuple[Quantity, Quantity]) – The bracket of grating translations, relative to the current position, within which the best focus is sought.
min_step_size (Quantity) – The tolerance on the translation of the best focus.
- Return type:
Examples
Move the gratings of the ESIS-I as-built model, which carries the measured radii of curvature but the design positions, to their best focus in the O V line.
import astropy.units as u import named_arrays as na import esis instrument = esis.flights.f1.optics.as_built_unfocused(num_distribution=0) focused = instrument.focus_grating(wavelength=629.73 * u.AA) na.nominal(focused.grating.translation.z - instrument.grating.translation.z)
ScalarArray( ndarray=[0.70506445, 0.57811216, 0.58559673, 0.47486535] mm, shape={'channel': 4}, )
- isel(**item)#
Index every array-like field of this object along named axes given as keyword arguments.
This is a convenience wrapper around
__getitem__():a.isel(x=0)is equivalent toa[dict(x=0)].Since keyword-argument names must be valid Python identifiers, axes whose names are not valid identifiers can only be indexed using the
dictform,a[{...}].- Parameters:
item (int | slice | AbstractArray) – The index to apply along each named axis.
self (Self)
- Return type:
- moved_grating(z=None, yaw=None)[source]#
Copy this instrument, putting its gratings somewhere else.
Built rather than copied and adjusted, so that the raytrace of the result is the one its gratings ask for.
systemis cached, and a copy carries the cache with it, so moving a grating on a copy moves nothing: the rays go on being traced through the geometry the cache was built from. A new instrument has nothing cached and cannot go stale in that way.The copy is shallow, so everything except the grating is shared with this instrument. Take
copy.deepcopy()of the result before changing anything else about it.- Parameters:
z (None | Quantity | AbstractScalar) – Where to put the gratings along the optic axis. If
None(the default), they are left where they are.yaw (None | Quantity | AbstractScalar) – How far to rotate the gratings about \(y\). If
None(the default), they are left as they are.
- Return type:
- position_line(wavelength=None)[source]#
Where the center of the field of view lands on the sensor.
The ray from the middle of the field of view, through the middle of the pupil, at the wavelength asked for. This is the position a spectral line is at, in the sense that
esis.optics.Sensor.position_imagemeans it.It is taken from the one ray rather than from the centroid of the whole image because the centroid depends on how much of each beam survives to the sensor. With the primary aperture stop removed, three quarters of the rays are lost, and asymmetrically enough to drag the centroid of the O V image 0.42 mm from where its central ray lands. That is a real effect and it is what the flight data show, but it is not a property of the alignment, and it would move under any change to the model of the apertures.
- Parameters:
wavelength (None | Quantity | AbstractScalar) – The wavelength of the line. If
None(the default),wavelength_physicalis used.- Return type:
- replace(**changes)#
A copy of this object with the given fields replaced.
A method version of
dataclasses.replace(), matchingnamed_arrays.AbstractArray.replace(), so that a nested change reads the same at every level:system.replace( surface=system.surface.replace( sag=system.surface.sag.replace(radius=r), ), )
The copy is shallow, as
dataclasses.replace()is: every field which is not named is shared with the original, and mutating one through the copy is mutating it in both. Takecopy.deepcopy()of the result where that matters.- Parameters:
changes – The fields to overwrite in the copy.
- Return type:
- schematic_primary(ax=None, transformation=None, footprint=True, color='black', kwargs_footprint=None, **kwargs)[source]#
Plot a schematic of the primary mirror along with the beam footprint.
- Parameters:
ax (None | Axes) – The
matplotlibaxes on which to plot this schematic. IfNone(the default), the schematic is plotted on the current axes.transformation (None | AbstractTransformation) – An additional transformation to apply to the coordinates before plotting the schematic.
footprint (bool) – Whether to plot the footprint of the rays on the mirror surface.
color (str) – The color of the primary mirror.
kwargs_footprint (None | dict[str, Any]) – Additional kwargs for plotting the footprint of the beam.
kwargs – Additional kwargs for plotting the primary mirror.
- Return type:
None
- to_string(prefix=None)#
Public-facing version of the
__repr__method that allows for defining a prefix string, which can be used to calculate how much whitespace to add to the beginning of each line of the result.
- property angle_grating_input: AbstractScalar#
The angle between the grating normal and the direction of the incident light.
This is the incidence angle \(theta_i\) in the diffraction grating equation.
- property angle_grating_output: AbstractScalar#
The angle between the grating normal and the direction of the diffracted light.
This is an analogue to the diffracted angle in the diffraction grating equation.
- abstract property axis_channel#
The name of the logical axis corresponding to changing camera channel.
- abstract property central_obscuration: None | AbstractCentralObscuration#
A model of the central obscuration.
- abstract property field: None | AbstractCartesian2dVectorArray#
A default grid of field positions to trace through the system.
- abstract property field_stop: None | AbstractFieldStop#
A model of the field stop.
- abstract property filter: None | AbstractFilter#
A model of the thin-film filters.
- abstract property front_aperture: None | AbstractFrontAperture#
A model of the front aperture plate.
- abstract property grating: None | AbstractGrating#
A model of the diffraction grating array.
- abstract property kwargs_plot#
Extra keyword arguments used to plot the optical system.
- abstract property pitch: Quantity | int | float | complex | ndarray | AbstractScalar#
pitch angle of this object
- abstract property primary_mirror: None | AbstractPrimaryMirror#
A model of the primary mirror.
- abstract property pupil#
A default grid of pupil positions to trace through the system.
- abstract property roll: Quantity | int | float | complex | ndarray | AbstractScalar#
roll angle of this object
- property size: int#
The total number of elements in this object, the product of the values of
shape.
- property system: SequentialSystem#
Convert this model into an instance of
optika.systems.SequentialSystem.This is a cached property that is only computed once.
- property transformation: AbstractTransformation#
the coordinate transformation between the global coordinate system and this object’s local coordinate system
- abstract property wavelength: None | Quantity | AbstractScalar#
A default grid of wavelengths to trace through the system.
Can be either in normalized coordinates (in the range \(-1\) to \(+1\)) or in physical coordinates (with units of length).
See also
wavelength_physicalThis value converted into in physical coordinates.
- property wavelength_max: Quantity | AbstractScalar#
The maximum wavelength permitted through the system.
- property wavelength_min: Quantity | AbstractScalar#
The minimum wavelength permitted through the system.
- property wavelength_physical: ScalarArray#
The value of
wavelengthconverted to physical units if needed.