Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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 

22import unittest 

23import os 

24 

25import numpy as np 

26 

27import lsst.utils.tests 

28import lsst.pex.exceptions as pexExcept 

29import lsst.geom 

30import lsst.afw.image as afwImage 

31import lsst.afw.display as afwDisplay 

32from lsst.afw.cameraGeom import PIXELS, FIELD_ANGLE, FOCAL_PLANE, CameraSys, CameraSysPrefix, \ 

33 Camera, Detector, assembleAmplifierImage, assembleAmplifierRawImage, DetectorCollection 

34import lsst.afw.cameraGeom.testUtils as testUtils 

35import lsst.afw.cameraGeom.utils as cameraGeomUtils 

36 

37try: 

38 type(display) 

39except NameError: 

40 display = False 

41 

42testPath = os.path.abspath(os.path.dirname(__file__)) 

43 

44 

45class CameraGeomTestCase(lsst.utils.tests.TestCase): 

46 """A test case for camera geometry""" 

47 

48 def setUp(self): 

49 self.lsstCamWrapper = testUtils.CameraWrapper(isLsstLike=True) 

50 self.scCamWrapper = testUtils.CameraWrapper(isLsstLike=False) 

51 self.cameraList = (self.lsstCamWrapper, self.scCamWrapper) 

52 self.assemblyList = {} 

53 self.assemblyList[self.lsstCamWrapper.camera.getName()] =\ 

54 [afwImage.ImageU(os.path.join(testPath, 'test_amp.fits.gz')) 

55 for i in range(8)] 

56 self.assemblyList[self.scCamWrapper.camera.getName()] =\ 

57 [afwImage.ImageU(os.path.join(testPath, 'test.fits.gz'), allowUnsafe=True)] 

58 

59 def tearDown(self): 

60 del self.lsstCamWrapper 

61 del self.scCamWrapper 

62 del self.cameraList 

63 del self.assemblyList 

64 

65 def testConstructor(self): 

66 for cw in self.cameraList: 

67 self.assertIsInstance(cw.camera, Camera) 

68 self.assertEqual(cw.nDetectors, len(cw.camera)) 

69 self.assertEqual(cw.nDetectors, len(cw.ampDataDict)) 

70 self.assertEqual(sorted(cw.detectorNameList), 

71 sorted(cw.camera.getNameIter())) 

72 self.assertEqual(sorted(cw.detectorIdList), 

73 sorted(cw.camera.getIdIter())) 

74 for det in cw.camera: 

75 self.assertIsInstance(det, Detector) 

76 self.assertEqual( 

77 cw.ampDataDict[det.getName()]['namps'], len(det)) 

78 idList = [det.getId() for det in cw.camera] 

79 self.assertEqual(idList, sorted(idList)) 

80 

81 def testCameraSysRepr(self): 

82 """Test CameraSys.__repr__ and CameraSysPrefix.__repr__ 

83 """ 

84 for sysName in ("FocalPlane", "FieldAngle", "Pixels", "foo"): 

85 cameraSys = CameraSys(sysName) 

86 predRepr = f"CameraSys({sysName})" 

87 self.assertEqual(repr(cameraSys), predRepr) 

88 

89 cameraSysPrefix = CameraSysPrefix(sysName) 

90 predCSPRepr = f"CameraSysPrefix({sysName})" 

91 self.assertEqual(repr(cameraSysPrefix), predCSPRepr) 

92 for detectorName in ("Detector 1", "bar"): 

93 cameraSys2 = CameraSys(sysName, detectorName) 

94 predRepr2 = f"CameraSys({sysName}, {detectorName})" 

95 self.assertEqual(repr(cameraSys2), predRepr2) 

96 

97 def testAccessor(self): 

98 for cw in self.cameraList: 

99 camera = cw.camera 

100 for name in cw.detectorNameList: 

101 self.assertIsInstance(camera[name], Detector) 

102 for detId in cw.detectorIdList: 

103 self.assertIsInstance(camera[detId], Detector) 

104 

105 def testTransformSlalib(self): 

106 """Test Camera.transform against data computed using SLALIB 

107 

108 These test data come from SLALIB using SLA_PCD with 0.925 and 

109 a plate scale of 20 arcsec/mm 

110 """ 

111 testData = [(-1.84000000, 1.04000000, -331.61689069, 187.43563387), 

112 (-1.64000000, 0.12000000, -295.42491556, 21.61645724), 

113 (-1.44000000, -0.80000000, -259.39818797, -144.11010443), 

114 (-1.24000000, -1.72000000, -223.48275934, -309.99221457), 

115 (-1.08000000, 1.36000000, -194.56520533, 245.00803635), 

116 (-0.88000000, 0.44000000, -158.44320430, 79.22160215), 

117 (-0.68000000, -0.48000000, -122.42389383, -86.41686623), 

118 (-0.48000000, -1.40000000, -86.45332534, -252.15553224), 

119 (-0.32000000, 1.68000000, -57.64746955, 302.64921514), 

120 (-0.12000000, 0.76000000, -21.60360306, 136.82281940), 

121 (0.08000000, -0.16000000, 14.40012984, -28.80025968), 

122 (0.28000000, -1.08000000, 50.41767773, -194.46818554), 

123 (0.48000000, -2.00000000, 86.50298919, -360.42912163), 

124 (0.64000000, 1.08000000, 115.25115701, 194.48632746), 

125 (0.84000000, 0.16000000, 151.23115189, 28.80593369), 

126 (1.04000000, -0.76000000, 187.28751874, -136.86395600), 

127 (1.24000000, -1.68000000, 223.47420612, -302.77150507), 

128 (1.40000000, 1.40000000, 252.27834478, 252.27834478), 

129 (1.60000000, 0.48000000, 288.22644118, 86.46793236), 

130 (1.80000000, -0.44000000, 324.31346653, -79.27662515), ] 

131 

132 for cw in self.cameraList: 

133 camera = cw.camera 

134 for point in testData: 

135 fpGivenPos = lsst.geom.Point2D(point[2], point[3]) 

136 fieldGivenPos = lsst.geom.Point2D( 

137 lsst.geom.degToRad(point[0]), lsst.geom.degToRad(point[1])) 

138 

139 fieldAngleToFocalPlane = camera.getTransform(FIELD_ANGLE, FOCAL_PLANE) 

140 fpComputedPos = fieldAngleToFocalPlane.applyForward(fieldGivenPos) 

141 self.assertPairsAlmostEqual(fpComputedPos, fpGivenPos) 

142 

143 focalPlaneToFieldAngle = camera.getTransform(FOCAL_PLANE, FIELD_ANGLE) 

144 fieldComputedPos = focalPlaneToFieldAngle.applyForward(fpGivenPos) 

145 self.assertPairsAlmostEqual(fieldComputedPos, fieldGivenPos) 

146 

147 def testTransformDet(self): 

148 """Test Camera.getTransform with detector-based coordinate systems (PIXELS) 

149 """ 

150 for cw in self.cameraList: 

151 numOffUsable = 0 # number of points off one detector but on another 

152 camera = cw.camera 

153 detNameList = list(camera.getNameIter()) 

154 for detName in detNameList: 

155 det = camera[detName] 

156 

157 # test transforms using an arbitrary point on the detector 

158 posPixels = lsst.geom.Point2D(10, 10) 

159 pixSys = det.makeCameraSys(PIXELS) 

160 pixelsToFocalPlane = camera.getTransform(pixSys, FOCAL_PLANE) 

161 pixelsToFieldAngle = camera.getTransform(pixSys, FIELD_ANGLE) 

162 focalPlaneToFieldAngle = camera.getTransform(FOCAL_PLANE, FIELD_ANGLE) 

163 posFocalPlane = pixelsToFocalPlane.applyForward(posPixels) 

164 posFieldAngle = pixelsToFieldAngle.applyForward(posPixels) 

165 posFieldAngle2 = focalPlaneToFieldAngle.applyForward(posFocalPlane) 

166 self.assertPairsAlmostEqual(posFieldAngle, posFieldAngle2) 

167 

168 posFieldAngle3 = camera.transform(posPixels, pixSys, FIELD_ANGLE) 

169 self.assertPairsAlmostEqual(posFieldAngle, posFieldAngle3) 

170 

171 for intermedPos, intermedSys in ( 

172 (posPixels, pixSys), 

173 (posFocalPlane, FOCAL_PLANE), 

174 (posFieldAngle, FIELD_ANGLE), 

175 ): 

176 pixelSys = det.makeCameraSys(PIXELS) 

177 intermedSysToPixels = camera.getTransform(intermedSys, pixelSys) 

178 posPixelsRoundTrip = intermedSysToPixels.applyForward(intermedPos) 

179 self.assertPairsAlmostEqual(posPixels, posPixelsRoundTrip) 

180 

181 posPixelsRoundTrip2 = camera.transform(intermedPos, intermedSys, pixelSys) 

182 self.assertPairsAlmostEqual(posPixels, posPixelsRoundTrip2) 

183 

184 # Test finding detectors for a point off this detector. 

185 # The point off the detector may be on one other detector, 

186 # depending if the detector has neighbor on the correct edge. 

187 pixOffDet = lsst.geom.Point2D(0, -10) 

188 pixCoordSys = det.makeCameraSys(PIXELS) 

189 detList = camera.findDetectors(pixOffDet, pixCoordSys) 

190 self.assertIn(len(detList), (0, 1)) 

191 if len(detList) == 1: 

192 numOffUsable += 1 

193 

194 otherDet = detList[0] 

195 self.assertNotEqual(otherDet, det) 

196 otherCoordPixSys = otherDet.makeCameraSys(PIXELS) 

197 

198 pixelsToOtherPixels = camera.getTransform(pixCoordSys, otherCoordPixSys) 

199 otherPixels = pixelsToOtherPixels.applyForward(pixOffDet) 

200 with self.assertRaises(AssertionError): 

201 self.assertPairsAlmostEqual(otherPixels, pixOffDet) 

202 

203 # convert back 

204 otherPixelsToPixels = camera.getTransform(otherCoordPixSys, pixCoordSys) 

205 pixOffDetRoundTrip = otherPixelsToPixels.applyForward(otherPixels) 

206 self.assertPairsAlmostEqual(pixOffDet, pixOffDetRoundTrip) 

207 self.assertEqual(numOffUsable, 5) 

208 

209 def testFindDetectors(self): 

210 for cw in self.cameraList: 

211 detCtrFocalPlaneList = [] 

212 for det in cw.camera: 

213 # This currently assumes there is only one detector at the center 

214 # position of any detector. That is not enforced and multiple detectors 

215 # at a given FIELD_ANGLE position is supported. Change this if the default 

216 # camera changes. 

217 detCtrFocalPlane = det.getCenter(FOCAL_PLANE) 

218 detCtrFocalPlaneList.append(detCtrFocalPlane) 

219 detList = cw.camera.findDetectors(detCtrFocalPlane, FOCAL_PLANE) 

220 self.assertEqual(len(detList), 1) 

221 self.assertEqual(det.getName(), detList[0].getName()) 

222 detList = cw.camera.findDetectorsList(detCtrFocalPlaneList, FOCAL_PLANE) 

223 self.assertEqual(len(cw.camera), len(detList)) 

224 for dets in detList: 

225 self.assertEqual(len(dets), 1) 

226 

227 def testFpBbox(self): 

228 for cw in self.cameraList: 

229 camera = cw.camera 

230 bbox = lsst.geom.Box2D() 

231 for name in cw.detectorNameList: 

232 for corner in camera[name].getCorners(FOCAL_PLANE): 

233 bbox.include(corner) 

234 self.assertEqual(bbox.getMin(), camera.getFpBBox().getMin()) 

235 self.assertEqual(bbox.getMax(), camera.getFpBBox().getMax()) 

236 

237 def testLinearity(self): 

238 """Test if we can set/get Linearity parameters""" 

239 for cw in self.cameraList: 

240 camera = cw.camera 

241 for det in camera: 

242 for amp in det: 

243 self.assertEqual(cw.ampDataDict[det.getName()]['linInfo'][amp.getName()]['linthresh'], 

244 amp.getLinearityThreshold()) 

245 self.assertEqual(cw.ampDataDict[det.getName()]['linInfo'][amp.getName()]['linmax'], 

246 amp.getLinearityMaximum()) 

247 self.assertEqual(cw.ampDataDict[det.getName()]['linInfo'][amp.getName()]['linunits'], 

248 amp.getLinearityUnits()) 

249 self.assertEqual(cw.ampDataDict[det.getName()]['linInfo'][amp.getName()]['lintype'], 

250 amp.getLinearityType()) 

251 for c1, c2 in zip(cw.ampDataDict[det.getName()]['linInfo'][amp.getName()]['lincoeffs'], 

252 amp.getLinearityCoeffs()): 

253 if np.isfinite(c1) and np.isfinite(c2): 

254 self.assertEqual(c1, c2) 

255 

256 def testAssembly(self): 

257 ccdNames = ('R:0,0 S:1,0', 'R:0,0 S:0,1') 

258 compMap = {True: afwImage.ImageU(os.path.join(testPath, 'test_comp_trimmed.fits.gz'), 

259 allowUnsafe=True), 

260 False: afwImage.ImageU(os.path.join(testPath, 'test_comp.fits.gz'), allowUnsafe=True)} 

261 for cw in self.cameraList: 

262 camera = cw.camera 

263 imList = self.assemblyList[camera.getName()] 

264 for ccdName in ccdNames: 

265 for trim, assemble in ((False, assembleAmplifierRawImage), (True, assembleAmplifierImage)): 

266 det = camera[ccdName] 

267 if not trim: 

268 outBbox = cameraGeomUtils.calcRawCcdBBox(det) 

269 else: 

270 outBbox = det.getBBox() 

271 outImage = afwImage.ImageU(outBbox) 

272 if len(imList) == 1: 

273 for amp in det: 

274 assemble(outImage, imList[0], amp) 

275 else: 

276 for amp, im in zip(det, imList): 

277 assemble(outImage, im, amp) 

278 self.assertListEqual(outImage.getArray().flatten().tolist(), 

279 compMap[trim].getArray().flatten().tolist()) 

280 

281 @unittest.skipIf(not display, "display variable not set; skipping cameraGeomUtils test") 

282 def testCameraGeomUtils(self): 

283 for cw in self.cameraList: 

284 camera = cw.camera 

285 disp = afwDisplay.Display() 

286 cameraGeomUtils.showCamera(camera, display=disp) 

287 disp.incrDefaultFrame() 

288 for det in (camera[10], camera[20]): 

289 cameraGeomUtils.showCcd(det, inCameraCoords=False) 

290 disp.incrDefaultFrame() 

291 cameraGeomUtils.showCcd(det, inCameraCoords=True) 

292 disp.incrDefaultFrame() 

293 cameraGeomUtils.showCcd(det, inCameraCoords=False) 

294 disp.incrDefaultFrame() 

295 cameraGeomUtils.showCcd(det, inCameraCoords=True) 

296 disp.incrDefaultFrame() 

297 for amp in det: 

298 cameraGeomUtils.showAmp(amp, display=disp, imageFactory=afwImage.ImageF) 

299 disp.incrDefaultFrame() 

300 

301 def testCameraRaises(self): 

302 for cw in self.cameraList: 

303 camera = cw.camera 

304 point = lsst.geom.Point2D(0, 0) 

305 # non-existant source camera system 

306 with self.assertRaises(pexExcept.InvalidParameterError): 

307 camera.getTransform(CameraSys("badSystem"), FOCAL_PLANE) 

308 with self.assertRaises(pexExcept.InvalidParameterError): 

309 camera.transform(point, CameraSys("badSystem"), FOCAL_PLANE) 

310 # non-existant destination camera system 

311 with self.assertRaises(pexExcept.InvalidParameterError): 

312 camera.getTransform(FOCAL_PLANE, CameraSys("badSystem")) 

313 with self.assertRaises(pexExcept.InvalidParameterError): 

314 camera.transform(point, FOCAL_PLANE, CameraSys("badSystem")) 

315 # non-existent source detector 

316 with self.assertRaises(pexExcept.InvalidParameterError): 

317 camera.getTransform(CameraSys("pixels", "invalid"), FOCAL_PLANE) 

318 with self.assertRaises(pexExcept.InvalidParameterError): 

319 camera.transform(point, CameraSys("pixels", "invalid"), FOCAL_PLANE) 

320 # non-existent destination detector 

321 with self.assertRaises(pexExcept.InvalidParameterError): 

322 camera.getTransform(FOCAL_PLANE, CameraSys("pixels", "invalid")) 

323 with self.assertRaises(pexExcept.InvalidParameterError): 

324 camera.transform(point, FOCAL_PLANE, CameraSys("pixels", "invalid")) 

325 

326 def testDetectorCollectionPersistence(self): 

327 """Test that we can round-trip a DetectorCollection through FITS I/O. 

328 """ 

329 for wrapper in self.cameraList: 

330 camera = wrapper.camera 

331 detectors = list(camera) 

332 collectionIn = DetectorCollection(detectors) 

333 with lsst.utils.tests.getTempFilePath(".fits") as filename: 

334 collectionIn.writeFits(filename) 

335 collectionOut = DetectorCollection.readFits(filename) 

336 self.assertDetectorCollectionsEqual(collectionIn, collectionOut) 

337 

338 def testCameraPersistence(self): 

339 """Test that we can round-trip a Camera through FITS I/O. 

340 """ 

341 for wrapper in self.cameraList: 

342 cameraIn = wrapper.camera 

343 with lsst.utils.tests.getTempFilePath(".fits") as filename: 

344 cameraIn.writeFits(filename) 

345 cameraOut = Camera.readFits(filename) 

346 self.assertCamerasEqual(cameraIn, cameraOut) 

347 

348 

349class TestMemory(lsst.utils.tests.MemoryTestCase): 

350 pass 

351 

352 

353def setup_module(module): 

354 lsst.utils.tests.init() 

355 

356 

357if __name__ == "__main__": 357 ↛ 358line 357 didn't jump to line 358, because the condition on line 357 was never true

358 lsst.utils.tests.init() 

359 unittest.main()