LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
focalPlaneProjector.py
Go to the documentation of this file.
1 # This file is part of fgcmcal.
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 """A class to project the focal plane in arbitrary rotations for fgcm.
22 
23 This file contains a class used by fgcm ...
24 """
25 from functools import lru_cache
26 import warnings
27 import numpy as np
28 
29 import lsst.afw.image as afwImage
30 import lsst.afw.cameraGeom as afwCameraGeom
31 import lsst.geom as geom
32 from lsst.obs.base import createInitialSkyWcs
33 
34 __all__ = ['FocalPlaneProjector']
35 
36 
38  """
39  Class to project the focal plane onto the sky.
40 
41  Parameters
42  ----------
43  camera : `lsst.afw.cameraGeom.Camera`
44  Camera from the butler.
45  defaultOrientation : `int`
46  Default camera orientation in degrees. This angle is the position
47  angle of the focal plane +Y with respect to north.
48  """
49  def __init__(self, camera, defaultOrientation):
50  self.cameracamera = camera
51 
52  # Put the reference boresight at the equator to avoid cos(dec) problems.
53  self.boresightboresight = geom.SpherePoint(180.0*geom.degrees, 0.0*geom.degrees)
54  self.flipXflipX = False
55  self.defaultOrientationdefaultOrientation = int(defaultOrientation) % 360
56 
57  def _makeWcsDict(self, orientation):
58  """
59  Make a dictionary of WCSs at the reference boresight position.
60 
61  Parameters
62  ----------
63  orientation : `int`
64  Orientation in degrees. This angle is the position
65  angle of the focal plane +Y with respect to north.
66 
67  Returns
68  -------
69  wcsDict : `dict`
70  Dictionary of WCS, with the detector id as the key.
71  """
72  _orientation = orientation*geom.degrees
73 
74  visitInfo = afwImage.VisitInfo(boresightRaDec=self.boresightboresight,
75  boresightRotAngle=_orientation,
76  rotType=afwImage.RotType.SKY)
77 
78  wcsDict = {}
79 
80  for detector in self.cameracamera:
81  detectorId = detector.getId()
82  wcsDict[detectorId] = createInitialSkyWcs(visitInfo, detector, self.flipXflipX)
83 
84  return wcsDict
85 
86  def __call__(self, orientation, nstep=50, use_cache=True):
87  """
88  Make a focal plane projection mapping for use with fgcm.
89 
90  Parameters
91  ----------
92  orientation : `float` or `int`
93  Camera orientation in degrees. This angle is the position
94  angle of the focal plane +Y with respect to north.
95  nstep : `int`
96  Number of steps in x/y per detector for the mapping.
97  use_cache : `bool`, optional
98  Use integerized cached lookup.
99 
100  Returns
101  -------
102  projectionMapping : `np.ndarray`
103  A projection mapping object with x, y, x_size, y_size,
104  delta_ra_cent, delta_dec_cent, delta_ra, delta_dec for
105  each detector id.
106  """
107  if not np.isfinite(orientation):
108  warnings.warn('Encountered non-finite orientation; using default.')
109  _orientation = self.defaultOrientationdefaultOrientation
110  else:
111  _orientation = orientation % 360
112 
113  if use_cache:
114  _orientation = int(_orientation)
115 
116  return self._compute_cached_projection_compute_cached_projection(int(_orientation), nstep=nstep)
117  else:
118  return self._compute_projection_compute_projection(_orientation, nstep=nstep)
119 
120  @lru_cache(maxsize=360)
121  def _compute_cached_projection(self, orientation, nstep=50):
122  """
123  Compute the focal plane projection, with caching.
124 
125  Parameters
126  ----------
127  orientation : `int`
128  Camera orientation in degrees. This angle is the position
129  angle of the focal plane +Y with respect to north.
130  nstep : `int`
131  Number of steps in x/y per detector for the mapping.
132 
133  Returns
134  -------
135  projectionMapping : `np.ndarray`
136  A projection mapping object with x, y, x_size, y_size,
137  delta_ra_cent, delta_dec_cent, delta_ra, delta_dec for
138  each detector id.
139  """
140  return self._compute_projection_compute_projection(orientation, nstep=nstep)
141 
142  def _compute_projection(self, orientation, nstep=50):
143  """
144  Compute the focal plane projection.
145 
146  Parameters
147  ----------
148  orientation : `float` or `int`
149  Camera orientation in degrees. This angle is the position
150  angle of the focal plane +Y with respect to north.
151  nstep : `int`
152  Number of steps in x/y per detector for the mapping.
153 
154  Returns
155  -------
156  projectionMapping : `np.ndarray`
157  A projection mapping object with x, y, x_size, y_size,
158  delta_ra_cent, delta_dec_cent, delta_ra, delta_dec for
159  each detector id.
160  """
161  wcsDict = self._makeWcsDict_makeWcsDict(orientation)
162 
163  # Need something for the max detector ...
164  deltaMapper = np.zeros(len(self.cameracamera), dtype=[('id', 'i4'),
165  ('x', 'f8', nstep**2),
166  ('y', 'f8', nstep**2),
167  ('x_size', 'i4'),
168  ('y_size', 'i4'),
169  ('delta_ra_cent', 'f8'),
170  ('delta_dec_cent', 'f8'),
171  ('delta_ra', 'f8', nstep**2),
172  ('delta_dec', 'f8', nstep**2)])
173 
174  for detector in self.cameracamera:
175  detectorId = detector.getId()
176 
177  deltaMapper['id'][detectorId] = detectorId
178 
179  xSize = detector.getBBox().getMaxX()
180  ySize = detector.getBBox().getMaxY()
181 
182  xValues = np.linspace(0.0, xSize, nstep)
183  yValues = np.linspace(0.0, ySize, nstep)
184 
185  deltaMapper['x'][detectorId, :] = np.repeat(xValues, yValues.size)
186  deltaMapper['y'][detectorId, :] = np.tile(yValues, xValues.size)
187  deltaMapper['x_size'][detectorId] = xSize
188  deltaMapper['y_size'][detectorId] = ySize
189 
190  radec = wcsDict[detector.getId()].pixelToSkyArray(deltaMapper['x'][detectorId, :],
191  deltaMapper['y'][detectorId, :],
192  degrees=True)
193 
194  deltaMapper['delta_ra'][detectorId, :] = radec[0] - self.boresightboresight.getRa().asDegrees()
195  deltaMapper['delta_dec'][detectorId, :] = radec[1] - self.boresightboresight.getDec().asDegrees()
196 
197  detCenter = wcsDict[detector.getId()].pixelToSky(detector.getCenter(afwCameraGeom.PIXELS))
198  deltaMapper['delta_ra_cent'][detectorId] = (detCenter.getRa()
199  - self.boresightboresight.getRa()).asDegrees()
200  deltaMapper['delta_dec_cent'][detectorId] = (detCenter.getDec()
201  - self.boresightboresight.getDec()).asDegrees()
202 
203  return deltaMapper
Information about a single exposure of an imaging camera.
Definition: VisitInfo.h:68
def __call__(self, orientation, nstep=50, use_cache=True)
def __init__(self, camera, defaultOrientation)
def _compute_cached_projection(self, orientation, nstep=50)
Point in an unspecified spherical coordinate system.
Definition: SpherePoint.h:57
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.