pypeit.spectrographs.opticalmodel module

Module to generate an optical model for a spectrograph.

class pypeit.spectrographs.opticalmodel.DetectorMap[source]

Bases: object

General class for mapping the image plane to the pixel coordinates for multiple detectors in a mosaic.

!! PIXEL COORDINATES ARE 1-INDEXED !!

All CCDs in the detector are assumed to have the same size.

nccd

Number of CCD chips in the detector.

Type:

int

npix

Number of pixels in each dimension (x,y) of all CCDs.

Type:

numpy.ndarray

pixel_size

Pixel size in mm.

Type:

float

ccd_gap

The nominal gap between each chip in (x,y) in mm.

Type:

numpy.ndarray

ccd_edge

The width of the CCD edge in (x,y) in mm.

Type:

numpy.ndarray

ccd_size

The nominal size in number of pixels of each CCD accounting for gap, edge width, and number of pixels.

Type:

numpy.ndarray

ccd_center

The (x,y) center of each CCD in number of pixels, accounting for the per CCD offset.

Type:

numpy.ndarray

rotation

The rotation of each CCD.

Type:

numpy.ndarray

rot_matrix

The rotation matrix used for each CCD.

Type:

numpy.ndarray

ccd_coordinates(x_img, y_img, in_mm=True)[source]

Convert the provided coordinates in the image plane to (1-indexed) pixel coordinates on the relevant detector.

Parameters:
  • x_img (float or array-like) – Image coordinates in x

  • y_img (float or array-like) – Image coordinates in y

  • in_mm (bool, optional) – The input coordinates are provided in mm, not pixels.

Returns:

Returns three objects, the detector associated with each coordinates and the x and y pixel coordinates on that detector. Return object type (float or array) is based on the input.

Return type:

float, numpy.ndarray

Raises:

ValueError – Raised if the input x and y arrays do not have the same shape.

image_coordinates(x_pix, y_pix, detector=1, in_mm=True)[source]

Convert the provided (1-indexed) pixel coordinates into coordinates in the image plane.

Parameters:
  • x_pix (float or array-like) – Pixel coordinate in x (1-indexed) on the detector

  • y_pix (float or array-like) – Pixel coordinate in y (1-indexed) on the detector

  • detector (int or array-like, optional) – Relevant detector for the pixel coordinates. Default is 1. Can be a single detector used for all coordinates or an array that provides the detector for each (x,y) coordinate.

  • in_mm (bool, optional) – Return the coordinates in mm.

Returns:

Returns two objects with the x and y coordinates. Return object type is based on the input.

Return type:

float, numpy.ndarray

Raises:

ValueError – Raised if the detector number is not valid or if the input x and y arrays do not have the same shape.

class pypeit.spectrographs.opticalmodel.OpticalModel(pupil_distance, focal_r_surface, focal_r_curvature, mask_r_curvature, mask_tilt_angle, mask_y_zeropoint, mask_z_zeropoint, collimator_d, collimator_r, collimator_k, coll_tilt_err, coll_tilt_phi, grating, camera_tilt, camera_phi, camera_focal_length, camera_distortions, imaging_rotation, optical_axis)[source]

Bases: object

Vanilla optical model for an imaging spectrograph.

Model includes four elements:
  • Slit mask at the focal plane

  • Reflective Collimator

  • Reflective Grating

  • Refractive Camera

Primary objective is to trace light rays from the focal plane position to a position in the imagine coordinate system of the camera. See mask_to_imaging_coordinates().

It is expected that each spectrograph will have its own optical model to perturb what is done in the vanilla model as necessary.

Parameters:
  • pupil_distance (float) – Pupil distance in mm

  • focal_r_surface (float) – Radius of the image surface in mm

  • focal_r_curvature (float) – Focal-plane radius of curvature in mm

  • mask_r_curvature (float) – Mask radius of curvature in mm

  • mask_tilt_angle (float) – Mask tilt angle in radians

  • mask_y_zeropoint (float) – Mask y zero point in mm

  • mask_z_zeropoint (float) – Mask z zero point in mm

  • collimator_d (float) – Collimator distance in mm

  • collimator_r (float) – Collimator radius of curvature in mm

  • collimator_k (float) – Collimator curvature constant

  • coll_tilt_err (float) – Collimator tilt error in radians

  • coll_tilt_phi (float) – Collimator tilt phi in radians

  • grating (ReflectionGrating) – Grating object that evaluates the grating equation and performs the grating reflection.

  • camera_tilt (float) – Camera angle in radians

  • camera_phi (float) – Camera tilt phi angle in radians

  • camera_focal_length (float) – Camera focal length in mm

  • camera_distortions (object) – Class to apply/remove camera distortions. Can be None. If provided, must have remove_distortion and apply_distortion methods.

  • imaging_rotation (float) – Image coordinate system rotation in radians

  • optical_axis (numpy.ndarray) – Camera optical axis center (x,y) in mm

Attributes:

_collimator_transform()[source]

tilt and tilt_error are in radians

Taken from xidl/DEEP2/spec2d/pro/model/setup.pro:

COLL ERROR (first order): In this case, we must remove the phi we put in, hence the more complex form

static conjugate_surface_transform(ray, surface_transform, forward=False)[source]

Transform a ray by a surface.

Taken from xidl/DEEP2/spec2d/pro/model/gen_xfm.pro

Todo

I’m trying to mimic what was done in the IDL code, meaning the matrix ordering may not make sense…

Parameters:
  • ray (numpy.ndarray) – The rays to tranform. If more than one ray is provided, they must be organized along the last axis. I.e., for two rays, the shape of ray should be (2,3).

  • surface_transform (numpy.ndarray) – The transform for the surface. For example, see OpticalModel.get_reflection_transform(). For more than one surface, the surface matrix must be organized along the last two axes. I.e., for two surfaces, the shape of surface should be (2,3,3).

Returns:

The array with the reflected arrays.

Return type:

numpy.ndarray

static get_reflection_transform(theta, phi)[source]

General reflection transform.

Taken from xidl/DEEP2/spec2d/pro/model/setup.pro:

grating_output_vectors_to_ics_coo(r, sign=1)[source]

Revert rays from the CCD coordinates back to the grating output vectors.

There’s a sign degeneracy going this way, so it must be defined.

OUTPUT IS MM

Inverted xidl/DEEP2/spec2d/pro/model/ics_post_grating.pro

ics_coo_to_grating_output_vectors(x, y)[source]

Revert rays from the CCD coordinates back to the grating output vectors.

INPUT IS MM

Taken from xidl/DEEP2/spec2d/pro/model/ics_post_grating.pro

mask_coo_to_grating_input_vectors(x, y)[source]

Propagate rays from the mask plane to the grating.

Taken from xidl/DEEP2/spec2d/pro/model/pre_grating.pro

mask_to_imaging_coordinates(x, y, amap, bmap, nslits, wave, order)[source]

Convert mask coordinates in mm to detector coordinates in pixels.

wave is in angstroms

If more than one wavelength is provided, wavelength samples are ordered along the first axis.

Taken from xidl/DEEP2/spec2d/pro/model/qmodel.pro.

Parameters:
  • x (numpy.ndarray) – The x coordinates in the slit mask in mm.

  • y (numpy.ndarray) – The y coordinates in the slit mask in mm.

  • amap (FITS_rec) – pre-grating map

  • bmap (FITS_rec) – post-grating map

  • nslits (int) – Number of slits

  • wave (numpy.ndarray) – The wavelengths in angstroms for the propagated coordinates.

  • order (int) – The grating order.

Returns:

Detector image plane coordinates in pixels

Return type:

Two numpy.ndarray

post_grating_vectors_to_ics_coo(r, bmap, nslits, npoints)[source]

Revert rays from post-grating output vectors to CCD coordinates, by interpolating a post-grating map (bmap).

This should replace grating_output_vectors_to_ics_coo

Taken from DEEP2/spec2d/pro/model/qmodel.pro

Parameters:
  • r (numpy.ndarray) – Rays to be transformed

  • bmap (FITS_rec) – post-grating map

  • nslits (int) – Number of slits

  • npoints (int) – Size of the spectral direction

Returns:

Detector image plane coordinates in pixels

Return type:

Two numpy.ndarray

pre_grating_vectors(x, y, amap, npoints=1)[source]

Propagate rays from the mask plane to the grating, by interpolating a pre-grating map (amap).

This should replace mask_coo_to_grating_input_vectors

Taken from DEEP2/spec2d/pro/model/qmodel.pro

Parameters:
  • x (numpy.ndarray) – The x coordinates in the slit mask in mm.

  • y (numpy.ndarray) – The y coordinates in the slit mask in mm.

  • amap (FITS_rec) – pre-grating map

  • npoints (int) – Size of the spectral direction

Returns:

Rays propagated from mask plane to grating.

Return type:

numpy.ndarray

project_mask_onto_plane(x, y, a)[source]

Project slitmask coords (curved surface) onto a plane.

Generic as long as self is properly defined

Taken from xidl/DEEP2/spec2d/pro/model/mask_to_proj.pro:

This is pure geometry.

Parameters:
  • x (float) – x coordinate on mask surface in mm

  • y (float) – y coordinate on mask surface in mm

  • a (float) – position angle on curved mask surface

Returns:

Three floats, the x, y, and position angle of the coordinate in the (focal-)planar system

Return type:

float

static reflect(r, surface)[source]

Reflect a (set of) ray(s) of a surface using the provided transformation.

Todo

(KBW) I’m trying to mimic what was done in the IDL code, meaning the matrix ordering may not make sense…

Parameters:
  • r (numpy.ndarray) – The rays to reflect of the defined surface. If more than one ray is provided, they must be organized along the last axis. I.e., for two rays, the shape of r should be (2,3).

  • surface (numpy.ndarray) – The transform for the surface used in the reflection. For example, see OpticalModel.get_reflection_transform(). For more than one surface, the surface matrix must be organized along the last two axes. I.e., for two surfaces, the shape of surface should be (2,3,3).

Returns:

The array with the reflected arrays.

Return type:

numpy.ndarray

telescope_plane_coo_to_collimator_angle(x, y)[source]

Convert the coordinates in the focal plane to the collimator angles.

Taken from xidl/DEEP2/spec2d/pro/model/coll_angle.pro

telescope_plane_coo_to_unit_vector(x, y)[source]

Convert the coordinates in the focal plane to the ray tracing unit vector.

!! IGNORES ANGLE !!

Taken from xidl/DEEP2/spec2d/pro/model/pre_grating.pro

class pypeit.spectrographs.opticalmodel.ReflectionGrating(ruling, tilt, roll, yaw, central_wave=None)[source]

Bases: object

Doc this!

_get_grating_transform()[source]

Taken from xidl/DEEP2/spec2d/pro/model/setup.pro ; same as in xidl/DEEP2/spec2d/pro/model/gsetup.pro

Here tilt is the same as mu (!MU), roll is the same as roll3 (!GR_YERR), and yaw is the same as o3 (!GR_ZERR).

Assumes phin=0. (ie adopts the roll/yaw approach)

MIRROR/GRATING: Better in thetax, thetay description (see above) for GRATING: need to add the third rotation Note the hack with phin + PI. This is needed to keep the transformed x, y axes from flipping, wrt the original x,y. Not a problem wrt reflections but if we want to work _within_ a system it is a problem. Cf. camera also note that this _forces_ us to work in a particular hemisphere, and thus we must make use of the negative theta as needed.

reflect(r, nslits, wave=None, order=1)[source]

Propagate an input ray for a given wavelength and order.

wave is in angstroms ruling is in mm^-1

If more than one wave provided, wavelength samples are ordered along the first axis.

Taken from xidl/DEEP2/spec2d/pro/model/qmodel.pro.

Parameters:
  • r (numpy.ndarray) – Rays to propagate.

  • nslits (int) – Number of slits

  • wave (numpy.ndarray) – The wavelengths in angstroms for the propagated coordinates.

  • order (int) – The grating order.

Returns:

Rays reflected off the grating