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

1from __future__ import with_statement 

2from builtins import zip 

3from builtins import range 

4import os 

5import numpy as np 

6import unittest 

7import lsst.utils.tests 

8from lsst.utils import getPackageDir 

9 

10from lsst.sims.utils import ObservationMetaData, radiansFromArcsec, arcsecFromRadians 

11from lsst.sims.utils import haversine 

12from lsst.obs.lsstSim import LsstSimMapper 

13 

14from lsst.sims.utils import pupilCoordsFromRaDec, observedFromICRS 

15from lsst.sims.coordUtils import (chipNameFromRaDec, 

16 chipNameFromPupilCoords, 

17 _chipNameFromRaDec) 

18 

19from lsst.sims.coordUtils import (pixelCoordsFromPupilCoords, 

20 pixelCoordsFromRaDec, 

21 _pixelCoordsFromRaDec) 

22 

23from lsst.sims.coordUtils import (focalPlaneCoordsFromPupilCoords, 

24 focalPlaneCoordsFromRaDec, 

25 _focalPlaneCoordsFromRaDec) 

26 

27from lsst.sims.coordUtils import pupilCoordsFromPixelCoords 

28from lsst.sims.coordUtils import raDecFromPixelCoords, _raDecFromPixelCoords 

29from lsst.sims.coordUtils import getCornerPixels, _getCornerRaDec, getCornerRaDec 

30 

31from lsst.sims.coordUtils import pupilCoordsFromFocalPlaneCoords 

32from lsst.sims.coordUtils import lsst_camera 

33 

34from lsst.geom import Point2D 

35from lsst.afw.cameraGeom import FIELD_ANGLE, FOCAL_PLANE 

36 

37def setup_module(module): 

38 lsst.utils.tests.init() 

39 

40 

41class ChipNameTest(unittest.TestCase): 

42 

43 @classmethod 

44 def setUpClass(cls): 

45 cls.camera = LsstSimMapper().camera 

46 

47 @classmethod 

48 def tearDownClass(cls): 

49 del cls.camera 

50 

51 def setUp(self): 

52 self.rng = np.random.RandomState(45532) 

53 

54 def testRuns(self): 

55 """ 

56 Test that chipName runs, and that the various iterations of that method 

57 are all self-consistent 

58 """ 

59 nStars = 100 

60 ra0 = 45.0 

61 dec0 = -112.0 

62 rotSkyPos = 135.0 

63 mjd = 42350.0 

64 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

65 mjd=mjd, rotSkyPos=rotSkyPos) 

66 

67 raList = (self.rng.random_sample(nStars)-0.5)*1000.0/3600.0 + ra0 

68 decList = (self.rng.random_sample(nStars)-0.5)*1000.0/3600.0 + dec0 

69 

70 xpList, ypList = pupilCoordsFromRaDec(raList, decList, 

71 obs_metadata=obs, 

72 epoch=2000.0) 

73 

74 names1 = chipNameFromRaDec(raList, decList, 

75 obs_metadata=obs, 

76 epoch=2000.0, 

77 camera=self.camera) 

78 

79 names2 = _chipNameFromRaDec(np.radians(raList), np.radians(decList), 

80 obs_metadata=obs, 

81 epoch=2000.0, 

82 camera=self.camera) 

83 

84 names3 = chipNameFromPupilCoords(xpList, ypList, camera=self.camera) 

85 

86 np.testing.assert_array_equal(names1, names2) 

87 np.testing.assert_array_equal(names1, names3) 

88 

89 isNone = 0 

90 isNotNone = 0 

91 for name in names1: 

92 if name is None: 

93 isNone += 1 

94 else: 

95 isNotNone += 1 

96 

97 self.assertGreater(isNotNone, 0) 

98 

99 def testExceptions(self): 

100 """ 

101 Test that exceptions are raised when they should be 

102 """ 

103 

104 nStars = 10 

105 xpList = self.rng.random_sample(nStars)*0.1 

106 ypList = self.rng.random_sample(nStars)*0.1 

107 

108 obs = ObservationMetaData(pointingRA=25.0, pointingDec=112.0, mjd=42351.0, 

109 rotSkyPos=35.0) 

110 

111 # verify that an exception is raised if you do not pass in a camera 

112 with self.assertRaises(RuntimeError) as context: 

113 chipNameFromPupilCoords(xpList, ypList) 

114 self.assertEqual('No camera defined. Cannot run chipName.', 

115 context.exception.args[0]) 

116 

117 with self.assertRaises(RuntimeError) as context: 

118 chipNameFromRaDec(xpList, ypList, obs_metadata=obs, epoch=2000.0) 

119 self.assertEqual('No camera defined. Cannot run chipName.', 

120 context.exception.args[0]) 

121 

122 with self.assertRaises(RuntimeError) as context: 

123 _chipNameFromRaDec(xpList, ypList, obs_metadata=obs, epoch=2000.0) 

124 self.assertEqual('No camera defined. Cannot run chipName.', 

125 context.exception.args[0]) 

126 

127 # verify that an exception is raised if you do not pass in a numpy array 

128 with self.assertRaises(RuntimeError) as context: 

129 chipNameFromPupilCoords(list(xpList), ypList) 

130 self.assertIn("The arg xPupil", context.exception.args[0]) 

131 

132 with self.assertRaises(RuntimeError) as context: 

133 _chipNameFromRaDec(list(xpList), ypList, obs_metadata=obs, epoch=2000.0) 

134 self.assertIn("The arg ra", context.exception.args[0]) 

135 

136 with self.assertRaises(RuntimeError) as context: 

137 chipNameFromPupilCoords(xpList, list(ypList)) 

138 self.assertIn("The input arguments:", context.exception.args[0]) 

139 self.assertIn("yPupil", context.exception.args[0]) 

140 

141 with self.assertRaises(RuntimeError) as context: 

142 _chipNameFromRaDec(xpList, list(ypList), obs_metadata=obs, epoch=2000.0) 

143 self.assertIn("The input arguments:", context.exception.args[0]) 

144 self.assertIn("Dec", context.exception.args[0]) 

145 

146 # do not need to run the above test on chipNameFromRaDec because 

147 # the conversion from degrees to radians that happens inside that 

148 # method automatically casts lists as numpy arrays 

149 

150 # verify that an exception is raised if the two coordinate arrays contain 

151 # different numbers of elements 

152 xpDummy = self.rng.random_sample(nStars//2) 

153 

154 with self.assertRaises(RuntimeError) as context: 

155 chipNameFromPupilCoords(xpDummy, ypList, camera=self.camera) 

156 

157 self.assertEqual(context.exception.args[0], 

158 "The arrays input to chipNameFromPupilCoords all need " 

159 "to have the same length") 

160 

161 with self.assertRaises(RuntimeError) as context: 

162 chipNameFromRaDec(xpDummy, ypList, obs_metadata=obs, epoch=2000.0, 

163 camera=self.camera) 

164 

165 self.assertEqual(context.exception.args[0], 

166 "The arrays input to chipNameFromRaDec all need to have the same length") 

167 

168 with self.assertRaises(RuntimeError) as context: 

169 _chipNameFromRaDec(xpDummy, ypList, obs_metadata=obs, epoch=2000.0, 

170 camera=self.camera) 

171 

172 self.assertEqual(context.exception.args[0], 

173 "The arrays input to chipNameFromRaDec all need to have the same length") 

174 

175 # verify that an exception is raised if you call chipNameFromRaDec 

176 # without an ObservationMetaData 

177 with self.assertRaises(RuntimeError) as context: 

178 chipNameFromRaDec(xpList, ypList, epoch=2000.0, camera=self.camera) 

179 

180 self.assertEqual(context.exception.args[0], 

181 'You need to pass an ObservationMetaData into chipName') 

182 

183 with self.assertRaises(RuntimeError) as context: 

184 _chipNameFromRaDec(xpList, ypList, epoch=2000.0, camera=self.camera) 

185 

186 self.assertEqual(context.exception.args[0], 

187 'You need to pass an ObservationMetaData into chipName') 

188 

189 # verify that an exception is raised if you call chipNameFromRaDec 

190 # with an ObservationMetaData that has no mjd 

191 obsDummy = ObservationMetaData(pointingRA=25.0, pointingDec=-112.0, 

192 rotSkyPos=112.0) 

193 

194 with self.assertRaises(RuntimeError) as context: 

195 chipNameFromRaDec(xpList, ypList, epoch=2000.0, obs_metadata=obsDummy, 

196 camera=self.camera) 

197 

198 self.assertEqual(context.exception.args[0], 

199 'You need to pass an ObservationMetaData with an mjd into chipName') 

200 

201 with self.assertRaises(RuntimeError) as context: 

202 _chipNameFromRaDec(xpList, ypList, epoch=2000.0, obs_metadata=obsDummy, 

203 camera=self.camera) 

204 

205 self.assertEqual(context.exception.args[0], 

206 'You need to pass an ObservationMetaData with an mjd into chipName') 

207 

208 # verify that an exception is raised if you all chipNameFromRaDec 

209 # using an ObservationMetaData without a rotSkyPos 

210 obsDummy = ObservationMetaData(pointingRA=25.0, pointingDec=-112.0, 

211 mjd=52350.0) 

212 

213 with self.assertRaises(RuntimeError) as context: 

214 chipNameFromRaDec(xpList, ypList, epoch=2000.0, obs_metadata=obsDummy, 

215 camera=self.camera) 

216 

217 self.assertEqual(context.exception.args[0], 

218 'You need to pass an ObservationMetaData with a rotSkyPos into chipName') 

219 

220 with self.assertRaises(RuntimeError) as context: 

221 _chipNameFromRaDec(xpList, ypList, epoch=2000.0, obs_metadata=obsDummy, 

222 camera=self.camera) 

223 

224 self.assertEqual(context.exception.args[0], 

225 'You need to pass an ObservationMetaData with a rotSkyPos into chipName') 

226 

227 def testNaNbecomesNone(self): 

228 """ 

229 Test that chipName maps NaNs and Nones in RA, Dec, and 

230 pupil coordinates to None as chip name 

231 """ 

232 nStars = 100 

233 ra0 = 45.0 

234 dec0 = -112.0 

235 rotSkyPos = 135.0 

236 mjd = 42350.0 

237 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

238 mjd=mjd, rotSkyPos=rotSkyPos) 

239 

240 for badVal in [np.NaN, None]: 

241 

242 raList = (self.rng.random_sample(nStars)-0.5)*5.0/3600.0 + ra0 

243 decList = (self.rng.random_sample(nStars)-0.5)*5.0/3600.0 + dec0 

244 

245 raList[5] = badVal 

246 raList[10] = badVal 

247 decList[10] = badVal 

248 decList[25] = badVal 

249 

250 xpList, ypList = pupilCoordsFromRaDec(raList, decList, 

251 obs_metadata=obs, 

252 epoch=2000.0) 

253 

254 names1 = chipNameFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0, 

255 camera=self.camera) 

256 

257 names2 = _chipNameFromRaDec(np.radians(raList), np.radians(decList), 

258 obs_metadata=obs, epoch=2000.0, camera=self.camera) 

259 

260 names3 = chipNameFromPupilCoords(xpList, ypList, camera=self.camera) 

261 

262 np.testing.assert_array_equal(names1, names2) 

263 np.testing.assert_array_equal(names1, names3) 

264 

265 for ix in range(len(names1)): 

266 if ix != 5 and ix != 10 and ix != 25: 

267 self.assertEqual(names1[ix], 'R:2,2 S:1,1') 

268 self.assertEqual(names2[ix], 'R:2,2 S:1,1') 

269 self.assertEqual(names3[ix], 'R:2,2 S:1,1') 

270 else: 

271 self.assertIsNone(names1[ix], None) 

272 self.assertIsNone(names2[ix], None) 

273 self.assertIsNone(names3[ix], None) 

274 

275 def testPassingFloats(self): 

276 """ 

277 Test that you can pass floats of RA, Dec into chipNameFromRaDec. 

278 

279 Ditto for chipNameFromPupilCoords 

280 """ 

281 

282 ra0 = 45.0 

283 dec0 = -112.0 

284 rotSkyPos = 135.0 

285 mjd = 42350.0 

286 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

287 mjd=mjd, rotSkyPos=rotSkyPos) 

288 

289 nStars = 100 

290 raList = (self.rng.random_sample(nStars)-0.5)*500.0/3600.0 + ra0 

291 decList = (self.rng.random_sample(nStars)-0.5)*500.0/3600.0 + dec0 

292 

293 chipNameList = chipNameFromRaDec(raList, decList, camera=self.camera, obs_metadata=obs) 

294 

295 n_not_none = 0 

296 # now iterate over the list of RA, Dec to make sure that the same name comes back 

297 for ix, (rr, dd) in enumerate(zip(raList, decList)): 

298 test_name = chipNameFromRaDec(rr, dd, camera=self.camera, obs_metadata=obs) 

299 self.assertIsInstance(rr, np.float) 

300 self.assertIsInstance(dd, np.float) 

301 self.assertEqual(chipNameList[ix], test_name) 

302 if test_name is not None: 

303 try: 

304 self.assertIsInstance(test_name, str) 

305 except AssertionError: 

306 self.assertIsInstance(test_name, unicode) 

307 n_not_none += 1 

308 

309 self.assertGreater(n_not_none, 50) 

310 

311 # try it with pupil coordinates 

312 n_not_none = 0 

313 xpList, ypList = pupilCoordsFromRaDec(raList, decList, obs_metadata=obs) 

314 chipNameList = chipNameFromPupilCoords(xpList, ypList, camera=self.camera) 

315 for ix, (xp, yp) in enumerate(zip(xpList, ypList)): 

316 test_name = chipNameFromPupilCoords(xp, yp, camera=self.camera) 

317 self.assertIsInstance(xp, np.float) 

318 self.assertIsInstance(yp, np.float) 

319 self.assertEqual(chipNameList[ix], test_name) 

320 if test_name is not None: 

321 try: 

322 self.assertIsInstance(test_name, str) 

323 except AssertionError: 

324 self.assertIsInstance(test_name, unicode) 

325 n_not_none += 1 

326 

327 self.assertGreater(n_not_none, 50) 

328 

329 def test_one_by_one(self): 

330 """ 

331 Test that runing chipNameFromRaDec one at a time gives 

332 the same results as running in batch mode 

333 """ 

334 ra = 145.0 

335 dec = -25.0 

336 obs = ObservationMetaData(pointingRA=ra, pointingDec=dec, 

337 mjd=59580.0, rotSkyPos=113.0) 

338 rng = np.random.RandomState(100) 

339 theta = rng.random_sample(100)*2.0*np.pi 

340 rr = rng.random_sample(len(theta))*2.0 

341 ra_list = ra + rr*np.cos(theta) 

342 dec_list = dec + rr*np.sin(theta) 

343 name_control = chipNameFromRaDec(ra_list, dec_list, obs_metadata=obs, 

344 camera=self.camera) 

345 is_none = 0 

346 for ra, dec, name in zip(ra_list, dec_list, name_control): 

347 test_name = chipNameFromRaDec(ra, dec, obs_metadata=obs, 

348 camera=self.camera) 

349 self.assertEqual(test_name, name) 

350 if test_name is None: 

351 is_none += 1 

352 self.assertGreater(is_none, 0) 

353 self.assertLess(is_none, len(ra_list)) 

354 

355 

356class PixelCoordTest(unittest.TestCase): 

357 

358 longMessage = True 

359 

360 @classmethod 

361 def setUpClass(cls): 

362 cls.camera = LsstSimMapper().camera 

363 

364 @classmethod 

365 def tearDownClass(cls): 

366 del cls.camera 

367 

368 def setUp(self): 

369 self.rng = np.random.RandomState(11324) 

370 

371 def testConsistency(self): 

372 """ 

373 Test that all of the pixelCoord calculation methods agree with 

374 each other 

375 """ 

376 ra0 = 95.0 

377 dec0 = -33.0 

378 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

379 mjd=52350.0, rotSkyPos=27.0) 

380 

381 nStars = 100 

382 raList = (self.rng.random_sample(nStars)-0.5)*1.5 + ra0 

383 decList = (self.rng.random_sample(nStars)-0.5)*1.5 + dec0 

384 

385 xpList, ypList = pupilCoordsFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0) 

386 

387 chipNameList = chipNameFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0, 

388 camera=self.camera) 

389 

390 for includeDistortion in [True, False]: 

391 

392 xx1, yy1 = pixelCoordsFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0, 

393 camera=self.camera, includeDistortion=includeDistortion) 

394 

395 xx2, yy2 = _pixelCoordsFromRaDec(np.radians(raList), np.radians(decList), 

396 obs_metadata=obs, epoch=2000.0, 

397 camera=self.camera, includeDistortion=includeDistortion) 

398 

399 xx3, yy3 = pixelCoordsFromPupilCoords(xpList, ypList, camera=self.camera, 

400 includeDistortion=includeDistortion) 

401 

402 xx4, yy4 = pixelCoordsFromPupilCoords(xpList, ypList, chipName=chipNameList, 

403 camera=self.camera, 

404 includeDistortion=includeDistortion) 

405 

406 xx5, yy5 = pixelCoordsFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0, 

407 camera=self.camera, includeDistortion=includeDistortion, 

408 chipName=chipNameList) 

409 

410 xx6, yy6 = _pixelCoordsFromRaDec(np.radians(raList), np.radians(decList), 

411 obs_metadata=obs, epoch=2000.0, 

412 camera=self.camera, includeDistortion=includeDistortion, 

413 chipName=chipNameList) 

414 

415 np.testing.assert_array_equal(xx1, xx2) 

416 np.testing.assert_array_equal(xx1, xx3) 

417 np.testing.assert_array_equal(xx1, xx4) 

418 np.testing.assert_array_equal(xx1, xx5) 

419 np.testing.assert_array_equal(xx1, xx6) 

420 

421 np.testing.assert_array_equal(yy1, yy2) 

422 np.testing.assert_array_equal(yy1, yy3) 

423 np.testing.assert_array_equal(yy1, yy4) 

424 np.testing.assert_array_equal(yy1, yy5) 

425 np.testing.assert_array_equal(yy1, yy6) 

426 

427 # make sure that objects which do not fall on a chip 

428 # get NaN pixel coords 

429 ctNaN = 0 

430 ctNotNaN = 0 

431 for x, y, name in zip(xx1, yy1, chipNameList): 

432 if name is None: 

433 np.testing.assert_equal(x, np.NaN) 

434 np.testing.assert_equal(y, np.NaN) 

435 ctNaN += 1 

436 else: 

437 self.assertFalse(np.isnan(x), msg='x is Nan; should not be') 

438 self.assertFalse(np.isnan(y), msg='y is Nan; should not be') 

439 ctNotNaN += 1 

440 

441 self.assertGreater(ctNaN, 0) 

442 self.assertGreater(ctNotNaN, 0) 

443 

444 # now test that passing in the points one at a time gives consistent results 

445 for ix in range(len(raList)): 

446 x_f, y_f = pixelCoordsFromRaDec(raList[ix], decList[ix], obs_metadata=obs, 

447 epoch=2000.0, camera=self.camera, 

448 includeDistortion=includeDistortion) 

449 self.assertIsInstance(x_f, np.float) 

450 self.assertIsInstance(y_f, np.float) 

451 if not np.isnan(x_f): 

452 self.assertEqual(x_f, xx1[ix]) 

453 self.assertEqual(y_f, yy1[ix]) 

454 else: 

455 np.testing.assert_equal(xx1[ix], np.NaN) 

456 np.testing.assert_equal(yy1[ix], np.NaN) 

457 

458 x_f, y_f = pixelCoordsFromRaDec(raList[ix], decList[ix], obs_metadata=obs, 

459 epoch=2000.0, camera=self.camera, 

460 includeDistortion=includeDistortion, 

461 chipName=chipNameList[ix]) 

462 self.assertIsInstance(x_f, np.float) 

463 self.assertIsInstance(y_f, np.float) 

464 if not np.isnan(x_f): 

465 self.assertEqual(x_f, xx1[ix]) 

466 self.assertEqual(y_f, yy1[ix]) 

467 else: 

468 np.testing.assert_equal(xx1[ix], np.NaN) 

469 np.testing.assert_equal(yy1[ix], np.NaN) 

470 

471 x_f, y_f = pixelCoordsFromRaDec(raList[ix], decList[ix], obs_metadata=obs, 

472 epoch=2000.0, camera=self.camera, 

473 includeDistortion=includeDistortion, 

474 chipName=[chipNameList[ix]]) 

475 self.assertIsInstance(x_f, np.float) 

476 self.assertIsInstance(y_f, np.float) 

477 if not np.isnan(x_f): 

478 self.assertEqual(x_f, xx1[ix]) 

479 self.assertEqual(y_f, yy1[ix]) 

480 else: 

481 np.testing.assert_equal(xx1[ix], np.NaN) 

482 np.testing.assert_equal(yy1[ix], np.NaN) 

483 

484 def testSingleChipName(self): 

485 """ 

486 Test that pixelCoordsFromRaDec works when a list of RA, Dec are passed in, 

487 but only one chipName 

488 """ 

489 ra0 = 95.0 

490 dec0 = -33.0 

491 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

492 mjd=52350.0, rotSkyPos=27.0) 

493 

494 nStars = 100 

495 raList = ra0 - (self.rng.random_sample(nStars)-0.5)*1.5 

496 decList = (self.rng.random_sample(nStars)-0.5)*1.5 + dec0 

497 

498 xpList, ypList = pupilCoordsFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0) 

499 

500 chipNameList = chipNameFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0, 

501 camera=self.camera) 

502 

503 chosen_chip = 'R:2,1 S:1,1' 

504 valid_pts = np.where(chipNameList == chosen_chip)[0] 

505 self.assertGreater(len(valid_pts), 1, msg='list_of_chips: %s' % str(chipNameList[valid_pts])) 

506 xPixControl, yPixControl = pixelCoordsFromRaDec(raList[valid_pts], decList[valid_pts], 

507 obs_metadata=obs, 

508 includeDistortion=True, 

509 camera=self.camera) 

510 

511 xPixTest, yPixTest = pixelCoordsFromRaDec(raList[valid_pts], decList[valid_pts], 

512 obs_metadata=obs, 

513 includeDistortion=True, 

514 camera=self.camera, 

515 chipName=chosen_chip) 

516 

517 np.testing.assert_array_almost_equal(xPixControl, xPixTest, 12) 

518 np.testing.assert_array_almost_equal(yPixControl, yPixTest, 12) 

519 

520 xPixTest, yPixTest = pixelCoordsFromRaDec(raList[valid_pts], decList[valid_pts], 

521 obs_metadata=obs, 

522 includeDistortion=True, 

523 camera=self.camera, 

524 chipName=[chosen_chip]) 

525 

526 np.testing.assert_array_almost_equal(xPixControl, xPixTest, 12) 

527 np.testing.assert_array_almost_equal(yPixControl, yPixTest, 12) 

528 

529 # test raDecFromPixelCoords 

530 raTest, decTest = raDecFromPixelCoords(xPixControl, yPixControl, chosen_chip, 

531 camera=self.camera, obs_metadata=obs, 

532 includeDistortion=True) 

533 

534 distance = arcsecFromRadians(haversine(np.radians(raList[valid_pts]), 

535 np.radians(decList[valid_pts]), 

536 np.radians(raTest), np.radians(decTest))) 

537 

538 self.assertLess(distance.max(), 0.004) # because of the imprecision in 

539 # _icrsFromObserved, this is the best we can do 

540 

541 raTest, decTest = raDecFromPixelCoords(xPixControl, yPixControl, [chosen_chip], 

542 camera=self.camera, obs_metadata=obs, 

543 includeDistortion=True) 

544 

545 distance = arcsecFromRadians(haversine(np.radians(raList[valid_pts]), 

546 np.radians(decList[valid_pts]), 

547 np.radians(raTest), np.radians(decTest))) 

548 

549 self.assertLess(distance.max(), 0.004) 

550 

551 def testExceptions(self): 

552 """ 

553 Test that pixelCoord calculation methods raise exceptions when 

554 they should 

555 """ 

556 nPoints = 100 

557 xpList = self.rng.random_sample(nPoints)*np.radians(1.0) 

558 ypList = self.rng.random_sample(nPoints)*np.radians(1.0) 

559 obs = ObservationMetaData(pointingRA=25.0, 

560 pointingDec=-36.0, 

561 rotSkyPos=122.0, 

562 mjd=41325.0) 

563 

564 raList = self.rng.random_sample(nPoints)*1.0+25.0 

565 decList = self.rng.random_sample(nPoints)*1.0-36.0 

566 

567 # check that an error is raised when you forget to 

568 # pass in a camera 

569 with self.assertRaises(RuntimeError) as context: 

570 pixelCoordsFromPupilCoords(xpList, ypList) 

571 

572 self.assertEqual(context.exception.args[0], 

573 'Camera not specified. Cannot calculate pixel coordinates.') 

574 

575 with self.assertRaises(RuntimeError) as context: 

576 pixelCoordsFromRaDec(raList, decList, obs_metadata=obs, 

577 epoch=2000.0) 

578 

579 self.assertEqual(context.exception.args[0], 

580 'Camera not specified. Cannot calculate pixel coordinates.') 

581 

582 with self.assertRaises(RuntimeError) as context: 

583 _pixelCoordsFromRaDec(np.radians(raList), 

584 np.radians(decList), 

585 obs_metadata=obs, 

586 epoch=2000.0) 

587 

588 self.assertEqual(context.exception.args[0], 

589 'Camera not specified. Cannot calculate pixel coordinates.') 

590 

591 # test that an exception is raised when you pass in something 

592 # that is not a numpy array 

593 with self.assertRaises(RuntimeError) as context: 

594 pixelCoordsFromPupilCoords(list(xpList), ypList, 

595 camera=self.camera) 

596 

597 self.assertIn("The arg xPupil", context.exception.args[0]) 

598 

599 with self.assertRaises(RuntimeError) as context: 

600 pixelCoordsFromPupilCoords(xpList, list(ypList), 

601 camera=self.camera) 

602 

603 self.assertIn("The input arguments:", context.exception.args[0]) 

604 self.assertIn("yPupil", context.exception.args[0]) 

605 

606 with self.assertRaises(RuntimeError) as context: 

607 _pixelCoordsFromRaDec(list(np.radians(raList)), 

608 np.radians(decList), 

609 obs_metadata=obs, 

610 epoch=2000.0, 

611 camera=self.camera) 

612 

613 self.assertIn("The arg ra", context.exception.args[0]) 

614 

615 with self.assertRaises(RuntimeError) as context: 

616 _pixelCoordsFromRaDec(np.radians(raList), 

617 list(np.radians(decList)), 

618 obs_metadata=obs, 

619 epoch=2000.0, 

620 camera=self.camera) 

621 

622 self.assertIn("The input arguments:", context.exception.args[0]) 

623 self.assertIn("dec", context.exception.args[0]) 

624 

625 # do not need to run the above test on pixelCoordsFromRaDec, 

626 # because the conversion from degrees to radians that happens 

627 # inside that method automatically casts lists as numpy arrays 

628 

629 # test that an exception is raised if you pass in mis-matched 

630 # input arrays 

631 with self.assertRaises(RuntimeError) as context: 

632 pixelCoordsFromPupilCoords(xpList, ypList[0:10], 

633 camera=self.camera) 

634 

635 self.assertEqual(context.exception.args[0], 

636 "The arrays input to pixelCoordsFromPupilCoords " 

637 "all need to have the same length") 

638 

639 with self.assertRaises(RuntimeError) as context: 

640 pixelCoordsFromRaDec(raList, decList[0:10], 

641 obs_metadata=obs, 

642 epoch=2000.0, 

643 camera=self.camera) 

644 

645 self.assertEqual(context.exception.args[0], 

646 "The arrays input to pixelCoordsFromRaDec all need " 

647 "to have the same length") 

648 

649 with self.assertRaises(RuntimeError) as context: 

650 _pixelCoordsFromRaDec(np.radians(raList), 

651 np.radians(decList[0:10]), 

652 obs_metadata=obs, 

653 epoch=2000.0, 

654 camera=self.camera) 

655 

656 self.assertEqual(context.exception.args[0], 

657 "The arrays input to pixelCoordsFromRaDec all need " 

658 "to have the same length") 

659 

660 # test that an error is raised if you pass an incorrect 

661 # number of chipNames to pixelCoordsFromPupilCoords 

662 with self.assertRaises(RuntimeError) as context: 

663 pixelCoordsFromPupilCoords(xpList, ypList, chipName=['R:2,2 S:1,1']*10, 

664 camera=self.camera) 

665 

666 self.assertIn("You passed 10 chipNames", context.exception.args[0]) 

667 

668 with self.assertRaises(RuntimeError) as context: 

669 pixelCoordsFromRaDec(raList, decList, chipName=['R:2,2 S:1,1']*10, 

670 camera=self.camera, 

671 obs_metadata=obs, 

672 epoch=2000.0) 

673 

674 self.assertIn("You passed 10 chipNames", context.exception.args[0]) 

675 

676 with self.assertRaises(RuntimeError) as context: 

677 _pixelCoordsFromRaDec(np.radians(raList), 

678 np.radians(decList), 

679 chipName=['R:2,2 S:1,1']*10, 

680 camera=self.camera, 

681 obs_metadata=obs, 

682 epoch=2000.0) 

683 

684 self.assertIn("You passed 10 chipNames", context.exception.args[0]) 

685 

686 # test that an exception is raised if you call one of the 

687 # pixelCoordsFromRaDec methods without an ObservationMetaData 

688 with self.assertRaises(RuntimeError) as context: 

689 pixelCoordsFromRaDec(raList, decList, 

690 camera=self.camera, epoch=2000.0) 

691 

692 self.assertEqual(context.exception.args[0], 

693 'You need to pass an ObservationMetaData into ' 

694 'pixelCoordsFromRaDec') 

695 

696 with self.assertRaises(RuntimeError) as context: 

697 _pixelCoordsFromRaDec(raList, decList, 

698 camera=self.camera, epoch=2000.0) 

699 

700 self.assertEqual(context.exception.args[0], 

701 'You need to pass an ObservationMetaData into ' 

702 'pixelCoordsFromRaDec') 

703 

704 # test that an exception is raised if you try to use an 

705 # ObservationMetaData without an mjd 

706 obsDummy = ObservationMetaData(pointingRA=25.0, 

707 pointingDec=-36.0, 

708 rotSkyPos=112.0) 

709 

710 with self.assertRaises(RuntimeError) as context: 

711 pixelCoordsFromRaDec(raList, decList, 

712 camera=self.camera, 

713 epoch=2000.0, 

714 obs_metadata=obsDummy) 

715 

716 self.assertEqual(context.exception.args[0], 

717 'You need to pass an ObservationMetaData ' 

718 'with an mjd into pixelCoordsFromRaDec') 

719 

720 with self.assertRaises(RuntimeError) as context: 

721 _pixelCoordsFromRaDec(raList, decList, 

722 camera=self.camera, 

723 epoch=2000.0, 

724 obs_metadata=obsDummy) 

725 

726 self.assertEqual(context.exception.args[0], 

727 'You need to pass an ObservationMetaData ' 

728 'with an mjd into pixelCoordsFromRaDec') 

729 

730 # test that an exception is raised if you try to use an 

731 # ObservationMetaData without a rotSkyPos 

732 obsDummy = ObservationMetaData(pointingRA=25.0, 

733 pointingDec=-36.0, 

734 mjd=53000.0) 

735 

736 with self.assertRaises(RuntimeError) as context: 

737 pixelCoordsFromRaDec(raList, decList, 

738 camera=self.camera, 

739 epoch=2000.0, 

740 obs_metadata=obsDummy) 

741 

742 self.assertEqual(context.exception.args[0], 

743 'You need to pass an ObservationMetaData ' 

744 'with a rotSkyPos into pixelCoordsFromRaDec') 

745 

746 obsDummy = ObservationMetaData(pointingRA=25.0, 

747 pointingDec=-36.0, 

748 mjd=53000.0) 

749 with self.assertRaises(RuntimeError) as context: 

750 _pixelCoordsFromRaDec(raList, decList, 

751 camera=self.camera, 

752 epoch=2000.0, 

753 obs_metadata=obsDummy) 

754 

755 self.assertEqual(context.exception.args[0], 

756 'You need to pass an ObservationMetaData ' 

757 'with a rotSkyPos into pixelCoordsFromRaDec') 

758 

759 @unittest.skip("The test camera has changed") 

760 def testResults(self): 

761 """ 

762 Test that the results of the pixelCoords methods make sense. Note that the test 

763 camera has a platescale of 0.02 arcsec per pixel (2.0 arcsec per mm encoded in 

764 CameraForUnitTests.py and 10 microns per pixel encoded in cameraData/focalplanelayout.txt). 

765 We will use that to set the control values for our unit test. 

766 

767 Note: This unit test will fail if the test camera ever changes. 

768 

769 Note: Because we have already tested the self-consistency of 

770 pixelCoordsFromPupilCoords and pixelCoordsFromRaDec, we will 

771 only be testing pixelCoordsFromPupilCoords here, because it 

772 is easier. 

773 """ 

774 

775 arcsecPerPixel = 0.02 

776 arcsecPerMicron = 0.002 

777 

778 # list a bunch of detector centers in radians 

779 x22 = 0.0 

780 y22 = 0.0 

781 

782 x32 = radiansFromArcsec(40000.0 * arcsecPerMicron) 

783 y32 = 0.0 

784 

785 x40 = radiansFromArcsec(80000.0 * arcsecPerMicron) 

786 y40 = radiansFromArcsec(-80000.0 * arcsecPerMicron) 

787 

788 # assemble a bunch of displacements in pixels 

789 dxPixList = [] 

790 dyPixList = [] 

791 for xx in np.arange(-1999.0, 1999.0, 500.0): 

792 for yy in np.arange(-1999.0, 1999.0, 500.0): 

793 dxPixList.append(xx) 

794 dyPixList.append(yy) 

795 

796 dxPixList = np.array(dxPixList) 

797 dyPixList = np.array(dyPixList) 

798 

799 # convert to raidans 

800 dxPupList = radiansFromArcsec(dxPixList*arcsecPerPixel) 

801 dyPupList = radiansFromArcsec(dyPixList*arcsecPerPixel) 

802 

803 # assemble a bunch of test pupil coordinate pairs 

804 xPupList = x22 + dxPupList 

805 yPupList = y22 + dyPupList 

806 xPupList = np.append(xPupList, x32 + dxPupList) 

807 yPupList = np.append(yPupList, y32 + dyPupList) 

808 xPupList = np.append(xPupList, x40 + dxPupList) 

809 yPupList = np.append(yPupList, y40 + dyPupList) 

810 

811 # this is what the chipNames ought to be for these points 

812 chipNameControl = np.array(['Det22'] * len(dxPupList)) 

813 chipNameControl = np.append(chipNameControl, ['Det32'] * len(dxPupList)) 

814 chipNameControl = np.append(chipNameControl, ['Det40'] * len(dxPupList)) 

815 

816 chipNameTest = chipNameFromPupilCoords(xPupList, yPupList, camera=self.camera) 

817 

818 # verify that the test points fall on the expected chips 

819 np.testing.assert_array_equal(chipNameControl, chipNameTest) 

820 

821 # Note, the somewhat backwards way in which we go from dxPixList to 

822 # xPixControl is due to the fact that pixel coordinates are actually 

823 # aligned so that the x-axis is along the read-out direction, which 

824 # makes positive x in pixel coordinates correspond to positive y 

825 # in pupil coordinates 

826 xPixControl = 1999.5 + dyPixList 

827 yPixControl = 1999.5 - dxPixList 

828 xPixControl = np.append(xPixControl, 1999.5 + dyPixList) 

829 yPixControl = np.append(yPixControl, 1999.5 - dxPixList) 

830 xPixControl = np.append(xPixControl, 1999.5 + dyPixList) 

831 yPixControl = np.append(yPixControl, 1999.5 - dxPixList) 

832 

833 # verify that the pixel coordinates are as expected to within 0.01 pixel 

834 xPixTest, yPixTest = pixelCoordsFromPupilCoords(xPupList, yPupList, camera=self.camera, 

835 includeDistortion=False) 

836 

837 np.testing.assert_array_almost_equal(xPixTest, xPixControl, 2) 

838 np.testing.assert_array_almost_equal(yPixTest, yPixControl, 2) 

839 

840 # now test that we get the same results when we pass the pupil coords in 

841 # one at a time 

842 for ix in range(len(xPupList)): 

843 xpx_f, ypx_f = pixelCoordsFromPupilCoords(xPupList[ix], yPupList[ix], 

844 camera=self.camera, 

845 includeDistortion=False) 

846 self.assertIsInstance(xpx_f, np.float) 

847 self.assertIsInstance(ypx_f, np.float) 

848 self.assertAlmostEqual(xpx_f, xPixTest[ix], 12) 

849 self.assertAlmostEqual(ypx_f, yPixTest[ix], 12) 

850 

851 def testOffChipResults(self): 

852 """ 

853 Test that the results of the pixelCoords methods make sense in the case 

854 that you specify a chip name that is not necessarily the chip on which 

855 the object actually fell. 

856 

857 Note that the test camera has a platescale of 0.02 arcsec per pixel 

858 (2.0 arcsec per mm encoded in CameraForUnitTests.py and 10 microns per 

859 pixel encoded in cameraData/focalplanelayout.txt). We will use that to 

860 set the control values for our unit test. 

861 

862 Note: This unit test will fail if the test camera ever changes. 

863 

864 Note: Because we have already tested the self-consistency of 

865 pixelCoordsFromPupilCoords and pixelCoordsFromRaDec, we will 

866 only be testing pixelCoordsFromPupilCoords here, because it 

867 is easier. 

868 """ 

869 

870 arcsecPerPixel = 0.2 

871 arcsecPerMicron = 0.02 

872 

873 # list a bunch of detector centers in radians 

874 x22 = 0.0 

875 y22 = 0.0 

876 

877 x32 = 0.008 

878 y32 = 0.0 

879 

880 x40 = 0.0 

881 y40 = -0.012 

882 

883 # assemble a bunch of displacements in pixels 

884 dxPixList = [] 

885 dyPixList = [] 

886 for xx in np.arange(-1000.0, 1000.0, 250.0): 

887 for yy in np.arange(-1000.0, 1000.0, 250.0): 

888 dxPixList.append(xx) 

889 dyPixList.append(yy) 

890 

891 dxPixList = np.array(dxPixList) 

892 dyPixList = np.array(dyPixList) 

893 

894 # convert to radians 

895 dxPupList = radiansFromArcsec(dxPixList*arcsecPerPixel) 

896 dyPupList = radiansFromArcsec(dyPixList*arcsecPerPixel) 

897 

898 # assemble a bunch of test pupil coordinate pairs 

899 xPupList = x22 + dxPupList 

900 yPupList = y22 + dyPupList 

901 xPupList = np.append(xPupList, x32 + dxPupList) 

902 yPupList = np.append(yPupList, y32 + dyPupList) 

903 xPupList = np.append(xPupList, x40 + dxPupList) 

904 yPupList = np.append(yPupList, y40 + dyPupList) 

905 

906 # this is what the chipNames ought to be for these points 

907 chipNameControl = np.array(['R:2,2 S:1,1'] * len(dxPupList)) 

908 chipNameControl = np.append(chipNameControl, ['R:3,2 S:0,1'] * len(dxPupList)) 

909 chipNameControl = np.append(chipNameControl, ['R:2,1 S:1,1'] * len(dxPupList)) 

910 

911 chipNameTest = chipNameFromPupilCoords(xPupList, yPupList, camera=self.camera) 

912 print(np.unique(chipNameTest)) 

913 

914 # verify that the test points fall on the expected chips 

915 np.testing.assert_array_equal(chipNameControl, chipNameTest) 

916 

917 

918 """Something about the new camera doesn't match, so this doesn't quite work. 

919 Commenting this section out for now - scale wrong maybe? Or bigger camera (and 

920 thus the pixels don't match because pixels within ccd vs. focal plane?)? 

921 

922 # Note, the somewhat backwards way in which we go from dxPupList to 

923 # xPixControl is due to the fact that pixel coordinates are actually 

924 # aligned so that the x-axis is along the read-out direction, which 

925 # makes positive x in pixel coordinates correspond to positive y 

926 # in pupil coordinates 

927 xPixControl = 1000 + arcsecFromRadians(yPupList - y40)/arcsecPerPixel 

928 yPixControl = 1000 - arcsecFromRadians(xPupList - x40)/arcsecPerPixel 

929 

930 # verify that the pixel coordinates are as expected to within 0.01 pixel 

931 inputChipNames = ['R:2,2 S:1,1'] * len(xPupList) 

932 xPixTest, yPixTest = pixelCoordsFromPupilCoords(xPupList, yPupList, camera=self.camera, 

933 includeDistortion=False, 

934 chipName=inputChipNames) 

935 

936 np.testing.assert_array_almost_equal(xPixTest, xPixControl, 2) 

937 np.testing.assert_array_almost_equal(yPixTest, yPixControl, 2) 

938 

939 # now test that we get the same results when we pass the pupil coords in 

940 # one at a time 

941 for ix in range(len(xPupList)): 

942 xpx_f, ypx_f = pixelCoordsFromPupilCoords(xPupList[ix], yPupList[ix], 

943 camera=self.camera, 

944 includeDistortion=False, 

945 chipName=inputChipNames[ix]) 

946 self.assertIsInstance(xpx_f, np.float) 

947 self.assertIsInstance(ypx_f, np.float) 

948 self.assertAlmostEqual(xpx_f, xPixTest[ix], 12) 

949 self.assertAlmostEqual(ypx_f, yPixTest[ix], 12) 

950 

951 # We will now use this opportunity to test that pupilCoordsFromPixelCoords 

952 # and pixelCoordsFromPupilCoords work when we pass in a list of pixel 

953 # coords, but only one chip name 

954 xPix_one, yPix_one = pixelCoordsFromPupilCoords(xPupList, yPupList, 

955 camera=self.camera, 

956 includeDistortion=False, 

957 chipName='R:2,1 S:1,1') 

958 

959 np.testing.assert_array_almost_equal(xPix_one, xPixTest, 12) 

960 np.testing.assert_array_almost_equal(yPix_one, yPixTest, 12) 

961 

962 xPix_one, yPix_one = pixelCoordsFromPupilCoords(xPupList, yPupList, 

963 camera=self.camera, 

964 includeDistortion=False, 

965 chipName='R:2,1 S:1,1') 

966 

967 np.testing.assert_array_almost_equal(xPix_one, xPixTest, 12) 

968 np.testing.assert_array_almost_equal(yPix_one, yPixTest, 12) 

969 

970 xPupTest, yPupTest = pupilCoordsFromPixelCoords(xPixTest, yPixTest, 'R:2,1 S:1,1', 

971 camera=self.camera, 

972 includeDistortion=False) 

973 

974 np.testing.assert_array_almost_equal(xPupTest, xPupList, 12) 

975 np.testing.assert_array_almost_equal(yPupTest, yPupList, 12) 

976 

977 xPupTest, yPupTest = pupilCoordsFromPixelCoords(xPixTest, yPixTest, ['Det40'], 

978 camera=self.camera, 

979 includeDistortion=False) 

980 

981 np.testing.assert_array_almost_equal(xPupTest, xPupList, 12) 

982 np.testing.assert_array_almost_equal(yPupTest, yPupList, 12) 

983 """ 

984 

985 def testNaN(self): 

986 """ 

987 Verify that NaNs and Nones input to pixelCoordinate calculation methods result 

988 in NaNs coming out 

989 """ 

990 ra0 = 25.0 

991 dec0 = -35.0 

992 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

993 rotSkyPos=42.0, mjd=42356.0) 

994 

995 raList = self.rng.random_sample(100)*100.0/3600.0 + ra0 

996 decList = self.rng.random_sample(100)*100.0/3600.0 + dec0 

997 chipNameList = chipNameFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0, 

998 camera=self.camera) 

999 

1000 # make sure that all of the test points actually fall on chips 

1001 for name in chipNameList: 

1002 self.assertIsNotNone(name) 

1003 

1004 xPupList, yPupList = pupilCoordsFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0) 

1005 

1006 # make sure that none of the test points already result in NaN pixel coordinates 

1007 xPixList, yPixList = pixelCoordsFromRaDec(raList, decList, obs_metadata=obs, 

1008 epoch=2000.0, camera=self.camera) 

1009 

1010 for xx, yy in zip(xPixList, yPixList): 

1011 self.assertFalse(np.isnan(xx), msg='xx is NaN; should not be') 

1012 self.assertFalse(np.isnan(yy), msg='yy is NaN; should not be') 

1013 self.assertIsNotNone(xx, None) 

1014 self.assertIsNotNone(yy, None) 

1015 

1016 for badVal in [np.NaN, None]: 

1017 raList[5] = badVal 

1018 decList[7] = badVal 

1019 raList[9] = badVal 

1020 decList[9] = badVal 

1021 

1022 xPixList, yPixList = pixelCoordsFromRaDec(raList, decList, obs_metadata=obs, 

1023 epoch=2000.0, camera=self.camera) 

1024 

1025 for ix, (xx, yy) in enumerate(zip(xPixList, yPixList)): 

1026 if ix in [5, 7, 9]: 

1027 np.testing.assert_equal(xx, np.NaN) 

1028 np.testing.assert_equal(yy, np.NaN) 

1029 else: 

1030 self.assertFalse(np.isnan(xx), msg='xx is NaN; should not be') 

1031 self.assertFalse(np.isnan(yy), msg='yy is NaN; should not be') 

1032 self.assertIsNotNone(xx) 

1033 self.assertIsNotNone(yy) 

1034 

1035 xPixList, yPixList = _pixelCoordsFromRaDec(np.radians(raList), np.radians(decList), 

1036 obs_metadata=obs, epoch=2000.0, camera=self.camera) 

1037 

1038 for ix, (xx, yy) in enumerate(zip(xPixList, yPixList)): 

1039 if ix in [5, 7, 9]: 

1040 np.testing.assert_equal(xx, np.NaN) 

1041 np.testing.assert_equal(yy, np.NaN) 

1042 else: 

1043 self.assertFalse(np.isnan(xx), msg='xx is NaN; should not be') 

1044 self.assertFalse(np.isnan(yy), msg='yy is NaN; should not be') 

1045 self.assertIsNotNone(xx) 

1046 self.assertIsNotNone(yy) 

1047 

1048 xPupList[5] = badVal 

1049 yPupList[7] = badVal 

1050 xPupList[9] = badVal 

1051 yPupList[9] = badVal 

1052 xPixList, yPixList = pixelCoordsFromPupilCoords(xPupList, yPupList, camera=self.camera) 

1053 for ix, (xx, yy) in enumerate(zip(xPixList, yPixList)): 

1054 

1055 # verify the same result if we had passed in pupil coords one-at-a-time 

1056 xpx_f, ypx_f = pixelCoordsFromPupilCoords(xPupList[ix], yPupList[ix], camera=self.camera) 

1057 self.assertIsInstance(xpx_f, np.float) 

1058 self.assertIsInstance(ypx_f, np.float) 

1059 

1060 if ix in [5, 7, 9]: 

1061 np.testing.assert_equal(xx, np.NaN) 

1062 np.testing.assert_equal(yy, np.NaN) 

1063 np.testing.assert_equal(xpx_f, np.NaN) 

1064 np.testing.assert_equal(ypx_f, np.NaN) 

1065 else: 

1066 self.assertFalse(np.isnan(xx), msg='xx is NaN; should not be') 

1067 self.assertFalse(np.isnan(yy), msg='yy is NaN; should not be') 

1068 self.assertIsNotNone(xx) 

1069 self.assertIsNotNone(yy) 

1070 self.assertAlmostEqual(xx, xpx_f, 12) 

1071 self.assertAlmostEqual(yy, ypx_f, 12) 

1072 

1073 def testDistortion(self): 

1074 """ 

1075 Make sure that the results from pixelCoordsFromPupilCoords are different 

1076 if includeDistortion is True as compared to if includeDistortion is False 

1077 

1078 Note: This test passes because the test camera has a pincushion distortion. 

1079 If we take that away, the test will no longer pass. 

1080 """ 

1081 xp = radiansFromArcsec((self.rng.random_sample(100)-0.5)*500.0) 

1082 yp = radiansFromArcsec((self.rng.random_sample(100)-0.5)*500.0) 

1083 

1084 xu, yu = pixelCoordsFromPupilCoords(xp, yp, camera=self.camera, includeDistortion=False) 

1085 xd, yd = pixelCoordsFromPupilCoords(xp, yp, camera=self.camera, includeDistortion=True) 

1086 

1087 # just verify that the distorted versus undistorted coordinates vary in the 

1088 # 4th decimal place 

1089 self.assertRaises(AssertionError, 

1090 np.testing.assert_array_almost_equal, xu, xd, 4) 

1091 

1092 self.assertRaises(AssertionError, 

1093 np.testing.assert_array_almost_equal, yu, yd, 4) 

1094 

1095 # make sure that distortions are also present when we pass pupil coordinates in 

1096 # one-at-a-time 

1097 for ix in range(len(xp)): 

1098 x_f, y_f = pixelCoordsFromPupilCoords(xp[ix], yp[ix], camera=self.camera, 

1099 includeDistortion=True) 

1100 

1101 self.assertAlmostEqual(xd[ix], x_f, 12) 

1102 self.assertAlmostEqual(yd[ix], y_f, 12) 

1103 self.assertIsInstance(x_f, np.float) 

1104 self.assertIsInstance(y_f, np.float) 

1105 

1106 

1107class FocalPlaneCoordTest(unittest.TestCase): 

1108 

1109 @classmethod 

1110 def setUpClass(cls): 

1111 cls.camera = LsstSimMapper().camera 

1112 

1113 @classmethod 

1114 def tearDownClass(cls): 

1115 del cls.camera 

1116 

1117 def setUp(self): 

1118 self.rng = np.random.RandomState(8374522) 

1119 

1120 def testConsistency(self): 

1121 """ 

1122 Test that all of the focalPlaneCoord calculation methods 

1123 return self-consistent answers. 

1124 """ 

1125 

1126 ra0 = 34.1 

1127 dec0 = -23.0 

1128 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

1129 mjd=43257.0, rotSkyPos = 127.0) 

1130 

1131 raCenter, decCenter = observedFromICRS(np.array([ra0]), 

1132 np.array([dec0]), 

1133 obs_metadata=obs, 

1134 epoch=2000.0) 

1135 

1136 nStars = 100 

1137 raList = self.rng.random_sample(nStars)*1000.0/3600.0 + raCenter[0] 

1138 decList = self.rng.random_sample(nStars)*1000.0/3600.0 + decCenter[0] 

1139 

1140 xPupList, yPupList = pupilCoordsFromRaDec(raList, decList, 

1141 obs_metadata=obs, 

1142 epoch=2000.0) 

1143 

1144 xf1, yf1 = focalPlaneCoordsFromRaDec(raList, decList, 

1145 obs_metadata=obs, 

1146 epoch=2000.0, camera=self.camera) 

1147 

1148 xf2, yf2 = _focalPlaneCoordsFromRaDec(np.radians(raList), 

1149 np.radians(decList), 

1150 obs_metadata=obs, 

1151 epoch=2000.0, camera=self.camera) 

1152 

1153 xf3, yf3 = focalPlaneCoordsFromPupilCoords(xPupList, yPupList, 

1154 camera=self.camera) 

1155 

1156 np.testing.assert_array_equal(xf1, xf2) 

1157 np.testing.assert_array_equal(xf1, xf3) 

1158 np.testing.assert_array_equal(yf1, yf2) 

1159 np.testing.assert_array_equal(yf1, yf3) 

1160 

1161 for x, y in zip(xf1, yf1): 

1162 self.assertFalse(np.isnan(x), msg='x is NaN; should not be') 

1163 self.assertIsNotNone(x) 

1164 self.assertFalse(np.isnan(y), msg='y is NaN; should not be') 

1165 self.assertIsNotNone(y) 

1166 

1167 # now test that focalPlaneCoordsFromRaDec and 

1168 # focalPlaneCoordsFromPupilCoords give the same results 

1169 # when you pass the inputs in one-by-one 

1170 for ix in range(len(xf1)): 

1171 x_f, y_f = focalPlaneCoordsFromRaDec(raList[ix], decList[ix], 

1172 camera=self.camera, 

1173 obs_metadata=obs, epoch=2000.0) 

1174 self.assertIsInstance(x_f, float) 

1175 self.assertIsInstance(y_f, float) 

1176 self.assertEqual(x_f, xf1[ix]) 

1177 self.assertEqual(y_f, yf1[ix]) 

1178 

1179 x_f, y_f = focalPlaneCoordsFromPupilCoords(xPupList[ix], yPupList[ix], 

1180 camera=self.camera) 

1181 self.assertIsInstance(x_f, float) 

1182 self.assertIsInstance(y_f, float) 

1183 self.assertEqual(x_f, xf1[ix]) 

1184 self.assertEqual(y_f, yf1[ix]) 

1185 

1186 def testExceptions(self): 

1187 """ 

1188 Test that the focalPlaneCoord methods raise the exceptions 

1189 (with the correct messages) when they should. 

1190 """ 

1191 

1192 ra0 = 34.0 

1193 dec0 = -19.0 

1194 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

1195 rotSkyPos=61.0, mjd=52349.0) 

1196 

1197 nStars = 10 

1198 raList = (self.rng.random_sample(nStars)-0.5) + ra0 

1199 decList = (self.rng.random_sample(nStars)-0.5) + dec0 

1200 xPupList, yPupList = pupilCoordsFromRaDec(raList, decList, 

1201 obs_metadata=obs, 

1202 epoch=2000.0) 

1203 

1204 # verify that an error is raised when you forget to pass 

1205 # in a camera 

1206 with self.assertRaises(RuntimeError) as context: 

1207 xf, yf = focalPlaneCoordsFromPupilCoords(xPupList, yPupList) 

1208 self.assertEqual(context.exception.args[0], 

1209 "You cannot calculate focal plane coordinates " 

1210 "without specifying a camera") 

1211 

1212 with self.assertRaises(RuntimeError) as context: 

1213 xf, yf = focalPlaneCoordsFromRaDec(raList, decList, 

1214 obs_metadata=obs, 

1215 epoch=2000.0) 

1216 

1217 self.assertEqual(context.exception.args[0], 

1218 "You cannot calculate focal plane coordinates " 

1219 "without specifying a camera") 

1220 

1221 with self.assertRaises(RuntimeError) as context: 

1222 xf, yf = _focalPlaneCoordsFromRaDec(raList, decList, 

1223 obs_metadata=obs, 

1224 epoch=2000.0) 

1225 

1226 self.assertEqual(context.exception.args[0], 

1227 "You cannot calculate focal plane coordinates " 

1228 "without specifying a camera") 

1229 

1230 # test that an error is raised when you pass in something that 

1231 # is not a numpy array 

1232 with self.assertRaises(RuntimeError) as context: 

1233 xf, yf = focalPlaneCoordsFromPupilCoords(list(xPupList), yPupList, 

1234 camera=self.camera) 

1235 self.assertIn("The arg xPupil", context.exception.args[0]) 

1236 

1237 with self.assertRaises(RuntimeError) as context: 

1238 xf, yf = focalPlaneCoordsFromPupilCoords(xPupList, list(yPupList), 

1239 camera=self.camera) 

1240 self.assertIn("The input arguments:", context.exception.args[0]) 

1241 self.assertIn("yPupil", context.exception.args[0]) 

1242 

1243 with self.assertRaises(RuntimeError) as context: 

1244 xf, yf = _focalPlaneCoordsFromRaDec(list(raList), decList, 

1245 obs_metadata=obs, 

1246 epoch=2000.0, 

1247 camera=self.camera) 

1248 self.assertIn("The arg ra", context.exception.args[0]) 

1249 

1250 with self.assertRaises(RuntimeError) as context: 

1251 xf, yf = _focalPlaneCoordsFromRaDec(raList, list(decList), 

1252 obs_metadata=obs, 

1253 epoch=2000.0, 

1254 camera=self.camera) 

1255 self.assertIn("The input arguments:", context.exception.args[0]) 

1256 self.assertIn("dec", context.exception.args[0]) 

1257 

1258 # we do not have to run the test above on focalPlaneCoordsFromRaDec 

1259 # because the conversion to radians automatically casts lists into 

1260 # numpy arrays 

1261 

1262 # test that an error is raised if you pass in mismatched numbers 

1263 # of x and y coordinates 

1264 with self.assertRaises(RuntimeError) as context: 

1265 xf, yf = focalPlaneCoordsFromPupilCoords(xPupList, yPupList[0:4], 

1266 camera=self.camera) 

1267 self.assertEqual(context.exception.args[0], 

1268 "The arrays input to focalPlaneCoordsFromPupilCoords " 

1269 "all need to have the same length") 

1270 

1271 with self.assertRaises(RuntimeError) as context: 

1272 xf, yf = focalPlaneCoordsFromRaDec(raList, decList[0:4], 

1273 obs_metadata=obs, 

1274 epoch=2000.0, 

1275 camera=self.camera) 

1276 self.assertEqual(context.exception.args[0], 

1277 "The arrays input to focalPlaneCoordsFromRaDec " 

1278 "all need to have the same length") 

1279 

1280 with self.assertRaises(RuntimeError) as context: 

1281 xf, yf = _focalPlaneCoordsFromRaDec(raList, decList[0:4], 

1282 obs_metadata=obs, 

1283 epoch=2000.0, 

1284 camera=self.camera) 

1285 self.assertEqual(context.exception.args[0], 

1286 "The arrays input to focalPlaneCoordsFromRaDec " 

1287 "all need to have the same length") 

1288 

1289 # test that an error is raised if you call 

1290 # focalPlaneCoordsFromRaDec without an ObservationMetaData 

1291 with self.assertRaises(RuntimeError) as context: 

1292 xf, yf = focalPlaneCoordsFromRaDec(raList, decList, 

1293 epoch=2000.0, 

1294 camera=self.camera) 

1295 

1296 self.assertEqual(context.exception.args[0], 

1297 "You have to specify an ObservationMetaData to run " 

1298 "focalPlaneCoordsFromRaDec") 

1299 

1300 with self.assertRaises(RuntimeError) as context: 

1301 xf, yf = _focalPlaneCoordsFromRaDec(raList, decList, 

1302 epoch=2000.0, 

1303 camera=self.camera) 

1304 self.assertEqual(context.exception.args[0], 

1305 "You have to specify an ObservationMetaData to run " 

1306 "focalPlaneCoordsFromRaDec") 

1307 

1308 # test that an error is raised if you pass an ObservationMetaData 

1309 # without an mjd into focalPlaneCoordsFromRaDec 

1310 obsDummy = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

1311 rotSkyPos=112.0) 

1312 with self.assertRaises(RuntimeError) as context: 

1313 xf, yf = focalPlaneCoordsFromRaDec(raList, decList, 

1314 obs_metadata=obsDummy, 

1315 epoch=2000.0, 

1316 camera=self.camera) 

1317 self.assertEqual(context.exception.args[0], 

1318 "You need to pass an ObservationMetaData with an " 

1319 "mjd into focalPlaneCoordsFromRaDec") 

1320 

1321 with self.assertRaises(RuntimeError) as context: 

1322 xf, yf = _focalPlaneCoordsFromRaDec(raList, decList, 

1323 obs_metadata=obsDummy, 

1324 epoch=2000.0, 

1325 camera=self.camera) 

1326 

1327 self.assertEqual(context.exception.args[0], 

1328 "You need to pass an ObservationMetaData with an " 

1329 "mjd into focalPlaneCoordsFromRaDec") 

1330 

1331 # test that an error is raised if you pass an ObservationMetaData 

1332 # without a rotSkyPos into focalPlaneCoordsFromRaDec 

1333 obsDummy = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

1334 mjd=42356.0) 

1335 with self.assertRaises(RuntimeError) as context: 

1336 xf, yf = focalPlaneCoordsFromRaDec(raList, decList, 

1337 obs_metadata=obsDummy, 

1338 epoch=2000.0, 

1339 camera=self.camera) 

1340 

1341 self.assertEqual(context.exception.args[0], 

1342 "You need to pass an ObservationMetaData with a " 

1343 "rotSkyPos into focalPlaneCoordsFromRaDec") 

1344 

1345 with self.assertRaises(RuntimeError) as context: 

1346 xf, yf = _focalPlaneCoordsFromRaDec(raList, decList, 

1347 obs_metadata=obsDummy, 

1348 epoch=2000.0, 

1349 camera=self.camera) 

1350 self.assertEqual(context.exception.args[0], 

1351 "You need to pass an ObservationMetaData with a " 

1352 "rotSkyPos into focalPlaneCoordsFromRaDec") 

1353 

1354 @unittest.skip("The test camera has changed") 

1355 def testResults(self): 

1356 """ 

1357 Test that the focalPlaneCoords methods give sensible results. 

1358 

1359 Note: since we have already tested the self-consistency of 

1360 focalPlaneCoordsFromPupilCoords and focalPlaneCoordsFromRaDec, 

1361 we will only test focalPlaneCoordsFromPupilCoords here, since it 

1362 is easier. 

1363 

1364 Note that the test camera has a platescale of 0.02 arcsec per pixel 

1365 (2.0 arcsec per mm encoded in CameraForUnitTests.py and 10 microns 

1366 per pixel encoded in cameraData/focalplanelayout.txt). We will use 

1367 that to set the control values for our unit test. 

1368 

1369 Note: This unit test will fail if the test camera ever changes. 

1370 """ 

1371 

1372 arcsecPerPixel = 0.02 

1373 arcsecPerMicron = 0.002 

1374 mmPerArcsec = 0.5 

1375 

1376 # list a bunch of detector centers in radians 

1377 x22 = 0.0 

1378 y22 = 0.0 

1379 

1380 x32 = radiansFromArcsec(40000.0 * arcsecPerMicron) 

1381 y32 = 0.0 

1382 

1383 x40 = radiansFromArcsec(80000.0 * arcsecPerMicron) 

1384 y40 = radiansFromArcsec(-80000.0 * arcsecPerMicron) 

1385 

1386 # assemble a bunch of displacements in pixels 

1387 dxPixList = [] 

1388 dyPixList = [] 

1389 for xx in np.arange(-1999.0, 1999.0, 500.0): 

1390 for yy in np.arange(-1999.0, 1999.0, 500.0): 

1391 dxPixList.append(xx) 

1392 dyPixList.append(yy) 

1393 

1394 dxPixList = np.array(dxPixList) 

1395 dyPixList = np.array(dyPixList) 

1396 

1397 # convert to raidans 

1398 dxPupList = radiansFromArcsec(dxPixList*arcsecPerPixel) 

1399 dyPupList = radiansFromArcsec(dyPixList*arcsecPerPixel) 

1400 

1401 # assemble a bunch of test pupil coordinate pairs 

1402 xPupList = x22 + dxPupList 

1403 yPupList = y22 + dyPupList 

1404 xPupList = np.append(xPupList, x32 + dxPupList) 

1405 yPupList = np.append(yPupList, y32 + dyPupList) 

1406 xPupList = np.append(xPupList, x40 + dxPupList) 

1407 yPupList = np.append(yPupList, y40 + dyPupList) 

1408 

1409 # this is what the chipNames ought to be for these points 

1410 chipNameControl = np.array(['Det22'] * len(dxPupList)) 

1411 chipNameControl = np.append(chipNameControl, ['Det32'] * len(dxPupList)) 

1412 chipNameControl = np.append(chipNameControl, ['Det40'] * len(dxPupList)) 

1413 

1414 chipNameTest = chipNameFromPupilCoords(xPupList, yPupList, camera=self.camera) 

1415 

1416 # verify that the test points fall on the expected chips 

1417 np.testing.assert_array_equal(chipNameControl, chipNameTest) 

1418 

1419 # convert into millimeters on the focal plane 

1420 xFocalControl = arcsecFromRadians(xPupList)*mmPerArcsec 

1421 yFocalControl = arcsecFromRadians(yPupList)*mmPerArcsec 

1422 

1423 xFocalTest, yFocalTest = focalPlaneCoordsFromPupilCoords(xPupList, yPupList, camera=self.camera) 

1424 

1425 np.testing.assert_array_almost_equal(xFocalTest, xFocalControl, 3) 

1426 np.testing.assert_array_almost_equal(yFocalTest, yFocalControl, 3) 

1427 

1428 def test_pupilCoordsFromFocalPlaneCoords(self): 

1429 """ 

1430 Test that pupilCoordsFromFocalPlaneCoords inverts 

1431 focalPlaneCoordsFromPupilCoords 

1432 """ 

1433 rng = np.random.RandomState(88123) 

1434 n_pts = 20 

1435 x_pup = rng.random_sample(n_pts)*0.05-0.025 

1436 y_pup = rng.random_sample(n_pts)*0.05-0.025 

1437 

1438 x_f, y_f = focalPlaneCoordsFromPupilCoords(x_pup, y_pup, 

1439 camera=lsst_camera()) 

1440 

1441 x_p_test, y_p_test = pupilCoordsFromFocalPlaneCoords(x_f, y_f, 

1442 camera=lsst_camera()) 

1443 

1444 np.testing.assert_array_almost_equal(arcsecFromRadians(x_pup), 

1445 arcsecFromRadians(x_p_test), 

1446 decimal=6) 

1447 

1448 np.testing.assert_array_almost_equal(arcsecFromRadians(y_pup), 

1449 arcsecFromRadians(y_p_test), 

1450 decimal=6) 

1451 

1452 # test that it works on scalars, too 

1453 for ii in range(len(x_pup)): 

1454 (x_p_test, 

1455 y_p_test) = pupilCoordsFromFocalPlaneCoords(x_f[ii], y_f[ii], 

1456 camera=lsst_camera()) 

1457 

1458 self.assertAlmostEqual(arcsecFromRadians(x_pup[ii]), 

1459 arcsecFromRadians(x_p_test), 

1460 6) 

1461 

1462 self.assertAlmostEqual(arcsecFromRadians(y_pup[ii]), 

1463 arcsecFromRadians(y_p_test), 

1464 6) 

1465 

1466 del lsst_camera._lsst_camera 

1467 

1468 def test_pupilCoordsFromFocalPlaneCoordsNaNs(self): 

1469 """ 

1470 Test that pupilCoordsFromFocalPlaneCoords handles NaNs correctly 

1471 """ 

1472 xp, yp = pupilCoordsFromFocalPlaneCoords(1.0, 2.0, camera=lsst_camera()) 

1473 self.assertFalse(np.isnan(xp)) 

1474 self.assertFalse(np.isnan(yp)) 

1475 xp, yp = pupilCoordsFromFocalPlaneCoords(np.NaN, 2.0, camera=lsst_camera()) 

1476 self.assertTrue(np.isnan(xp)) 

1477 self.assertTrue(np.isnan(yp)) 

1478 xp, yp = pupilCoordsFromFocalPlaneCoords(1.0, np.NaN, camera=lsst_camera()) 

1479 self.assertTrue(np.isnan(xp)) 

1480 self.assertTrue(np.isnan(yp)) 

1481 

1482 x = np.array([1,2,3,4]) 

1483 y = np.array([5,6,7,8]) 

1484 xp, yp = pupilCoordsFromFocalPlaneCoords(x, y, camera=lsst_camera()) 

1485 for xx, yy in zip(xp, yp): 

1486 self.assertFalse(np.isnan(xx)) 

1487 self.assertFalse(np.isnan(yy)) 

1488 

1489 x = np.array([np.NaN,2,3,4]) 

1490 y = np.array([5,np.NaN,7,8]) 

1491 xp, yp = pupilCoordsFromFocalPlaneCoords(x, y, camera=lsst_camera()) 

1492 self.assertTrue(np.isnan(xp[0])) 

1493 self.assertTrue(np.isnan(yp[0])) 

1494 self.assertTrue(np.isnan(xp[1])) 

1495 self.assertTrue(np.isnan(yp[1])) 

1496 for ii in range(2,4): 

1497 self.assertFalse(np.isnan(xp[ii])) 

1498 self.assertFalse(np.isnan(yp[ii])) 

1499 

1500 del lsst_camera._lsst_camera 

1501 

1502 

1503class ConversionFromPixelTest(unittest.TestCase): 

1504 

1505 @classmethod 

1506 def setUpClass(cls): 

1507 cls.camera = LsstSimMapper().camera 

1508 

1509 @classmethod 

1510 def tearDownClass(cls): 

1511 del cls.camera 

1512 

1513 def setUp(self): 

1514 self.rng = np.random.RandomState(543) 

1515 

1516 def testPupCoordsException(self): 

1517 """ 

1518 Test that pupilCoordsFromPixelCoords raises an exception when you 

1519 call it without a camera 

1520 """ 

1521 nStars = 100 

1522 xPupList = radiansFromArcsec((self.rng.random_sample(nStars)-0.5)*320.0) 

1523 yPupList = radiansFromArcsec((self.rng.random_sample(nStars)-0.5)*320.0) 

1524 chipNameList = chipNameFromPupilCoords(xPupList, yPupList, camera=self.camera) 

1525 xPix, yPix = pixelCoordsFromPupilCoords(xPupList, yPupList, camera=self.camera) 

1526 with self.assertRaises(RuntimeError) as context: 

1527 xPupTest, yPupTest = pupilCoordsFromPixelCoords(xPix, yPix, chipNameList) 

1528 self.assertEqual(context.exception.args[0], 

1529 "You cannot call pupilCoordsFromPixelCoords without specifying " 

1530 "a camera") 

1531 

1532 def testPupCoordsResults(self): 

1533 """ 

1534 Test that the results from pupilCoordsFromPixelCoords are consistent 

1535 with the results from pixelCoordsFromPupilCoords 

1536 """ 

1537 

1538 nStars = 100 

1539 xPupList = radiansFromArcsec((self.rng.random_sample(nStars)-0.5)*320.0) 

1540 yPupList = radiansFromArcsec((self.rng.random_sample(nStars)-0.5)*320.0) 

1541 chipNameList = chipNameFromPupilCoords(xPupList, yPupList, camera=self.camera) 

1542 for includeDistortion in [True, False]: 

1543 xPix, yPix = pixelCoordsFromPupilCoords(xPupList, yPupList, camera=self.camera, 

1544 includeDistortion=includeDistortion) 

1545 xPupTest, yPupTest = pupilCoordsFromPixelCoords(xPix, yPix, chipNameList, camera=self.camera, 

1546 includeDistortion=includeDistortion) 

1547 

1548 dx = arcsecFromRadians(xPupTest-xPupList) 

1549 np.testing.assert_array_almost_equal(dx, np.zeros(len(dx)), 9) 

1550 dy = arcsecFromRadians(yPupTest-yPupList) 

1551 np.testing.assert_array_almost_equal(dy, np.zeros(len(dy)), 9) 

1552 

1553 ctNaN = 0 

1554 for x, y in zip(xPupTest, yPupTest): 

1555 if np.isnan(x) or np.isnan(y): 

1556 ctNaN += 1 

1557 self.assertLess(ctNaN, len(xPupTest)/10) 

1558 

1559 # test passing in pixel coordinates one at a time 

1560 for ix in range(len(xPupList)): 

1561 xp_f, yp_f = pupilCoordsFromPixelCoords(xPix[ix], yPix[ix], chipNameList[ix], 

1562 camera=self.camera, 

1563 includeDistortion=includeDistortion) 

1564 

1565 self.assertIsInstance(xp_f, np.float) 

1566 self.assertIsInstance(yp_f, np.float) 

1567 self.assertAlmostEqual(xp_f, xPupTest[ix], 12) 

1568 self.assertAlmostEqual(yp_f, yPupTest[ix], 12) 

1569 

1570 def testPupCoordsNaN(self): 

1571 """ 

1572 Test that points which do not have a chip return NaN for pupilCoordsFromPixelCoords 

1573 """ 

1574 nStars = 10 

1575 xPupList = radiansFromArcsec((self.rng.random_sample(nStars)-0.5)*320.0) 

1576 yPupList = radiansFromArcsec((self.rng.random_sample(nStars)-0.5)*320.0) 

1577 chipNameList = chipNameFromPupilCoords(xPupList, yPupList, camera=self.camera) 

1578 chipNameList[5] = None 

1579 xPix, yPix = pixelCoordsFromPupilCoords(xPupList, yPupList, camera=self.camera) 

1580 xPupTest, yPupTest = pupilCoordsFromPixelCoords(xPix, yPix, chipNameList, camera=self.camera) 

1581 np.testing.assert_equal(xPupTest[5], np.NaN) 

1582 np.testing.assert_equal(yPupTest[5], np.NaN) 

1583 

1584 def testRaDecExceptions(self): 

1585 """ 

1586 Test that raDecFromPupilCoords raises exceptions when it is supposed to 

1587 """ 

1588 nStars = 20 

1589 ra0 = 45.0 

1590 dec0 = -19.0 

1591 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

1592 mjd=43525.0, rotSkyPos=145.0) 

1593 

1594 xPixList = self.rng.random_sample(nStars)*4000.0 

1595 yPixList = self.rng.random_sample(nStars)*4000.0 

1596 

1597 chipDexList = self.rng.randint(0, len(self.camera), nStars) 

1598 camera_detector_keys = list([det.getName() for det in self.camera]) 

1599 self.assertGreater(len(camera_detector_keys), 0) 

1600 chipNameList = [self.camera[camera_detector_keys[ii]].getName() for ii in chipDexList] 

1601 

1602 # test that an error is raised if you do not pass in a camera 

1603 with self.assertRaises(RuntimeError) as context: 

1604 ra, dec = raDecFromPixelCoords(xPixList, yPixList, chipNameList, 

1605 obs_metadata=obs, epoch=2000.0) 

1606 self.assertEqual(context.exception.args[0], 

1607 "You cannot call raDecFromPixelCoords without specifying a camera") 

1608 

1609 with self.assertRaises(RuntimeError) as context: 

1610 ra, dec = _raDecFromPixelCoords(xPixList, yPixList, chipNameList, 

1611 obs_metadata=obs, epoch=2000.0) 

1612 self.assertEqual(context.exception.args[0], 

1613 "You cannot call raDecFromPixelCoords without specifying a camera") 

1614 

1615 # test that an error is raised if you do not pass in an ObservationMetaData 

1616 with self.assertRaises(RuntimeError) as context: 

1617 ra, dec = raDecFromPixelCoords(xPixList, yPixList, chipNameList, 

1618 epoch=2000.0, camera=self.camera) 

1619 self.assertEqual(context.exception.args[0], 

1620 "You cannot call raDecFromPixelCoords without an ObservationMetaData") 

1621 

1622 # test that an error is raised if you do not pass in an ObservationMetaData 

1623 with self.assertRaises(RuntimeError) as context: 

1624 ra, dec = _raDecFromPixelCoords(xPixList, yPixList, chipNameList, 

1625 epoch=2000.0, camera=self.camera) 

1626 self.assertEqual(context.exception.args[0], 

1627 "You cannot call raDecFromPixelCoords without an ObservationMetaData") 

1628 

1629 # test that an error is raised if you pass in an ObservationMetaData 

1630 # without an mjd 

1631 obsDummy = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, rotSkyPos=95.0) 

1632 with self.assertRaises(RuntimeError) as context: 

1633 ra, dec = raDecFromPixelCoords(xPixList, yPixList, chipNameList, 

1634 obs_metadata=obsDummy, 

1635 epoch=2000.0, camera=self.camera) 

1636 self.assertEqual(context.exception.args[0], 

1637 "The ObservationMetaData in raDecFromPixelCoords must have an mjd") 

1638 

1639 with self.assertRaises(RuntimeError) as context: 

1640 ra, dec = _raDecFromPixelCoords(xPixList, yPixList, chipNameList, 

1641 obs_metadata=obsDummy, 

1642 epoch=2000.0, camera=self.camera) 

1643 self.assertEqual(context.exception.args[0], 

1644 "The ObservationMetaData in raDecFromPixelCoords must have an mjd") 

1645 

1646 # test that an error is raised if you pass in an ObservationMetaData 

1647 # without a rotSkyPos 

1648 obsDummy = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, mjd=43243.0) 

1649 with self.assertRaises(RuntimeError) as context: 

1650 ra, dec = raDecFromPixelCoords(xPixList, yPixList, chipNameList, 

1651 obs_metadata=obsDummy, 

1652 epoch=2000.0, camera=self.camera) 

1653 self.assertEqual(context.exception.args[0], 

1654 "The ObservationMetaData in raDecFromPixelCoords must have a rotSkyPos") 

1655 

1656 with self.assertRaises(RuntimeError) as context: 

1657 ra, dec = _raDecFromPixelCoords(xPixList, yPixList, chipNameList, 

1658 obs_metadata=obsDummy, 

1659 epoch=2000.0, camera=self.camera) 

1660 self.assertEqual(context.exception.args[0], 

1661 "The ObservationMetaData in raDecFromPixelCoords must have a rotSkyPos") 

1662 

1663 # test that an error is raised if you pass in lists of pixel coordinates, 

1664 # rather than numpy arrays 

1665 with self.assertRaises(RuntimeError) as context: 

1666 ra, dec = raDecFromPixelCoords(list(xPixList), yPixList, 

1667 chipNameList, obs_metadata=obs, 

1668 epoch=2000.0, camera=self.camera) 

1669 self.assertIn("The arg xPix", context.exception.args[0]) 

1670 

1671 with self.assertRaises(RuntimeError) as context: 

1672 ra, dec = raDecFromPixelCoords(xPixList, list(yPixList), 

1673 chipNameList, obs_metadata=obs, 

1674 epoch=2000.0, camera=self.camera) 

1675 self.assertIn("The input arguments:", context.exception.args[0]) 

1676 self.assertIn("yPix", context.exception.args[0]) 

1677 

1678 with self.assertRaises(RuntimeError) as context: 

1679 ra, dec = _raDecFromPixelCoords(list(xPixList), yPixList, 

1680 chipNameList, obs_metadata=obs, 

1681 epoch=2000.0, camera=self.camera) 

1682 self.assertIn("The arg xPix", context.exception.args[0]) 

1683 

1684 with self.assertRaises(RuntimeError) as context: 

1685 ra, dec = _raDecFromPixelCoords(xPixList, list(yPixList), 

1686 chipNameList, obs_metadata=obs, 

1687 epoch=2000.0, camera=self.camera) 

1688 self.assertIn("The input arguments:", context.exception.args[0]) 

1689 self.assertIn("yPix", context.exception.args[0]) 

1690 

1691 # test that an error is raised if you pass in mismatched lists of 

1692 # xPix and yPix 

1693 with self.assertRaises(RuntimeError) as context: 

1694 ra, dec = raDecFromPixelCoords(xPixList, yPixList[0:13], chipNameList, 

1695 obs_metadata=obs, epoch=2000.0, camera=self.camera) 

1696 self.assertEqual(context.exception.args[0], 

1697 "The arrays input to raDecFromPixelCoords all need to have the same length") 

1698 

1699 with self.assertRaises(RuntimeError) as context: 

1700 ra, dec = _raDecFromPixelCoords(xPixList, yPixList[0:13], chipNameList, 

1701 obs_metadata=obs, epoch=2000.0, camera=self.camera) 

1702 self.assertEqual(context.exception.args[0], 

1703 "The arrays input to raDecFromPixelCoords all need to have the same length") 

1704 

1705 # test that an error is raised if you do not pass in the same number of chipNames 

1706 # as pixel coordinates 

1707 with self.assertRaises(RuntimeError) as context: 

1708 ra, dec = raDecFromPixelCoords(xPixList, yPixList, ['R:2,2 S:1,1']*22, 

1709 obs_metadata=obs, epoch=2000.0, camera=self.camera) 

1710 self.assertIn("22 chipNames", context.exception.args[0]) 

1711 

1712 with self.assertRaises(RuntimeError) as context: 

1713 ra, dec = _raDecFromPixelCoords(xPixList, yPixList, ['R:2,2 S:1,1']*22, 

1714 obs_metadata=obs, epoch=2000.0, camera=self.camera) 

1715 self.assertIn("22 chipNames", context.exception.args[0]) 

1716 

1717 def testResults(self): 

1718 """ 

1719 Test that raDecFromPixelCoords results are consistent with 

1720 pixelCoordsFromRaDec 

1721 """ 

1722 nStars = 200 

1723 ra0 = 45.0 

1724 dec0 = -19.0 

1725 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

1726 mjd=43525.0, rotSkyPos=145.0) 

1727 

1728 xPixList = self.rng.random_sample(nStars)*3000.0 + 100 

1729 yPixList = self.rng.random_sample(nStars)*3000.0 + 100 

1730 

1731 #chipDexList = self.rng.randint(0, len(self.camera), nStars) 

1732 chipDexList = self.rng.randint(0, 1, nStars) 

1733 camera_detector_keys = list([det.getName() for det in self.camera]) 

1734 self.assertGreater(len(camera_detector_keys), 0) 

1735 chipNameList = [self.camera[camera_detector_keys[ii]].getName() for ii in chipDexList] 

1736 

1737 for includeDistortion in [True, False]: 

1738 

1739 raDeg, decDeg = raDecFromPixelCoords(xPixList, yPixList, chipNameList, obs_metadata=obs, 

1740 epoch=2000.0, camera=self.camera, 

1741 includeDistortion=includeDistortion) 

1742 

1743 raRad, decRad = _raDecFromPixelCoords(xPixList, yPixList, chipNameList, obs_metadata=obs, 

1744 epoch=2000.0, camera=self.camera, 

1745 includeDistortion=includeDistortion) 

1746 

1747 # first, make sure that the radians and degrees methods agree with each other 

1748 dRa = arcsecFromRadians(raRad-np.radians(raDeg)) 

1749 np.testing.assert_array_almost_equal(dRa, np.zeros(len(raRad)), 9) 

1750 dDec = arcsecFromRadians(decRad-np.radians(decDeg)) 

1751 np.testing.assert_array_almost_equal(dDec, np.zeros(len(decRad)), 9) 

1752 

1753 # now make sure that the results from raDecFromPixelCoords are consistent 

1754 # with the results from pixelCoordsFromRaDec by taking the ra and dec 

1755 # arrays found above and feeding them back into pixelCoordsFromRaDec 

1756 # and seeing if we get the same results 

1757 xPixTest, yPixTest = pixelCoordsFromRaDec(raDeg, decDeg, obs_metadata=obs, 

1758 epoch=2000.0, camera=self.camera, 

1759 includeDistortion=includeDistortion) 

1760 

1761 distance = np.sqrt(np.power(xPixTest-xPixList, 2) + np.power(yPixTest-yPixList, 2)) 

1762 idx = np.where(np.isnan(distance)) 

1763 self.assertLess(distance.max(), 0.2) # because of the imprecision in _icrsFromObserved, 

1764 # this is the best we can get; note that, in our test 

1765 # camera, each pixel is 10 microns in size and the 

1766 # plate scale is 2 arcsec per mm, so 0.2 pixels is 

1767 # 0.004 arcsec 

1768 

1769 # test passing the pixel coordinates in one at a time 

1770 for ix in range(len(xPixList)): 

1771 ra_f, dec_f = raDecFromPixelCoords(xPixList[ix], yPixList[ix], 

1772 chipNameList[ix], obs_metadata=obs, 

1773 epoch=2000.0, camera=self.camera, 

1774 includeDistortion=includeDistortion) 

1775 self.assertIsInstance(ra_f, np.float) 

1776 self.assertIsInstance(dec_f, np.float) 

1777 self.assertAlmostEqual(ra_f, raDeg[ix], 12) 

1778 self.assertAlmostEqual(dec_f, decDeg[ix], 12) 

1779 

1780 def testResultsOffChip(self): 

1781 """ 

1782 Test that raDecFromPixelCoords results are consistent with 

1783 pixelCoordsFromRaDec with chip names are specified 

1784 

1785 Note: this is the same test as in testResults, except that 

1786 we are going to intentionally make the pixel coordinate lists 

1787 fall outside the boundaries of the chips defined in chipNameList 

1788 """ 

1789 nStars = 200 

1790 ra0 = 45.0 

1791 dec0 = -19.0 

1792 obs = ObservationMetaData(pointingRA=ra0, pointingDec=dec0, 

1793 mjd=43525.0, rotSkyPos=145.0) 

1794 

1795 xPixList = self.rng.random_sample(nStars)*4000.0 + 4000.0 

1796 yPixList = self.rng.random_sample(nStars)*4000.0 + 4000.0 

1797 

1798 chipDexList = self.rng.randint(0, len(self.camera), nStars) 

1799 camera_detector_keys = list([det.getName() for det in self.camera]) 

1800 self.assertGreater(len(camera_detector_keys), 0) 

1801 chipNameList = [self.camera[camera_detector_keys[ii]].getName() for ii in chipDexList] 

1802 

1803 for includeDistortion in [True, False]: 

1804 

1805 raDeg, decDeg = raDecFromPixelCoords(xPixList, yPixList, chipNameList, obs_metadata=obs, 

1806 epoch=2000.0, camera=self.camera, 

1807 includeDistortion=includeDistortion) 

1808 

1809 raRad, decRad = _raDecFromPixelCoords(xPixList, yPixList, chipNameList, obs_metadata=obs, 

1810 epoch=2000.0, camera=self.camera, 

1811 includeDistortion=includeDistortion) 

1812 

1813 # first, make sure that the radians and degrees methods agree with each other 

1814 dRa = arcsecFromRadians(raRad-np.radians(raDeg)) 

1815 np.testing.assert_array_almost_equal(dRa, np.zeros(len(raRad)), 9) 

1816 dDec = arcsecFromRadians(decRad-np.radians(decDeg)) 

1817 np.testing.assert_array_almost_equal(dDec, np.zeros(len(decRad)), 9) 

1818 

1819 # now make sure that the results from raDecFromPixelCoords are consistent 

1820 # with the results from pixelCoordsFromRaDec by taking the ra and dec 

1821 # arrays found above and feeding them back into pixelCoordsFromRaDec 

1822 # and seeing if we get the same results 

1823 xPixTest, yPixTest = pixelCoordsFromRaDec(raDeg, decDeg, chipName=chipNameList, 

1824 obs_metadata=obs, 

1825 epoch=2000.0, 

1826 camera=self.camera, 

1827 includeDistortion=includeDistortion) 

1828 

1829 distance = np.sqrt(np.power(xPixTest-xPixList, 2) + np.power(yPixTest-yPixList, 2)) 

1830 self.assertLess(distance.max(), 0.2) # because of the imprecision in _icrsFromObserved, 

1831 # this is the best we can get; note that, in our 

1832 # test camera, each pixel is 10 microns in size and 

1833 # the plate scale is 2 arcsec per mm, so 0.2 pixels is 

1834 # 0.004 arcsec 

1835 

1836 def testDistortion(self): 

1837 """ 

1838 Make sure that the results from pupilCoordsFromPixelCoords are different 

1839 if includeDistortion is True as compared to if includeDistortion is False 

1840 

1841 Note: This test passes because the test camera has a pincushion distortion. 

1842 If we take that away, the test will no longer pass. 

1843 """ 

1844 nStars = 200 

1845 xPixList = self.rng.random_sample(nStars)*4000.0 + 4000.0 

1846 yPixList = self.rng.random_sample(nStars)*4000.0 + 4000.0 

1847 

1848 chipDexList = self.rng.randint(0, len(self.camera), nStars) 

1849 camera_detector_keys = list([det.getName() for det in self.camera]) 

1850 self.assertGreater(len(camera_detector_keys), 0) 

1851 chipNameList = [self.camera[camera_detector_keys[ii]].getName() for ii in chipDexList] 

1852 

1853 xu, yu = pupilCoordsFromPixelCoords(xPixList, yPixList, chipNameList, camera=self.camera, 

1854 includeDistortion=False) 

1855 

1856 xd, yd = pupilCoordsFromPixelCoords(xPixList, yPixList, chipNameList, camera=self.camera, 

1857 includeDistortion=True) 

1858 

1859 # just verify that the distorted versus undistorted coordinates vary in the 4th decimal 

1860 self.assertRaises(AssertionError, 

1861 np.testing.assert_array_almost_equal, 

1862 arcsecFromRadians(xu), 

1863 arcsecFromRadians(xd), 

1864 4) 

1865 

1866 self.assertRaises(AssertionError, 

1867 np.testing.assert_array_almost_equal, 

1868 arcsecFromRadians(yu), 

1869 arcsecFromRadians(yd), 

1870 4) 

1871 

1872 

1873class CornerTest(unittest.TestCase): 

1874 

1875 @classmethod 

1876 def setUpClass(cls): 

1877 cls.camera = LsstSimMapper().camera 

1878 

1879 @classmethod 

1880 def tearDownClass(cls): 

1881 del cls.camera 

1882 

1883 def testCornerPixels(self): 

1884 """ 

1885 Test the method to get the pixel coordinates of the corner 

1886 of a detector 

1887 """ 

1888 det_name = self.camera[12].getName() 

1889 corners = getCornerPixels(det_name, self.camera) 

1890 # [(0, 0), (0, 3999), (4071, 0), (4071, 3999)] 

1891 self.assertEqual(corners[0][0], 0) 

1892 self.assertEqual(corners[0][1], 0) 

1893 self.assertEqual(corners[1][0], 0) 

1894 self.assertEqual(corners[1][1], 3999) 

1895 self.assertEqual(corners[2][0], 4071) 

1896 self.assertEqual(corners[2][1], 0) 

1897 self.assertEqual(corners[3][0], 4071) 

1898 self.assertEqual(corners[3][1], 3999) 

1899 self.assertEqual(len(corners), 4) 

1900 for row in corners: 

1901 self.assertEqual(len(row), 2) 

1902 

1903 def testCornerRaDec_radians(self): 

1904 """ 

1905 Test that the method to return the Ra, Dec values of the corner 

1906 of a chip (in radians) works by validating its results against 

1907 known pixel corner values and the _raDecFromPixelCoords method, 

1908 which is tested separately. 

1909 """ 

1910 obs = ObservationMetaData(pointingRA=23.0, pointingDec=-65.0, 

1911 rotSkyPos=52.1, mjd=59582.3) 

1912 

1913 det_name = self.camera[12].getName() 

1914 cornerTest = _getCornerRaDec(det_name, self.camera, obs) 

1915 

1916 ra_control, dec_control = _raDecFromPixelCoords(np.array([0, 0, 4071, 4071]), 

1917 np.array([0, 3999, 0, 3999]), 

1918 [det_name]*4, 

1919 camera=self.camera, 

1920 obs_metadata=obs, 

1921 epoch=2000.0, includeDistortion=True) 

1922 

1923 # Loop over the control values and the corner values, using 

1924 # haversine() method to find the angular distance between the 

1925 # test and control values. Assert that they are within 

1926 # 0.01 milli-arcsecond of each other 

1927 for rr1, dd1, cc in zip(ra_control, dec_control, cornerTest): 

1928 dd = haversine(rr1, dd1, cc[0], cc[1]) 

1929 self.assertLess(arcsecFromRadians(dd), 0.00001) 

1930 

1931 def testCornerRaDec_degrees(self): 

1932 """ 

1933 Test that method to get corner RA, Dec in degrees is consistent 

1934 with method to get corner RA, Dec in radians 

1935 """ 

1936 

1937 obs = ObservationMetaData(pointingRA=31.0, pointingDec=-45.0, 

1938 rotSkyPos=46.2, mjd=59583.4) 

1939 

1940 det_name = self.camera[1101].getName() 

1941 

1942 cornerRad = _getCornerRaDec(det_name, self.camera, obs) 

1943 cornerDeg = getCornerRaDec(det_name, self.camera, obs) 

1944 for cc1, cc2 in zip(cornerRad, cornerDeg): 

1945 dd = haversine(cc1[0], cc1[1], np.radians(cc2[0]), np.radians(cc2[1])) 

1946 self.assertLess(arcsecFromRadians(dd), 0.000001) 

1947 

1948 

1949class MotionTestCase(unittest.TestCase): 

1950 """ 

1951 This class will contain test methods to verify that the camera utils 

1952 work when proper motion, parallax, and radial velocity are not None. 

1953 """ 

1954 

1955 @classmethod 

1956 def setUpClass(cls): 

1957 cls.camera = LsstSimMapper().camera 

1958 

1959 @classmethod 

1960 def tearDownClass(cls): 

1961 del cls.camera 

1962 

1963 def set_data(self, seed): 

1964 """ 

1965 Accept a seed integer. Return an ObservationMetaData 

1966 and numpy arrays of RA, Dec (in degrees), 

1967 pm_ra, pm_dec, parallax (in arcsec) and v_rad (in km/s) 

1968 centered on that bore site. 

1969 """ 

1970 rng = np.random.RandomState(seed) 

1971 n_obj = 100 

1972 ra = 23.1 

1973 dec = -15.6 

1974 rotSkyPos = 23.56 

1975 mjd = 59723.2 

1976 obs = ObservationMetaData(pointingRA=ra, pointingDec=dec, 

1977 rotSkyPos=rotSkyPos, mjd=mjd) 

1978 # Distribute objects out to rr degrees from ra/dec 

1979 rr = rng.random_sample(n_obj)*2 

1980 theta = rng.random_sample(n_obj)*2.0*np.pi 

1981 ra_list = ra + rr*np.cos(theta) 

1982 dec_list = dec + rr*np.sin(theta) 

1983 pm_ra = rng.random_sample(n_obj)*20.0 - 10.0 

1984 pm_dec = rng.random_sample(n_obj)*20.0 - 10.0 

1985 parallax = rng.random_sample(n_obj)*1.0 - 0.5 

1986 v_rad = rng.random_sample(n_obj)*600.0 - 300.0 

1987 return obs, ra_list, dec_list, pm_ra, pm_dec, parallax, v_rad 

1988 

1989 def test_chip_name(self): 

1990 """ 

1991 Test that chipNameFromRaDec with non-zero proper motion etc. 

1992 agrees with chipNameFromPupilCoords when pupilCoords are 

1993 calculated with the same proper motion, etc. 

1994 """ 

1995 (obs, ra_list, dec_list, 

1996 pm_ra_list, pm_dec_list, 

1997 parallax_list, v_rad_list) = self.set_data(8231) 

1998 

1999 for is_none in ('pm_ra', 'pm_dec', 'parallax', 'v_rad'): 

2000 pm_ra = pm_ra_list 

2001 pm_dec = pm_dec_list 

2002 parallax = parallax_list 

2003 v_rad = v_rad_list 

2004 

2005 if is_none == 'pm_ra': 

2006 pm_ra = None 

2007 elif is_none == 'pm_dec': 

2008 pm_dec = None 

2009 elif is_none == 'parallax': 

2010 parallax = None 

2011 elif is_none == 'v_rad': 

2012 v_rad = None 

2013 

2014 xp, yp = pupilCoordsFromRaDec(ra_list, dec_list, 

2015 pm_ra=pm_ra, pm_dec=pm_dec, 

2016 parallax=parallax, v_rad=v_rad, 

2017 obs_metadata=obs) 

2018 

2019 name_control = chipNameFromPupilCoords(xp, yp, camera=self.camera) 

2020 

2021 name_test = chipNameFromRaDec(ra_list, dec_list, 

2022 pm_ra=pm_ra, pm_dec=pm_dec, 

2023 parallax=parallax, v_rad=v_rad, 

2024 obs_metadata=obs, camera=self.camera) 

2025 

2026 name_radians = _chipNameFromRaDec(np.radians(ra_list), np.radians(dec_list), 

2027 pm_ra=radiansFromArcsec(pm_ra), 

2028 pm_dec=radiansFromArcsec(pm_dec), 

2029 parallax=radiansFromArcsec(parallax), v_rad=v_rad, 

2030 obs_metadata=obs, camera=self.camera) 

2031 

2032 np.testing.assert_array_equal(name_control, name_test) 

2033 np.testing.assert_array_equal(name_control, name_radians) 

2034 self.assertGreater(len(np.unique(name_control.astype(str))), 4) 

2035 self.assertLess(len(np.where(np.equal(name_control, None))[0]), 2*len(name_control)/3) 

2036 

2037 def test_pixel_coords(self): 

2038 """ 

2039 Test that pixelCoordsFromRaDec with non-zero proper motion etc. 

2040 agrees with pixelCoordsFromPupilCoords when pupilCoords are 

2041 calculated with the same proper motion, etc. 

2042 """ 

2043 (obs, ra_list, dec_list, 

2044 pm_ra_list, pm_dec_list, 

2045 parallax_list, v_rad_list) = self.set_data(72) 

2046 

2047 for is_none in ('pm_ra', 'pm_dec', 'parallax', 'v_rad'): 

2048 pm_ra = pm_ra_list 

2049 pm_dec = pm_dec_list 

2050 parallax = parallax_list 

2051 v_rad = v_rad_list 

2052 

2053 if is_none == 'pm_ra': 

2054 pm_ra = None 

2055 elif is_none == 'pm_dec': 

2056 pm_dec = None 

2057 elif is_none == 'parallax': 

2058 parallax = None 

2059 elif is_none == 'v_rad': 

2060 v_rad = None 

2061 

2062 xp, yp = pupilCoordsFromRaDec(ra_list, dec_list, 

2063 pm_ra=pm_ra, pm_dec=pm_dec, 

2064 parallax=parallax, v_rad=v_rad, 

2065 obs_metadata=obs) 

2066 

2067 xpx_control, ypx_control = pixelCoordsFromPupilCoords(xp, yp, camera=self.camera) 

2068 

2069 xpx_test, ypx_test = pixelCoordsFromRaDec(ra_list, dec_list, 

2070 pm_ra=pm_ra, pm_dec=pm_dec, 

2071 parallax=parallax, v_rad=v_rad, 

2072 obs_metadata=obs, camera=self.camera) 

2073 

2074 xpx_radians, ypx_radians = _pixelCoordsFromRaDec(np.radians(ra_list), np.radians(dec_list), 

2075 pm_ra=radiansFromArcsec(pm_ra), 

2076 pm_dec=radiansFromArcsec(pm_dec), 

2077 parallax=radiansFromArcsec(parallax), 

2078 v_rad=v_rad, 

2079 obs_metadata=obs, camera=self.camera) 

2080 

2081 np.testing.assert_array_equal(xpx_control, xpx_test) 

2082 np.testing.assert_array_equal(ypx_control, ypx_test) 

2083 np.testing.assert_array_equal(xpx_control, xpx_radians) 

2084 np.testing.assert_array_equal(ypx_control, ypx_radians) 

2085 self.assertLess(len(np.where(np.isnan(xpx_control))[0]), 2*len(xpx_control)/3) 

2086 

2087 def test_focal_plane_coords(self): 

2088 """ 

2089 Test that focalPlaneCoordsFromRaDec with non-zero proper motion etc. 

2090 agrees with focalPlaneCoordsFromPupilCoords when pupilCoords are 

2091 calculated with the same proper motion, etc. 

2092 """ 

2093 (obs, ra_list, dec_list, 

2094 pm_ra_list, pm_dec_list, 

2095 parallax_list, v_rad_list) = self.set_data(72) 

2096 

2097 for is_none in ('pm_ra', 'pm_dec', 'parallax', 'v_rad'): 

2098 pm_ra = pm_ra_list 

2099 pm_dec = pm_dec_list 

2100 parallax = parallax_list 

2101 v_rad = v_rad_list 

2102 

2103 if is_none == 'pm_ra': 

2104 pm_ra = None 

2105 elif is_none == 'pm_dec': 

2106 pm_dec = None 

2107 elif is_none == 'parallax': 

2108 parallax = None 

2109 elif is_none == 'v_rad': 

2110 v_rad = None 

2111 

2112 xp, yp = pupilCoordsFromRaDec(ra_list, dec_list, 

2113 pm_ra=pm_ra, pm_dec=pm_dec, 

2114 parallax=parallax, v_rad=v_rad, 

2115 obs_metadata=obs) 

2116 

2117 xf_control, yf_control = focalPlaneCoordsFromPupilCoords(xp, yp, camera=self.camera) 

2118 

2119 xf_test, yf_test = focalPlaneCoordsFromRaDec(ra_list, dec_list, 

2120 pm_ra=pm_ra, pm_dec=pm_dec, 

2121 parallax=parallax, v_rad=v_rad, 

2122 obs_metadata=obs, camera=self.camera) 

2123 

2124 xf_radians, yf_radians = _focalPlaneCoordsFromRaDec(np.radians(ra_list), np.radians(dec_list), 

2125 pm_ra=radiansFromArcsec(pm_ra), 

2126 pm_dec=radiansFromArcsec(pm_dec), 

2127 parallax=radiansFromArcsec(parallax), 

2128 v_rad=v_rad, obs_metadata=obs, 

2129 camera=self.camera) 

2130 

2131 np.testing.assert_array_equal(xf_control, xf_test) 

2132 np.testing.assert_array_equal(yf_control, yf_test) 

2133 np.testing.assert_array_equal(xf_control, xf_radians) 

2134 np.testing.assert_array_equal(yf_control, yf_radians) 

2135 self.assertEqual(len(np.where(np.isnan(xf_control))[0]), 0) 

2136 self.assertEqual(len(np.where(np.isnan(yf_control))[0]), 0) 

2137 

2138 

2139class MemoryTestClass(lsst.utils.tests.MemoryTestCase): 

2140 pass 

2141 

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

2143 lsst.utils.tests.init() 

2144 unittest.main()