LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
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
23This file contains a class used by fgcm ...
24"""
25from functools import lru_cache
26import warnings
27import numpy as np
28
29import lsst.afw.image as afwImage
30import lsst.afw.cameraGeom as afwCameraGeom
31import lsst.geom as geom
32from 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 ----------
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=100, 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
An immutable representation of a camera.
Definition: Camera.h:43
Information about a single exposure of an imaging camera.
Definition: VisitInfo.h:68
def __call__(self, orientation, nstep=100, 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.