LSST Applications g013ef56533+7c9321ec0f,g042eb84c57+c6cfa41bc3,g199a45376c+0ba108daf9,g1fd858c14a+fcad0d0313,g210f2d0738+c0f94c6586,g262e1987ae+a7e710680e,g29ae962dfc+fb55f2edb0,g2ac17093b6+61d6563b1e,g2b1d02342f+df6f932764,g2cef7863aa+aef1011c0b,g2f7ad74990+c0f94c6586,g35bb328faa+8c5ae1fdc5,g3fd5ace14f+53cf87ae69,g47891489e3+4316d04fff,g511e8cfd20+baa56acf6c,g53246c7159+8c5ae1fdc5,g54cd7ddccb+fd7ad03fde,g64539dfbff+c0f94c6586,g67b6fd64d1+4316d04fff,g67fd3c3899+c0f94c6586,g6985122a63+4316d04fff,g74acd417e5+ca833bee28,g786e29fd12+668abc6043,g81db2e9a8d+b2ec8e584f,g87389fa792+8856018cbb,g89139ef638+4316d04fff,g8d7436a09f+0a24083b20,g8ea07a8fe4+760ca7c3fc,g90f42f885a+033b1d468d,g97be763408+11eb8fd5b8,gbf99507273+8c5ae1fdc5,gcdda8b9158+e4c84c9d5c,gce8aa8abaa+8c5ae1fdc5,gd7ef33dd92+4316d04fff,gdab6d2f7ff+ca833bee28,ge410e46f29+4316d04fff,geaed405ab2+c4bbc419c6,gf9a733ac38+8c5ae1fdc5,w.2025.40
LSST Data Management Base Package
Loading...
Searching...
No Matches
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
37class FocalPlaneProjector(object):
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 useScienceDetectors : `bool`, optional
49 Use only science detectors in projector?
50 """
51 def __init__(self, camera, defaultOrientation, useScienceDetectors=False):
52 self.camera = camera
53
54 # Put the reference boresight at the equator to avoid cos(dec) problems.
55 self.boresight = geom.SpherePoint(180.0*geom.degrees, 0.0*geom.degrees)
56 self.flipX = False
57 self.defaultOrientation = int(defaultOrientation) % 360
58 self.useScienceDetectors = useScienceDetectors
59
60 def _makeWcsDict(self, orientation):
61 """
62 Make a dictionary of WCSs at the reference boresight position.
63
64 Parameters
65 ----------
66 orientation : `int`
67 Orientation in degrees. This angle is the position
68 angle of the focal plane +Y with respect to north.
69
70 Returns
71 -------
72 wcsDict : `dict`
73 Dictionary of WCS, with the detector id as the key.
74 """
75 _orientation = orientation*geom.degrees
76
77 visitInfo = afwImage.VisitInfo(boresightRaDec=self.boresight,
78 boresightRotAngle=_orientation,
79 rotType=afwImage.RotType.SKY)
80
81 wcsDict = {}
82
83 for detector in self.camera:
84 if self.useScienceDetectors:
85 if not detector.getType() == afwCameraGeom.DetectorType.SCIENCE:
86 continue
87
88 detectorId = detector.getId()
89 wcsDict[detectorId] = createInitialSkyWcs(visitInfo, detector, self.flipX)
90
91 return wcsDict
92
93 def __call__(self, orientation, nstep=100, use_cache=True):
94 """
95 Make a focal plane projection mapping for use with fgcm.
96
97 Parameters
98 ----------
99 orientation : `float` or `int`
100 Camera orientation in degrees. This angle is the position
101 angle of the focal plane +Y with respect to north.
102 nstep : `int`
103 Number of steps in x/y per detector for the mapping.
104 use_cache : `bool`, optional
105 Use integerized cached lookup.
106
107 Returns
108 -------
109 projectionMapping : `np.ndarray`
110 A projection mapping object with x, y, x_size, y_size,
111 delta_ra_cent, delta_dec_cent, delta_ra, delta_dec for
112 each detector id.
113 """
114 if not np.isfinite(orientation):
115 warnings.warn('Encountered non-finite orientation; using default.')
116 _orientation = self.defaultOrientation
117 else:
118 _orientation = orientation % 360
119
120 if use_cache:
121 _orientation = int(_orientation)
122
123 return self._compute_cached_projection(int(_orientation), nstep=nstep)
124 else:
125 return self._compute_projection(_orientation, nstep=nstep)
126
127 @lru_cache(maxsize=360)
128 def _compute_cached_projection(self, orientation, nstep=50):
129 """
130 Compute the focal plane projection, with caching.
131
132 Parameters
133 ----------
134 orientation : `int`
135 Camera orientation in degrees. This angle is the position
136 angle of the focal plane +Y with respect to north.
137 nstep : `int`
138 Number of steps in x/y per detector for the mapping.
139
140 Returns
141 -------
142 projectionMapping : `np.ndarray`
143 A projection mapping object with x, y, x_size, y_size,
144 delta_ra_cent, delta_dec_cent, delta_ra, delta_dec for
145 each detector id.
146 """
147 return self._compute_projection(orientation, nstep=nstep)
148
149 def _compute_projection(self, orientation, nstep=50):
150 """
151 Compute the focal plane projection.
152
153 Parameters
154 ----------
155 orientation : `float` or `int`
156 Camera orientation in degrees. This angle is the position
157 angle of the focal plane +Y with respect to north.
158 nstep : `int`
159 Number of steps in x/y per detector for the mapping.
160
161 Returns
162 -------
163 projectionMapping : `np.ndarray`
164 A projection mapping object with x, y, x_size, y_size,
165 delta_ra_cent, delta_dec_cent, delta_ra, delta_dec for
166 each detector id.
167 """
168 wcsDict = self._makeWcsDict(orientation)
169
170 # Need something for the max detector ...
171 deltaMapper = np.zeros(
172 len(wcsDict),
173 dtype=[
174 ('id', 'i4'),
175 ('x', 'f8', nstep**2),
176 ('y', 'f8', nstep**2),
177 ('x_size', 'i4'),
178 ('y_size', 'i4'),
179 ('delta_ra_cent', 'f8'),
180 ('delta_dec_cent', 'f8'),
181 ('delta_ra', 'f8', nstep**2),
182 ('delta_dec', 'f8', nstep**2)
183 ],
184 )
185
186 for detector in self.camera:
187 if self.useScienceDetectors:
188 if not detector.getType() == afwCameraGeom.DetectorType.SCIENCE:
189 continue
190
191 detectorId = detector.getId()
192
193 deltaMapper['id'][detectorId] = detectorId
194
195 xSize = detector.getBBox().getMaxX()
196 ySize = detector.getBBox().getMaxY()
197
198 xValues = np.linspace(0.0, xSize, nstep)
199 yValues = np.linspace(0.0, ySize, nstep)
200
201 deltaMapper['x'][detectorId, :] = np.repeat(xValues, yValues.size)
202 deltaMapper['y'][detectorId, :] = np.tile(yValues, xValues.size)
203 deltaMapper['x_size'][detectorId] = xSize
204 deltaMapper['y_size'][detectorId] = ySize
205
206 radec = wcsDict[detector.getId()].pixelToSkyArray(deltaMapper['x'][detectorId, :],
207 deltaMapper['y'][detectorId, :],
208 degrees=True)
209
210 deltaMapper['delta_ra'][detectorId, :] = radec[0] - self.boresight.getRa().asDegrees()
211 deltaMapper['delta_dec'][detectorId, :] = radec[1] - self.boresight.getDec().asDegrees()
212
213 detCenter = wcsDict[detector.getId()].pixelToSky(detector.getCenter(afwCameraGeom.PIXELS))
214 deltaMapper['delta_ra_cent'][detectorId] = (detCenter.getRa()
215 - self.boresight.getRa()).asDegrees()
216 deltaMapper['delta_dec_cent'][detectorId] = (detCenter.getDec()
217 - self.boresight.getDec()).asDegrees()
218
219 return deltaMapper
Information about a single exposure of an imaging camera.
Definition VisitInfo.h:68
__call__(self, orientation, nstep=100, use_cache=True)
__init__(self, camera, defaultOrientation, useScienceDetectors=False)
Point in an unspecified spherical coordinate system.
Definition SpherePoint.h:57