Coverage for tests/test_detector.py: 12%
150 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-10 02:46 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-10 02:46 -0800
1#
2# LSST Data Management System
3# Copyright 2014 LSST Corporation.
4#
5# This product includes software developed by the
6# LSST Project (http://www.lsst.org/).
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the LSST License Statement and
19# the GNU General Public License along with this program. If not,
20# see <http://www.lsstcorp.org/LegalNotices/>.
21#
22"""
23Tests for lsst.afw.cameraGeom.Detector
24"""
25import unittest
27import numpy as np
29import lsst.utils.tests
30import lsst.pex.exceptions
31import lsst.geom
32import lsst.afw.geom
33import lsst.afw.cameraGeom as cameraGeom
34from lsst.afw.cameraGeom.testUtils import DetectorWrapper
37class DetectorTestCase(lsst.utils.tests.TestCase):
39 def testBasics(self):
40 """Test getters and other basics
41 """
42 dw = DetectorWrapper()
43 detector = dw.detector
44 for methodName in ("begin", "end", "size"):
45 if hasattr(detector, methodName):
46 self.assertFalse(hasattr(detector, methodName))
47 self.assertEqual(dw.name, detector.getName())
48 self.assertEqual(dw.id, detector.getId())
49 self.assertEqual(dw.type, detector.getType())
50 self.assertEqual(dw.serial, detector.getSerial())
51 bbox = detector.getBBox()
52 for i in range(2):
53 self.assertEqual(bbox.getMin()[i], dw.bbox.getMin()[i])
54 self.assertEqual(bbox.getMax()[i], dw.bbox.getMax()[i])
55 self.assertAlmostEqual(dw.pixelSize, detector.getPixelSize())
56 self.assertEqual(len(detector), len(dw.ampList))
58 orientation = detector.getOrientation()
60 transformMap = detector.getTransformMap()
61 # add 1 for null transform
62 self.assertEqual(len(transformMap), len(dw.transMap) + 1)
63 for cameraSys in dw.transMap:
64 self.assertTrue(cameraSys in transformMap)
66 self.assertEqual(detector.getPhysicalType(), "CCD") # the default in DetectorWrapper, not Detector
68 # make sure some complex objects stick around after detector is deleted
70 detectorName = detector.getName()
71 nativeCoordSys = detector.getNativeCoordSys()
72 offset = dw.orientation.getFpPosition()
73 del detector
74 del dw
75 self.assertEqual(orientation.getFpPosition(), offset)
76 self.assertEqual(nativeCoordSys,
77 cameraGeom.CameraSys(cameraGeom.PIXELS.getSysName(), detectorName))
79 def testConstructorErrors(self):
80 """Test constructor errors
81 """
82 def duplicateAmpName(dw):
83 """Set two amplifiers to the same name"""
84 builder = dw.ampList[1]
85 builder.setName(dw.ampList[0].getName())
86 dw.ampList[1] = builder
87 with self.assertRaises(lsst.pex.exceptions.Exception):
88 DetectorWrapper(modFunc=duplicateAmpName)
90 # These break in the pybind layer
91 for crosstalk in ([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], # 1D and not numpy
92 np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]), # 1D, wrong numpy type
93 np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], dtype=np.float32), # 1D
94 ):
95 self.assertRaises(TypeError, DetectorWrapper, crosstalk=crosstalk)
96 # These break in the Detector ctor: wrong shape
97 self.assertRaises(lsst.pex.exceptions.InvalidParameterError,
98 DetectorWrapper, crosstalk=np.array([[1.0, 2.0], [3.0, 4.0]]))
99 self.assertRaises(lsst.pex.exceptions.InvalidParameterError,
100 DetectorWrapper, crosstalk=np.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]))
102 def testTransform(self):
103 """Test the transform method
104 """
105 dw = DetectorWrapper()
106 pixOffset = dw.orientation.getReferencePoint()
107 for xyMM in ((25.6, -31.07), (0, 0), (-1.234e5, 3.123e4)):
108 fpPoint = lsst.geom.Point2D(*xyMM)
109 pixPoint = dw.detector.transform(fpPoint, cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS)
110 for i in range(2):
111 self.assertAlmostEqual(
112 fpPoint[i]/dw.pixelSize[i] + pixOffset[i], pixPoint[i])
113 fpPoint2 = dw.detector.transform(pixPoint, cameraGeom.PIXELS, cameraGeom.FOCAL_PLANE)
114 self.assertPairsAlmostEqual(fpPoint, fpPoint2)
116 # test pix to pix
117 pixPoint2 = dw.detector.transform(pixPoint, cameraGeom.PIXELS, cameraGeom.PIXELS)
118 self.assertPairsAlmostEqual(pixPoint, pixPoint2)
120 def testIteration(self):
121 """Test iteration over amplifiers and __getitem__
122 """
123 dw = DetectorWrapper()
124 ampList = [amp for amp in dw.detector]
125 self.assertEqual(len(ampList), len(dw.ampList))
126 for i, amp in enumerate(ampList):
127 self.assertEqual(amp.getName(), dw.detector[i].getName())
128 self.assertEqual(amp.getName(), dw.ampList[i].getName())
129 self.assertEqual(
130 amp.getName(), dw.detector[amp.getName()].getName())
132 def testTransformAccess(self):
133 """Test hasTransform and getTransform
134 """
135 detector = DetectorWrapper().detector
136 for fromSys in (cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS, cameraGeom.TAN_PIXELS):
137 fullFromSys = detector.makeCameraSys(fromSys)
138 for toSys in (cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS, cameraGeom.TAN_PIXELS):
139 fullToSys = detector.makeCameraSys(toSys)
140 self.assertTrue(detector.hasTransform(fromSys))
141 self.assertTrue(detector.hasTransform(fullFromSys))
142 self.assertTrue(detector.hasTransform(toSys))
143 self.assertTrue(detector.hasTransform(fullToSys))
144 detector.getTransform(fromSys, toSys)
145 detector.getTransform(fromSys, fullToSys)
146 detector.getTransform(fullFromSys, toSys)
147 detector.getTransform(fullFromSys, fullToSys)
149 for badCamSys in (
150 cameraGeom.CameraSys("badName"),
151 cameraGeom.CameraSys("pixels", "badDetectorName")
152 ):
153 self.assertFalse(detector.hasTransform(badCamSys))
154 self.assertTrue(detector.hasTransform(cameraGeom.PIXELS))
155 with self.assertRaises(lsst.pex.exceptions.Exception):
156 detector.getTransform(cameraGeom.PIXELS, badCamSys)
158 def testMakeCameraSys(self):
159 """Test the makeCameraSys method
160 """
161 dw = DetectorWrapper()
162 for sysName in ("csys1", "csys2"):
163 for detectorName in ("", dw.name, "a different detector"):
164 inCamSys = cameraGeom.CameraSys(sysName, detectorName)
165 outCamSys = dw.detector.makeCameraSys(inCamSys)
166 self.assertEqual(inCamSys, outCamSys)
168 inCamSysPrefix = cameraGeom.CameraSysPrefix(sysName)
169 outCamSys2 = dw.detector.makeCameraSys(inCamSysPrefix)
170 self.assertEqual(
171 outCamSys2, cameraGeom.CameraSys(sysName, dw.name))
173 def testGetCorners(self):
174 """Test the getCorners method
175 """
176 dw = DetectorWrapper()
177 for cameraSys in (cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS):
178 # positions of corners in specified camera system
179 cornerList = dw.detector.getCorners(cameraSys)
180 for posPixels, posCameraSys in zip(lsst.geom.Box2D(dw.bbox).getCorners(), cornerList):
181 pixelsToCameraSys = dw.detector.getTransform(cameraGeom.PIXELS, cameraSys)
182 predPosCameraSys = pixelsToCameraSys.applyForward(posPixels)
183 self.assertPairsAlmostEqual(predPosCameraSys, posCameraSys)
184 if cameraSys == cameraGeom.PIXELS:
185 self.assertPairsAlmostEqual(posPixels, predPosCameraSys)
187 def testGetCenter(self):
188 """Test the getCenter method
189 """
190 dw = DetectorWrapper()
191 ctrPixPoint = lsst.geom.Box2D(dw.detector.getBBox()).getCenter()
192 for cameraSys in (cameraGeom.FOCAL_PLANE, cameraGeom.PIXELS):
193 ctrPoint = dw.detector.getCenter(cameraSys)
194 transform = dw.detector.getTransform(cameraGeom.PIXELS, cameraSys)
195 predCtrPoint = transform.applyForward(ctrPixPoint)
196 self.assertPairsAlmostEqual(predCtrPoint, ctrPoint)
198 def testDetectorRebuild(self):
199 """Test Detector.rebuild() method
200 """
201 #
202 # Make a copy without any modifications
203 #
204 detector = DetectorWrapper().detector
205 ndetector = detector.rebuild().finish()
207 self.assertEqual(detector.getName(), ndetector.getName())
208 self.assertEqual(detector.getBBox(), ndetector.getBBox())
209 self.assertEqual(detector.getPhysicalType(), ndetector.getPhysicalType())
210 for amp, namp in zip(detector, ndetector):
211 self.assertEqual(amp.getBBox(), namp.getBBox())
212 self.assertEqual(amp.getRawXYOffset(), namp.getRawXYOffset())
213 #
214 # Now make a copy with a hacked-up set of amps
215 #
216 builder = detector.rebuild()
217 for i, amp in enumerate(builder, 1):
218 amp.setRawXYOffset(i*lsst.geom.ExtentI(1, 1))
220 ndetector = builder.finish()
222 self.assertEqual(detector.getName(), ndetector.getName())
223 self.assertEqual(detector.getBBox(), ndetector.getBBox())
224 for i, (amp, namp) in enumerate(zip(detector, ndetector), 1):
225 self.assertEqual(amp.getBBox(), namp.getBBox())
226 self.assertNotEqual(amp.getRawXYOffset(), namp.getRawXYOffset())
227 self.assertEqual(namp.getRawXYOffset()[0], i)
229 def testPersistence(self):
230 """Test round-tripping a Detector through FITS I/O.
231 """
232 dw = DetectorWrapper()
233 detectorIn = dw.detector
234 with lsst.utils.tests.getTempFilePath("*.fits") as filename:
235 detectorIn.writeFits(filename)
236 detectorOut = cameraGeom.Detector.readFits(filename)
237 self.assertDetectorsEqual(detectorIn, detectorOut)
240class MemoryTester(lsst.utils.tests.MemoryTestCase):
241 pass
244def setup_module(module):
245 lsst.utils.tests.init()
248if __name__ == "__main__": 248 ↛ 249line 248 didn't jump to line 249, because the condition on line 248 was never true
249 lsst.utils.tests.init()
250 unittest.main()