LSSTApplications  20.0.0
LSSTDataManagementBasePackage
cameraConfig.py
Go to the documentation of this file.
1 # This file is part of afw.
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (https://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 
22 __all__ = ["CameraConfig", "DetectorConfig"]
23 
24 import numpy as np
25 import lsst.pex.config as pexConfig
26 import lsst.geom as geom
27 from .orientation import Orientation
28 from .transformConfig import TransformMapConfig
29 
30 
31 class DetectorConfig(pexConfig.Config):
32  """A configuration that represents (and can be used to construct) a
33  Detector.
34  """
35  transformDict = pexConfig.ConfigField(
36  "Dictionary of camera transforms keyed on the transform type.", TransformMapConfig)
37  name = pexConfig.Field("Name of detector slot", str)
38  id = pexConfig.Field("ID of detector slot", int)
39  bbox_x0 = pexConfig.Field("x0 of pixel bounding box", int)
40  bbox_y0 = pexConfig.Field("y0 of pixel bounding box", int)
41  bbox_x1 = pexConfig.Field("x1 of pixel bounding box", int)
42  bbox_y1 = pexConfig.Field("y1 of pixel bounding box", int)
43  detectorType = pexConfig.Field(
44  "Detector type: SCIENCE=0, FOCUS=1, GUIDER=2, WAVEFRONT=3", int)
45  physicalType = pexConfig.Field(
46  "How this specific detector is constructed; e.g. CCD, E2V, HgCdTe ", str, default="CCD")
47  serial = pexConfig.Field(
48  "Serial string associated with this specific detector", str)
49  offset_x = pexConfig.Field(
50  "x offset from the origin of the camera in mm in the transposed system.", float)
51  offset_y = pexConfig.Field(
52  "y offset from the origin of the camera in mm in the transposed system.", float)
53  refpos_x = pexConfig.Field("x position of the reference point in the detector in pixels "
54  "in transposed coordinates.", float)
55  refpos_y = pexConfig.Field("y position of the reference point in the detector in pixels "
56  "in transposed coordinates.", float)
57  yawDeg = pexConfig.Field("yaw (rotation about z) of the detector in degrees. "
58  "This includes any necessary rotation to go from "
59  "detector coordinates to camera coordinates "
60  "after optional transposition.", float)
61  pitchDeg = pexConfig.Field(
62  "pitch (rotation about y) of the detector in degrees", float)
63  rollDeg = pexConfig.Field(
64  "roll (rotation about x) of the detector in degrees", float)
65  pixelSize_x = pexConfig.Field("Pixel size in the x dimension in mm", float)
66  pixelSize_y = pexConfig.Field("Pixel size in the y dimension in mm", float)
67 
68  # Depending on the choice of detector coordinates, the pixel grid may need
69  # to be transposed before rotation to put it in camera coordinates.
70  transposeDetector = pexConfig.Field(
71  "Transpose the pixel grid before orienting in focal plane?", bool)
72 
73  crosstalk = pexConfig.ListField(
74  dtype=float,
75  doc=("Flattened crosstalk coefficient matrix; should have nAmps x nAmps entries. "
76  "Once 'reshape'-ed, ``coeffs[i][j]`` is the fraction of the j-th amp present on the i-th amp."),
77  optional=True
78  )
79 
80  # Accessors to get "compiled" versions of parameters.
81  def getCrosstalk(self, numAmps):
82  """Return a 2-D numpy array of crosstalk coefficients of the proper shape"""
83  if not self.crosstalk:
84  return None
85 
86  if numAmps != int(np.sqrt(len(self.crosstalk))):
87  numAmps = int(np.sqrt(len(self.crosstalk)))
88  try:
89  return np.array(self.crosstalk, dtype=np.float32).reshape((numAmps, numAmps))
90  except Exception as e:
91  raise RuntimeError(f"Cannot reshape 'crosstalk' coefficients to square matrix: {e}")
92 
93  @property
94  def bbox(self):
95  """Return the detector bounding box from the separate box endpoint
96  values.
97  """
98  return geom.BoxI(geom.PointI(self.bbox_x0, self.bbox_y0),
99  geom.PointI(self.bbox_x1, self.bbox_y1))
100 
101  @property
102  def offset(self):
103  """Return the detector offset as a Point2D from the separate config
104  values.
105  """
106  return geom.Point2D(self.offset_x, self.offset_y)
107 
108  @property
109  def refPos(self):
110  """Return the detector reference position as a Point2D from the
111  separate config values.
112  """
113  return geom.Point2D(self.refpos_x, self.refpos_y)
114 
115  @property
116  def orientation(self):
117  """Return the cameraGeom.Orientation() object defined by the
118  configuration values.
119  """
120  return Orientation(self.offset, self.refPos,
121  geom.Angle(self.yawDeg, geom.degrees),
122  geom.Angle(self.pitchDeg, geom.degrees),
123  geom.Angle(self.rollDeg, geom.degrees))
124 
125  @property
126  def pixelSize(self):
127  """Return the pixel size as an Extent2D from the separate values.
128  """
129  return geom.Extent2D(self.pixelSize_x, self.pixelSize_y)
130 
131 
132 class CameraConfig(pexConfig.Config):
133  """A configuration that represents (and can be used to construct) a Camera.
134  """
135  detectorList = pexConfig.ConfigDictField(
136  "List of detector configs", keytype=int, itemtype=DetectorConfig)
137  transformDict = pexConfig.ConfigField(
138  "Dictionary of camera transforms keyed on the transform type.", TransformMapConfig)
139  name = pexConfig.Field("Name of this camera", str)
140 
141  plateScale = pexConfig.Field(
142  "Plate scale of the camera in arcsec/mm", float)
143  # Note that the radial transform will also apply a scaling, so all coefficients should be
144  # scaled by the plate scale in appropriate units
145  radialCoeffs = pexConfig.ListField(
146  "Coefficients for radial distortion", float)
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.offset
def offset(self)
Definition: cameraConfig.py:102
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.refPos
def refPos(self)
Definition: cameraConfig.py:109
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.bbox_x0
bbox_x0
Definition: cameraConfig.py:39
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.bbox
def bbox(self)
Definition: cameraConfig.py:94
lsst::afw::cameraGeom.cameraConfig.CameraConfig
Definition: cameraConfig.py:132
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.pixelSize_y
pixelSize_y
Definition: cameraConfig.py:66
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.pitchDeg
pitchDeg
Definition: cameraConfig.py:61
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.pixelSize
def pixelSize(self)
Definition: cameraConfig.py:126
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.yawDeg
yawDeg
Definition: cameraConfig.py:57
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.crosstalk
crosstalk
Definition: cameraConfig.py:73
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.orientation
def orientation(self)
Definition: cameraConfig.py:116
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.rollDeg
rollDeg
Definition: cameraConfig.py:63
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.bbox_y0
bbox_y0
Definition: cameraConfig.py:40
lsst::afw::cameraGeom.cameraConfig.DetectorConfig
Definition: cameraConfig.py:31
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.pixelSize_x
pixelSize_x
Definition: cameraConfig.py:65
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.offset_x
offset_x
Definition: cameraConfig.py:49
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.refpos_x
refpos_x
Definition: cameraConfig.py:53
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.bbox_y1
bbox_y1
Definition: cameraConfig.py:42
lsst::geom
Definition: geomOperators.dox:4
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.getCrosstalk
def getCrosstalk(self, numAmps)
Definition: cameraConfig.py:81
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.refpos_y
refpos_y
Definition: cameraConfig.py:55
lsst::geom::Point< int, 2 >
lsst::geom::Angle
A class representing an angle.
Definition: Angle.h:127
lsst::geom::Box2I
An integer coordinate rectangle.
Definition: Box.h:55
lsst::geom::Extent< double, 2 >
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.offset_y
offset_y
Definition: cameraConfig.py:51
lsst::afw::cameraGeom.cameraConfig.DetectorConfig.bbox_x1
bbox_x1
Definition: cameraConfig.py:41