Coverage for tests/testLsstOpticalDistortions.py : 7%

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
1import unittest
2import os
3import numpy as np
4import numbers
5import lsst.utils.tests
7from lsst.utils import getPackageDir
8from lsst.afw.cameraGeom import PIXELS, FOCAL_PLANE
9from lsst.afw.cameraGeom import DetectorType
10import lsst.geom as geom
11from lsst.sims.coordUtils import lsst_camera
12from lsst.sims.coordUtils import focalPlaneCoordsFromPupilCoordsLSST
13from lsst.sims.coordUtils import focalPlaneCoordsFromPupilCoords
14from lsst.sims.coordUtils import pupilCoordsFromFocalPlaneCoordsLSST
15from lsst.sims.coordUtils import DMtoCameraPixelTransformer
16from lsst.sims.utils import ObservationMetaData
17from lsst.sims.utils import pupilCoordsFromRaDec
18from lsst.sims.utils import radiansFromArcsec
19from lsst.sims.utils import angularSeparation
20from lsst.sims.coordUtils import chipNameFromPupilCoordsLSST
21from lsst.sims.coordUtils import chipNameFromRaDecLSST
22from lsst.sims.coordUtils import _chipNameFromRaDecLSST
23from lsst.sims.coordUtils import pixelCoordsFromRaDecLSST
24from lsst.sims.coordUtils import _pixelCoordsFromRaDecLSST
25from lsst.sims.coordUtils import pixelCoordsFromRaDec
26from lsst.sims.coordUtils import pixelCoordsFromPupilCoordsLSST
27from lsst.sims.coordUtils import pupilCoordsFromPixelCoordsLSST
28from lsst.sims.coordUtils import raDecFromPixelCoordsLSST
29from lsst.sims.coordUtils import _raDecFromPixelCoordsLSST
30from lsst.sims.coordUtils.LsstZernikeFitter import _rawPupilCoordsFromObserved
32from lsst.sims.coordUtils import clean_up_lsst_camera
34def setup_module(module):
35 lsst.utils.tests.init()
38class FocalPlaneTestCase(unittest.TestCase):
40 @classmethod
41 def setUpClass(cls):
42 pix_transformer = DMtoCameraPixelTransformer()
43 data_dir = os.path.join(getPackageDir('sims_data'),
44 'FocalPlaneData',
45 'UnitTestData')
47 cls._data_dir = data_dir
49 phosim_dtype = np.dtype([('id', int), ('phot', int),
50 ('xpix', float), ('ypix', float)])
52 camera = lsst_camera()
53 cls._phosim_positions = {}
54 for i_band in range(6):
55 id_arr = None
56 x_arr = None
57 y_arr = None
58 for det in camera:
59 if det.getType() != DetectorType.SCIENCE:
60 continue
61 det_name = det.getName()
62 name = det_name.replace(':','').replace(',','')
63 name = name.replace(' ','_')
64 file_name = 'centroid_lsst_e_2_f%d_%s_E000.txt' % (i_band, name)
65 data = np.genfromtxt(os.path.join(data_dir, 'PhoSimData',
66 file_name),
67 dtype=phosim_dtype,
68 skip_header=1)
69 dm_x, dm_y = pix_transformer.dmPixFromCameraPix(data['xpix'],
70 data['ypix'],
71 det_name)
72 pix_to_focal = det.getTransform(PIXELS, FOCAL_PLANE)
73 x_mm = np.zeros(len(dm_x))
74 y_mm = np.zeros(len(dm_y))
75 for ii in range(len(x_mm)):
76 pix_pt = geom.Point2D(dm_x[ii], dm_y[ii])
77 focal_pt = pix_to_focal.applyForward(pix_pt)
78 x_mm[ii] = focal_pt.getX()
79 y_mm[ii] = focal_pt.getY()
81 if id_arr is None:
82 id_arr = data['id']
83 x_arr = x_mm
84 y_arr = y_mm
85 else:
86 id_arr = np.append(id_arr, data['id'])
87 x_arr = np.append(x_arr, x_mm)
88 y_arr = np.append(y_arr, y_mm)
90 sorted_dex = np.argsort(id_arr)
91 id_arr = id_arr[sorted_dex]
92 x_arr = x_arr[sorted_dex]
93 y_arr = y_arr[sorted_dex]
94 cls._phosim_positions[i_band] = {}
95 cls._phosim_positions[i_band]['id'] = id_arr
96 cls._phosim_positions[i_band]['xmm'] = x_arr
97 cls._phosim_positions[i_band]['ymm'] = y_arr
99 @classmethod
100 def tearDownClass(cls):
101 clean_up_lsst_camera()
103 def test_focal_plane_from_pupil(self):
104 """
105 Test conversion from pupil coords to focal plane coords
106 using data generated by PhoSim
107 """
108 catsim_dtype = np.dtype([('id', int),
109 ('xmm', float), ('ymm', float),
110 ('xpup', float), ('ypup', float),
111 ('raObs', float), ('decObs', float)])
113 catsim_data = np.genfromtxt(os.path.join(self._data_dir, 'CatSimData',
114 'predicted_positions.txt'),
115 dtype=catsim_dtype)
117 for i_band, band in enumerate('ugrizy'):
118 np.testing.assert_array_equal(catsim_data['id'],
119 self._phosim_positions[i_band]['id'])
121 xmm, ymm = focalPlaneCoordsFromPupilCoordsLSST(catsim_data['xpup'],
122 catsim_data['ypup'],
123 band)
125 distance = np.sqrt((xmm-self._phosim_positions[i_band]['xmm'])**2 +
126 (ymm-self._phosim_positions[i_band]['ymm'])**2)
128 # make sure predicted positions are accurate to within
129 # 1 pixel = 0.01 mm
130 self.assertLess(distance.max(), 0.01)
133class FullTransformationTestCase(unittest.TestCase):
134 """
135 Test that we can go from astrophysical coordinates (RA, Dec)
136 to pixel coordinates
137 """
139 longMessage = True
141 @classmethod
142 def setUpClass(cls):
143 cls._data_dir = os.path.join(getPackageDir('sims_data'),
144 'FocalPlaneData',
145 'UnitTestData',
146 'FullUnitTest')
148 truth_name = os.path.join(cls._data_dir, 'truth_catalog.txt')
149 with open(truth_name, 'r') as in_file:
150 header = in_file.readline()
151 params = header.strip().split()
152 ra = float(params[2])
153 dec = float(params[4])
154 rotSkyPos = float(params[6])
155 mjd = float(params[8])
156 cls._obs = ObservationMetaData(pointingRA=ra,
157 pointingDec=dec,
158 rotSkyPos=rotSkyPos,
159 mjd=mjd)
161 cls._obs.site._humidity = 0.0
162 cls._obs.site._pressure = 0.0
163 assert cls._obs.site.humidity == 0.0
164 assert cls._obs.site.pressure == 0.0
166 truth_dtype = np.dtype([('id', int), ('ra', float), ('dec', float),
167 ('pmra', float), ('pmdec', float),
168 ('px', float), ('vrad', float)])
170 cls._truth_data = np.genfromtxt(truth_name, dtype=truth_dtype,
171 delimiter=', ')
173 phosim_dtype = np.dtype([('id', int), ('phot', int),
174 ('xcam', float), ('ycam', float)])
176 list_of_files = os.listdir(cls._data_dir)
178 cls._phosim_data = {}
180 for file_name in list_of_files:
181 if 'centroid' not in file_name:
182 continue
183 full_name = os.path.join(cls._data_dir, file_name)
184 data = np.genfromtxt(full_name, dtype=phosim_dtype,
185 skip_header=1)
187 if len(data.shape)>0:
188 valid = np.where(data['phot']>0)
189 if len(valid[0]) == 0:
190 continue
191 data = data[valid]
192 else:
193 if data['phot'] == 0:
194 continue
196 params = file_name.split('_')
197 chip_name = params[5]+'_'+params[6]
198 filter_name = int(params[4][1])
199 if len(data.shape) == 0:
200 data_raw = data
201 data = {}
202 data['id'] = np.array([data_raw['id']])
203 data['phot'] = np.array([data_raw['phot']])
204 data['xcam'] = np.array([data_raw['xcam']])
205 data['ycam'] = np.array([data_raw['ycam']])
206 cls._phosim_data[(chip_name, 'ugrizy'[filter_name])] = data
208 @classmethod
209 def tearDownClass(cls):
210 clean_up_lsst_camera()
212 def test_chip_name_from_pupil_coords_lsst(self):
213 camera = lsst_camera()
215 x_pup, y_pup = pupilCoordsFromRaDec(self._truth_data['ra'],
216 self._truth_data['dec'],
217 pm_ra=self._truth_data['pmra'],
218 pm_dec=self._truth_data['pmdec'],
219 parallax=self._truth_data['px'],
220 v_rad=self._truth_data['vrad'],
221 obs_metadata=self._obs)
223 for band in 'ugrizy':
224 chip_name_list = chipNameFromPupilCoordsLSST(x_pup, y_pup, band=band)
225 n_checked = 0
226 for ii in range(len(chip_name_list)):
227 chip_name = chip_name_list[ii]
228 if chip_name is None:
229 for kk in self._phosim_data:
230 if kk[1] == band:
231 try:
232 assert self._truth_data['id'][ii] not in self._phosim_data[kk]['id']
233 except AssertionError:
234 # check that source wasn't just on the edge of the chip
235 dex = np.where(self._phosim_data[kk]['id']==self._truth_data['id'][ii])[0]
236 xx = self._phosim_data[kk]['xcam'][dex]
237 yy = self._phosim_data[kk]['ycam'][dex]
238 if xx>10.0 and xx<3990.0 and yy>10.0 and yy<3990.0:
239 msg = '\nxpix: %.3f\nypix: %.3f\n' % (xx, yy)
240 self.assertNotIn(self._truth_data['id'][ii],
241 self._phosim_data[kk]['id'],
242 msg=msg)
243 continue
245 det = camera[chip_name]
246 if det.getType() != DetectorType.SCIENCE:
247 continue
248 n_checked += 1
249 chip_name = chip_name.replace(':','').replace(',','')
250 chip_name = chip_name.replace(' ','_')
251 self.assertIn(self._truth_data['id'][ii],
252 self._phosim_data[(chip_name, band)]['id'])
254 self.assertGreater(n_checked, 200)
256 def test_chip_name_from_pupil_coords_lsst_one_at_a_time(self):
257 """
258 Test that chipNameFromPupilCoordsLSST works on scalars
259 """
260 rng = np.random.RandomState(76621)
261 x_pup, y_pup = pupilCoordsFromRaDec(self._truth_data['ra'],
262 self._truth_data['dec'],
263 pm_ra=self._truth_data['pmra'],
264 pm_dec=self._truth_data['pmdec'],
265 parallax=self._truth_data['px'],
266 v_rad=self._truth_data['vrad'],
267 obs_metadata=self._obs)
269 for band in 'ugrizy':
270 chip_name_list = chipNameFromPupilCoordsLSST(x_pup, y_pup, band=band)
271 self.assertIsInstance(chip_name_list, np.ndarray)
272 n_none = 0
273 n_not_none = 0
274 subsample = rng.choice(np.arange(len(chip_name_list), dtype=int),
275 size=50, replace=False)
276 for ii in subsample:
277 name = chipNameFromPupilCoordsLSST(x_pup[ii], y_pup[ii], band=band)
278 if name is not None:
279 self.assertIsInstance(name, str)
280 n_not_none += 1
281 else:
282 n_none += 1
283 self.assertEqual(name, chip_name_list[ii])
285 self.assertGreater(n_not_none, n_none//2)
287 def test_pupil_coords_from_ra_dec(self):
288 """
289 Verify that pupilCoordsFromRaDec gives results consistent
290 with the naive pupil coordinate method used by the
291 Zernike fitter
292 """
294 phosim_catalog_file = os.path.join(self._data_dir, 'phosim_catalog.txt')
295 ra_obs = []
296 dec_obs = []
297 unique_id = []
298 with open(phosim_catalog_file,'r') as input_file:
299 for line in input_file:
300 params = line.strip().split()
301 if params[0] != 'object':
302 if params[0] == 'rightascension':
303 ra_pointing = float(params[1])
304 if params[0] == 'declination':
305 dec_pointing = float(params[1])
306 if params[0] == 'rotskypos':
307 rotskypos = float(params[1])
308 continue
309 unique_id.append(int(params[1]))
310 ra_obs.append(float(params[2]))
311 dec_obs.append(float(params[3]))
312 unique_id = np.array(unique_id)
313 ra_obs = np.array(ra_obs)
314 dec_obs = np.array(dec_obs)
315 x_pup, y_pup = _rawPupilCoordsFromObserved(np.radians(ra_obs),
316 np.radians(dec_obs),
317 np.radians(ra_pointing),
318 np.radians(dec_pointing),
319 np.radians(rotskypos))
321 sorted_dex = np.argsort(unique_id)
322 unique_id = unique_id[sorted_dex]
323 x_pup = x_pup[sorted_dex]
324 y_pup = y_pup[sorted_dex]
326 (x_pup_test,
327 y_pup_test) = pupilCoordsFromRaDec(self._truth_data['ra'],
328 self._truth_data['dec'],
329 pm_ra=self._truth_data['pmra'],
330 pm_dec=self._truth_data['pmdec'],
331 parallax=self._truth_data['px'],
332 v_rad=self._truth_data['vrad'],
333 obs_metadata=self._obs)
335 sorted_dex = np.argsort(self._truth_data['id'])
336 truth_id = self._truth_data['id'][sorted_dex]
337 x_pup_test = x_pup_test[sorted_dex]
338 y_pup_test = y_pup_test[sorted_dex]
340 np.testing.assert_array_equal(unique_id, truth_id)
341 distance = np.sqrt((x_pup-x_pup_test)**2 +
342 (y_pup-y_pup_test)**2)
344 tenth_milli_arcsec = np.radians(0.0001/3600.0)
345 self.assertLess(distance.max(), tenth_milli_arcsec)
347 def test_focal_coords_from_pupil_coords(self):
348 """
349 Test that using pupilCoordsFromRaDec and
350 focalPlaneCoordsFromPupilCoordsLSST gives answers
351 consistent with PhoSim
352 """
353 camera = lsst_camera()
354 pix_transformer = DMtoCameraPixelTransformer()
356 x_pup, y_pup = pupilCoordsFromRaDec(self._truth_data['ra'],
357 self._truth_data['dec'],
358 pm_ra=self._truth_data['pmra'],
359 pm_dec=self._truth_data['pmdec'],
360 parallax=self._truth_data['px'],
361 v_rad=self._truth_data['vrad'],
362 obs_metadata=self._obs)
364 (xf_no_optics,
365 yf_no_optics) = focalPlaneCoordsFromPupilCoords(x_pup,
366 y_pup, camera=lsst_camera())
368 for band in 'ugrizy':
370 n_check = 0
371 d_max = None
372 n_old_better = 0
373 n_new_better = 0
375 (xf_optics,
376 yf_optics) = focalPlaneCoordsFromPupilCoordsLSST(x_pup, y_pup, band)
378 for det in camera:
379 if det.getType() != DetectorType.SCIENCE:
380 continue
381 det_name = det.getName()
382 name = det_name.replace(':','').replace(',','').replace(' ','_')
383 key_tuple = (name, band)
384 if key_tuple not in self._phosim_data:
385 continue
386 phosim_data = self._phosim_data[key_tuple]
388 pixel_to_focal = det.getTransform(PIXELS, FOCAL_PLANE)
390 (xdm_arr,
391 ydm_arr) = pix_transformer.dmPixFromCameraPix(phosim_data['xcam'],
392 phosim_data['ycam'],
393 det_name)
395 for id_val, xdm, ydm in zip(phosim_data['id'],xdm_arr, ydm_arr):
397 dex = np.where(self._truth_data['id'] == id_val)
398 xf = xf_optics[dex]
399 yf = yf_optics[dex]
401 pixel_pt = geom.Point2D(xdm, ydm)
402 focal_pt = pixel_to_focal.applyForward(pixel_pt)
404 dist = np.sqrt((xf-focal_pt.getX())**2+(yf-focal_pt.getY())**2)
405 r_center = np.sqrt(focal_pt.getX()**2 + focal_pt.getY()**2)
407 old_dist = np.sqrt((xf_no_optics[dex]-focal_pt.getX())**2 +
408 (yf_no_optics[dex]-focal_pt.getY())**2)
410 msg = '\nObject %d' % id_val
411 msg += '\nchip %s' % det_name
412 msg += '\nband %s' % band
413 msg += '\ndistance from center: %.4e' % r_center
414 msg += '\nPupil: %.4e %.4e' % (x_pup[dex], y_pup[dex])
415 msg += '\nPhosim: %.4f %.4f' % (focal_pt.getX(),focal_pt.getY())
416 msg += '\nCatSim: %.4f %.4f'% (xf, yf)
417 msg += '\nPixels: %.4f %.4f' % (xdm, ydm)
418 msg += '\nnew dist %.4e old_dist %.4e' % (dist, old_dist)
420 if dist<old_dist:
421 n_new_better += 1
422 else:
423 n_old_better += 1
425 # Near the center of the focal plane, the old transformation
426 # with no filter-dependence is actually better, but neither
427 # is off by more than a pixel
428 #
429 # It also occasionally happens that the old transformation
430 # was slightly better at the very edge of the focal plane
431 # (in some filters)
432 if old_dist<dist:
433 if r_center < 100.0:
434 # if we in the heart of the focal plane, make
435 # sure that the fit has not degraded by more
436 # than half a pixel and that the difference
437 # between CatSim and PhoSim is still less
438 # than a pixel
439 self.assertLess(dist-old_dist, 0.005, msg=msg)
440 self.assertLess(dist, 0.01, msg=msg)
441 else:
442 # if we are near the edge of the focal plane,
443 # make sure that the difference between
444 # CatSim and PhoSim is less than 2 pixels
445 self.assertLess(dist, 0.02, msg=msg)
446 else:
447 if r_center < 100.0:
448 # if we are in the heart of the focal plane,
449 # make sure that the difference between
450 # CatSim and PhoSim is less than a pixel
451 self.assertLess(dist, 0.01, msg=msg)
452 else:
453 # If we are at the edge of the focal plane,
454 # make sure that the difference between
455 # CatSim and PhoSim is less than five pixels,
456 # and if the difference is less than 2 pixels,
457 # make sure that the difference under the old
458 # transformation is more than 15 pixels (indicating
459 # that we are in a difficult-to-fit part of the
460 # focal plane)
461 self.assertLess(dist, 0.05, msg=msg)
462 if dist > 0.02:
463 self.assertGreater(old_dist, 0.15, msg=msg)
465 n_check += 1
467 self.assertGreater(n_check, 200)
468 self.assertGreater(n_new_better, 4*n_old_better)
470 def test_focal_coords_from_pupil_coords_vectorized(self):
471 """
472 Test that focalPlaneCoordsFromPupilCoordsLSST acting
473 on numpy arrays gives the same result as acting on
474 scalars
475 """
476 rng = np.random.RandomState(192312)
477 camera = lsst_camera()
478 pix_transformer = DMtoCameraPixelTransformer()
480 x_pup, y_pup = pupilCoordsFromRaDec(self._truth_data['ra'],
481 self._truth_data['dec'],
482 pm_ra=self._truth_data['pmra'],
483 pm_dec=self._truth_data['pmdec'],
484 parallax=self._truth_data['px'],
485 v_rad=self._truth_data['vrad'],
486 obs_metadata=self._obs)
488 for band in 'ugrizy':
489 x_f, y_f = focalPlaneCoordsFromPupilCoordsLSST(x_pup,
490 y_pup,
491 band=band)
493 subsample = rng.choice(np.arange(len(x_pup), dtype=int),
494 size=50, replace=False)
495 for ii in subsample:
496 x_f1, y_f1 = focalPlaneCoordsFromPupilCoordsLSST(x_pup[ii],
497 y_pup[ii],
498 band=band)
500 self.assertIsInstance(x_f1, numbers.Number)
501 self.assertIsInstance(y_f1, numbers.Number)
502 self.assertAlmostEqual(x_f1, x_f[ii], 8)
503 self.assertAlmostEqual(y_f1, y_f[ii], 8)
505 def test_pixel_coords_from_ra_dec(self):
506 """
507 Test that pixelCoordsFromRaDecLSST() works correctly
508 """
509 pix_transformer = DMtoCameraPixelTransformer()
511 x_pup, y_pup = pupilCoordsFromRaDec(self._truth_data['ra'],
512 self._truth_data['dec'],
513 pm_ra=self._truth_data['pmra'],
514 pm_dec=self._truth_data['pmdec'],
515 parallax=self._truth_data['px'],
516 v_rad=self._truth_data['vrad'],
517 obs_metadata=self._obs)
519 (x_pix_no_optics,
520 y_pix_no_optics) = pixelCoordsFromRaDec(self._truth_data['ra'],
521 self._truth_data['dec'],
522 pm_ra=self._truth_data['pmra'],
523 pm_dec=self._truth_data['pmdec'],
524 parallax=self._truth_data['px'],
525 v_rad=self._truth_data['vrad'],
526 obs_metadata=self._obs,
527 camera=lsst_camera())
529 for band in 'ugrizy':
531 x_pix, y_pix = pixelCoordsFromRaDecLSST(self._truth_data['ra'],
532 self._truth_data['dec'],
533 pm_ra=self._truth_data['pmra'],
534 pm_dec=self._truth_data['pmdec'],
535 parallax=self._truth_data['px'],
536 v_rad=self._truth_data['vrad'],
537 obs_metadata=self._obs,
538 band=band)
540 (x_f,
541 y_f) = focalPlaneCoordsFromPupilCoordsLSST(x_pup, y_pup, band=band)
543 r_center = np.sqrt(x_f**2 + y_f**2)
545 n_check = 0
546 n_diff_chip = 0
547 n_old_better = 0
548 n_new_better = 0
550 dist_arr = []
552 for det in lsst_camera():
553 if det.getType() != DetectorType.SCIENCE:
554 continue
555 det_name = det.getName()
556 name = det_name.replace(':','').replace(',','').replace(' ','_')
557 key_tuple = (name, band)
558 if key_tuple not in self._phosim_data:
559 continue
560 phosim_data = self._phosim_data[key_tuple]
562 for id_val, xcam, ycam in zip(phosim_data['id'],
563 phosim_data['xcam'],
564 phosim_data['ycam']):
566 dex = np.where(self._truth_data['id'] == id_val)
567 self.assertEqual(len(dex[0]), 1)
568 dex = dex[0][0]
569 x_pix_val = x_pix[dex]
570 y_pix_val = y_pix[dex]
571 if np.isnan(x_pix_val):
572 # PhoSim centroid files will report flux from bright
573 # stars that spill over onto neighboring chips. In
574 # this case, CatSim will report chipName=None and
575 # xpix=ypix=Nan. In these cases, we will force
576 # CatSim to calculate the pixel coordinates of the
577 # object on the chip that PhoSim is reporting and
578 # compare that result to the contents of the PhoSim
579 # centroid file.
580 #
581 n_diff_chip += 1
583 (x_pix_val,
584 y_pix_val) = pixelCoordsFromRaDecLSST(self._truth_data['ra'][dex],
585 self._truth_data['dec'][dex],
586 chipName = det_name,
587 pm_ra=self._truth_data['pmra'][dex],
588 pm_dec=self._truth_data['pmdec'][dex],
589 parallax=self._truth_data['px'][dex],
590 v_rad=self._truth_data['vrad'][dex],
591 obs_metadata=self._obs,
592 band=band)
594 self.assertIsInstance(x_pix_val, np.float)
595 self.assertIsInstance(y_pix_val, np.float)
597 x_pix_no_optics_val = x_pix_no_optics[dex]
598 y_pix_no_optics_val = y_pix_no_optics[dex]
599 if np.isnan(x_pix_no_optics_val):
601 x, y = pixelCoordsFromRaDec(self._truth_data['ra'][dex],
602 self._truth_data['dec'][dex],
603 chipName = det_name,
604 pm_ra=self._truth_data['pmra'][dex],
605 pm_dec=self._truth_data['pmdec'][dex],
606 parallax=self._truth_data['px'][dex],
607 v_rad=self._truth_data['vrad'][dex],
608 obs_metadata=self._obs,
609 camera=lsst_camera())
611 x_pix_no_optics_val = x
612 y_pix_no_optics_val = y
614 self.assertIsInstance(x_pix_no_optics_val, np.float)
615 self.assertIsInstance(y_pix_no_optics_val, np.float)
617 x_dm, y_dm = pix_transformer.dmPixFromCameraPix(xcam, ycam, det_name)
618 dd = np.sqrt((x_dm-x_pix_val)**2 + (y_dm-y_pix_val)**2)
619 dist_arr.append(dd)
620 dd_no_optics = np.sqrt((x_dm-x_pix_no_optics_val)**2 +
621 (y_dm-y_pix_no_optics_val)**2)
623 msg = '\nObject %d; chip %s' % (id_val, det_name)
624 msg += '\nband %s' % band
625 msg += '\ndist from center %.4e pixels' % (r_center[dex]/0.01)
626 msg += '\nPupil: %.4e %.4e' % (x_pup[dex], x_pup[dex])
627 msg += '\nPhoSim: %.4f %.4f' % (x_dm, y_dm)
628 msg += '\nCatSim: %.4f %.4f -- %.4e' % (x_pix_val, y_pix_val, dd)
629 msg += '\nno Optics: %.4f %.4f -- %.4e' % (x_pix_no_optics_val,
630 y_pix_no_optics_val,
631 dd_no_optics)
633 if dd<dd_no_optics:
634 n_new_better += 1
635 else:
636 n_old_better += 1
638 # Near the center of the focal plane, the old transformation
639 # with no filter-dependence is actually better, but neither
640 # is off by more than a pixel
641 #
642 # It also occasionally happens that the old transformation
643 # was slightly better at the very edge of the focal plane
644 # (in some filters)
645 if dd_no_optics<dd:
646 if r_center[dex] < 100.0:
647 # if we in the heart of the focal plane, make
648 # sure that the fit has not degraded by more
649 # than half a pixel and that the difference
650 # between CatSim and PhoSim is still less
651 # than a pixel
652 self.assertLess(dd-dd_no_optics, 5.0, msg=msg)
653 self.assertLess(dd, 1.0, msg=msg)
654 else:
655 # if we are near the edge of the focal plane,
656 # make sure that the difference between
657 # CatSim and PhoSim is less than 2 pixels
658 self.assertLess(dd, 2.0, msg=msg)
659 else:
660 if r_center[dex] < 100.0:
661 # if we are in the heart of the focal plane,
662 # make sure that the difference between
663 # CatSim and PhoSim is less than a pixel
664 self.assertLess(dd, 1.0, msg=msg)
665 else:
666 # If we are at the edge of the focal plane,
667 # make sure that the difference between
668 # CatSim and PhoSim is less than five pixels,
669 # and if the difference is less than 2 pixels,
670 # make sure that the difference under the old
671 # transformation is more than 15 pixels (indicating
672 # that we are in a difficult-to-fit part of the
673 # focal plane)
674 self.assertLess(dd, 5.0, msg=msg)
675 if dd > 2.0:
676 self.assertGreater(dd_no_optics, 15.0, msg=msg)
678 n_check += 1
680 if dd > 1.0:
681 if dd_no_optics>15.0:
682 self.assertLess(dd, 5.0, msg=msg)
683 else:
684 self.assertLess(dd, 2.0, msg=msg)
686 self.assertGreater(n_check, 200)
687 self.assertLess(n_diff_chip, n_check//2)
688 self.assertGreater(n_new_better, 4*n_old_better)
689 dist_arr = np.array(dist_arr)
690 dist_arr = np.sort(dist_arr)
692 def test_pixel_coords_from_ra_dec_one_at_a_time(self):
693 """
694 Test that pixelCoordsFromRaDecLSST works correctly on
695 scalars
696 """
698 rng = np.random.RandomState(1845332)
700 for band in 'ugrizy':
702 x_pix, y_pix = pixelCoordsFromRaDecLSST(self._truth_data['ra'],
703 self._truth_data['dec'],
704 pm_ra=self._truth_data['pmra'],
705 pm_dec=self._truth_data['pmdec'],
706 parallax=self._truth_data['px'],
707 v_rad=self._truth_data['vrad'],
708 obs_metadata=self._obs,
709 band=band)
711 self.assertIsInstance(x_pix, np.ndarray)
712 self.assertIsInstance(y_pix, np.ndarray)
714 n_nan = 0
715 n_good = 0
716 subsample = rng.choice(np.arange(len(x_pix), dtype=int),
717 size=50, replace=False)
718 for ii in subsample: # only test on a subsample; this is slow
719 x_pix1, y_pix1 = pixelCoordsFromRaDecLSST(self._truth_data['ra'][ii],
720 self._truth_data['dec'][ii],
721 pm_ra=self._truth_data['pmra'][ii],
722 pm_dec=self._truth_data['pmdec'][ii],
723 parallax=self._truth_data['px'][ii],
724 v_rad=self._truth_data['vrad'][ii],
725 obs_metadata=self._obs,
726 band=band)
728 self.assertIsInstance(x_pix1, numbers.Number)
729 self.assertIsInstance(y_pix1, numbers.Number)
730 if not np.isnan(x_pix1):
731 self.assertAlmostEqual(x_pix1, x_pix[ii], 8)
732 self.assertAlmostEqual(y_pix1, y_pix[ii], 8)
733 n_good += 1
734 else:
735 n_nan += 1
737 self.assertLess(n_nan, n_good//2)
739 def test_pupil_coords_from_focal_plane_coords_LSST(self):
740 """
741 Test that pupilCoordsFromFocalPlaneCoordsLSST inverts
742 focalPlaneCoordsFromPupilCoordsLSST
743 """
744 x_f = np.arange(-317.0, 317.0, 20.0)
745 y_f = np.arange(-317.0, 317.0, 20.0)
746 mesh = np.meshgrid(x_f, y_f)
747 x_f = mesh[0].flatten()
748 y_f = mesh[1].flatten()
749 for band in 'ugrizy':
750 x_p, y_p = pupilCoordsFromFocalPlaneCoordsLSST(x_f, y_f, band=band)
751 x_f1, y_f1 = focalPlaneCoordsFromPupilCoordsLSST(x_p, y_p,
752 band=band)
754 dd = np.sqrt((x_f-x_f1)**2 + (y_f-y_f1)**2)
755 self.assertLess(dd.max(), 3.0e-6)
757 def test_pupil_coords_from_focal_plane_coords_LSST_one_at_a_time(self):
758 """
759 Test that pupilCoordsFromFocalPlaneCoordsLSST works on scalars
760 """
761 rng = np.random.RandomState(8123412)
762 x_f = np.arange(-317.0, 317.0, 20.0)
763 y_f = np.arange(-317.0, 317.0, 20.0)
764 mesh = np.meshgrid(x_f, y_f)
765 x_f = mesh[0].flatten()
766 y_f = mesh[1].flatten()
768 for band in 'ugrizy':
769 x_p, y_p = pupilCoordsFromFocalPlaneCoordsLSST(x_f, y_f, band=band)
770 self.assertIsInstance(x_p, np.ndarray)
771 self.assertIsInstance(y_p, np.ndarray)
772 subsample = rng.choice(np.arange(len(x_p), dtype=int),
773 size=50, replace=False)
774 for ii in subsample:
775 x_p1, y_p1 = pupilCoordsFromFocalPlaneCoordsLSST(x_f[ii], y_f[ii],
776 band=band)
778 self.assertIsInstance(x_p1, numbers.Number)
779 self.assertIsInstance(y_p1, numbers.Number)
780 self.assertAlmostEqual(x_p1, x_p[ii], 16)
781 self.assertAlmostEqual(y_p1, y_p[ii], 16)
783 def test_chip_name_from_ra_dec_lsst(self):
784 """
785 Test that chipNameFromRaDecLSST is consistent with
786 chipNameFromPupilCoordsLSST
787 """
788 x_pup, y_pup = pupilCoordsFromRaDec(self._truth_data['ra'],
789 self._truth_data['dec'],
790 pm_ra=self._truth_data['pmra'],
791 pm_dec=self._truth_data['pmdec'],
792 parallax=self._truth_data['px'],
793 v_rad=self._truth_data['vrad'],
794 obs_metadata=self._obs)
796 for band in 'ugrizy':
797 chip_name_list = chipNameFromPupilCoordsLSST(x_pup, y_pup, band=band)
798 chip_name_list_1 = chipNameFromRaDecLSST(self._truth_data['ra'],
799 self._truth_data['dec'],
800 pm_ra=self._truth_data['pmra'],
801 pm_dec=self._truth_data['pmdec'],
802 parallax=self._truth_data['px'],
803 v_rad=self._truth_data['vrad'],
804 obs_metadata=self._obs,
805 band=band)
807 np.testing.assert_array_equal(chip_name_list, chip_name_list_1)
808 n_none = np.where(np.char.find(chip_name_list.astype(str), 'None')==0)
809 self.assertLess(len(n_none[0]), len(chip_name_list)//4)
811 def test_chip_name_from_ra_dec_lsst_one_at_a_time(self):
812 """
813 Test that chipNameFromRaDecLSST works on scalars
814 """
815 rng = np.random.RandomState(65673)
816 for band in 'ugrizy':
817 chip_name_list = chipNameFromRaDecLSST(self._truth_data['ra'],
818 self._truth_data['dec'],
819 pm_ra=self._truth_data['pmra'],
820 pm_dec=self._truth_data['pmdec'],
821 parallax=self._truth_data['px'],
822 v_rad=self._truth_data['vrad'],
823 obs_metadata=self._obs,
824 band=band)
826 self.assertIsInstance(chip_name_list, np.ndarray)
827 n_none = 0
828 n_not_none = 0
829 subsample = rng.choice(np.arange(len(chip_name_list), dtype=int),
830 size=50, replace=False)
831 for ii in subsample:
832 name = chipNameFromRaDecLSST(self._truth_data['ra'][ii],
833 self._truth_data['dec'][ii],
834 pm_ra=self._truth_data['pmra'][ii],
835 pm_dec=self._truth_data['pmdec'][ii],
836 parallax=self._truth_data['px'][ii],
837 v_rad=self._truth_data['vrad'][ii],
838 obs_metadata=self._obs,
839 band=band)
841 if name is not None:
842 n_not_none += 1
843 self.assertIsInstance(name, str)
844 else:
845 n_none += 1
847 self.assertEqual(name, chip_name_list[ii])
849 self.assertGreater(n_not_none, n_none//2)
851 def test_radians(self):
852 """
853 Test the radians versions of pixelCoordsFromRaDecLSST and
854 chipNameFromRaDecLSST
855 """
856 for band in 'ugrizy':
858 x_pix, y_pix = pixelCoordsFromRaDecLSST(self._truth_data['ra'],
859 self._truth_data['dec'],
860 pm_ra=self._truth_data['pmra'],
861 pm_dec=self._truth_data['pmdec'],
862 parallax=self._truth_data['px'],
863 v_rad=self._truth_data['vrad'],
864 obs_metadata=self._obs,
865 band=band)
867 (x_pix_r,
868 y_pix_r) = _pixelCoordsFromRaDecLSST(np.radians(self._truth_data['ra']),
869 np.radians(self._truth_data['dec']),
870 pm_ra=radiansFromArcsec(self._truth_data['pmra']),
871 pm_dec=radiansFromArcsec(self._truth_data['pmdec']),
872 parallax=radiansFromArcsec(self._truth_data['px']),
873 v_rad=self._truth_data['vrad'],
874 obs_metadata=self._obs,
875 band=band)
877 np.testing.assert_array_equal(x_pix, x_pix_r)
878 np.testing.assert_array_equal(y_pix, y_pix_r)
880 chip_name_list = chipNameFromRaDecLSST(self._truth_data['ra'],
881 self._truth_data['dec'],
882 pm_ra=self._truth_data['pmra'],
883 pm_dec=self._truth_data['pmdec'],
884 parallax=self._truth_data['px'],
885 v_rad=self._truth_data['vrad'],
886 obs_metadata=self._obs,
887 band=band)
889 chip_name_list_r = _chipNameFromRaDecLSST(np.radians(self._truth_data['ra']),
890 np.radians(self._truth_data['dec']),
891 pm_ra=radiansFromArcsec(self._truth_data['pmra']),
892 pm_dec=radiansFromArcsec(self._truth_data['pmdec']),
893 parallax=radiansFromArcsec(self._truth_data['px']),
894 v_rad=self._truth_data['vrad'],
895 obs_metadata=self._obs,
896 band=band)
898 np.testing.assert_array_equal(chip_name_list, chip_name_list_r)
900 def test_pupil_coords_from_pixel_coords_LSST(self):
901 """
902 Test that pupilCoordsFromPixelCoordsLSST inverts
903 pixelCoordsFromPupilCoordsLSST
904 """
905 xpix = np.arange(-2000.0, 2000.0, 100.0)
906 ypix = np.arange(-2000.0, 2000.0, 100.0)
907 mesh = np.meshgrid(xpix, ypix)
908 xpix = mesh[0].flatten()
909 ypix = mesh[1].flatten()
911 chip_name = 'R:3,1 S:1,2'
913 chip_name_list = ['None']
914 for det in lsst_camera():
915 if det.getType() == DetectorType.SCIENCE:
916 chip_name_list.append(det.getName())
917 chip_name_list = np.array(chip_name_list)
918 rng = np.random.RandomState(81231)
919 chip_name_sample = rng.choice(chip_name_list, size=len(xpix),
920 replace=True)
922 for band in 'ugrizy':
923 xpup, ypup = pupilCoordsFromPixelCoordsLSST(xpix, ypix,
924 chipName=chip_name,
925 band=band)
927 xpix1, ypix1 = pixelCoordsFromPupilCoordsLSST(xpup, ypup,
928 chipName=chip_name,
929 band=band)
931 dd = np.sqrt((xpix-xpix1)**2 + (ypix-ypix1)**2)
932 self.assertLess(dd.max(), 1.0e-4)
934 xpup, ypup = pupilCoordsFromPixelCoordsLSST(xpix, ypix,
935 chipName=chip_name_sample,
936 band=band)
938 xpix1, ypix1 = pixelCoordsFromPupilCoordsLSST(xpup, ypup,
939 chipName=chip_name_sample,
940 band=band)
942 valid = np.where(np.char.find(chip_name_sample, 'None')<0)
943 self.assertGreater(len(valid[0]), 0)
944 self.assertLess(len(valid[0]), len(xpix))
945 dd = np.sqrt((xpix[valid]-xpix1[valid])**2 + (ypix[valid]-ypix1[valid])**2)
946 self.assertLess(dd.max(), 1.0e-4)
948 for dist in dd:
949 self.assertFalse(np.isnan(dist))
951 invalid = np.where(np.char.find(chip_name_sample, 'None')==0)
952 for ii in invalid[0]:
953 self.assertTrue(np.isnan(xpix1[ii]))
954 self.assertTrue(np.isnan(ypix1[ii]))
956 def test_ra_dec_from_pixel_coords_lsst(self):
957 """
958 Test that raDecFromPixelCoordsLSST inverts
959 pixelCoordsFromRaDecLSST
960 """
962 rng = np.random.RandomState(1811231)
963 n_samples = 500
964 rr = rng.random_sample(n_samples)*2.2
965 theta = rng.random_sample(n_samples)*2.0*np.pi
966 ra = self._obs.pointingRA + rr*np.cos(theta)
967 dec = self._obs.pointingDec + rr*np.sin(theta)
969 name_list = [None]
970 for det in lsst_camera():
971 if det.getType() == DetectorType.SCIENCE:
972 name_list.append(det.getName())
973 name_list = np.array(name_list)
974 name_sample = rng.choice(name_list, size=n_samples, replace=True)
976 for band in 'ugrizy':
977 xpix, ypix = pixelCoordsFromRaDecLSST(ra, dec,
978 chipName=name_sample,
979 band=band,
980 obs_metadata=self._obs)
982 ra1, dec1 = raDecFromPixelCoordsLSST(xpix, ypix, chipName=name_sample,
983 band=band,
984 obs_metadata=self._obs)
986 valid = np.where(np.isfinite(ra1))
987 valid_name = np.where(np.char.find(name_sample.astype(str), 'None')<0)
988 np.testing.assert_array_equal(valid[0], valid_name[0])
990 invalid = np.where(np.isnan(ra1))
991 invalid_name = np.where(np.char.find(name_sample.astype(str), 'None')==0)
992 np.testing.assert_array_equal(invalid[0], invalid_name[0])
994 self.assertGreater(len(invalid[0]), 0)
995 self.assertGreater(len(valid[0]), 0)
997 dist = angularSeparation(ra[valid], dec[valid], ra1[valid], dec1[valid])
998 dist *= 3600.0
999 self.assertLess(dist.max(), 1.0e-5)
1001 # test one at a time
1002 for ii in range(len(ra1)):
1003 ra2, dec2 = raDecFromPixelCoordsLSST(xpix[ii], ypix[ii],
1004 chipName=str(name_sample[ii]),
1005 band=band,
1006 obs_metadata=self._obs)
1008 self.assertIsInstance(ra2, numbers.Number)
1009 self.assertIsInstance(dec2, numbers.Number)
1011 if name_sample[ii] is None:
1012 self.assertTrue(np.isnan(ra2))
1013 self.assertTrue(np.isnan(dec2))
1014 else:
1015 self.assertAlmostEqual(ra2, ra1[ii], 10)
1016 self.assertAlmostEqual(dec2, dec1[ii], 10)
1019 def test_ra_dec_from_pixel_coords_lsst_radians(self):
1020 """
1021 Test that radians version of raDecFromPixelCoordsLSST
1022 agrees with degrees version
1023 """
1024 rng = np.random.RandomState(56123)
1025 n_samples = 500
1026 name_list = [None]
1027 for det in lsst_camera():
1028 if det.getType() == DetectorType.SCIENCE:
1029 name_list.append(det.getName())
1030 name_list = np.array(name_list)
1031 name_sample = rng.choice(name_list, size=n_samples, replace=True)
1032 invalid = np.where(np.char.find(name_sample.astype(str), 'None')==0)
1033 self.assertLess(len(invalid[0]), n_samples//2)
1035 xpix = rng.random_sample(n_samples)*4000.0
1036 ypix = rng.random_sample(n_samples)*4000.0
1037 for band in 'ugrizy':
1038 ra_deg, dec_deg = raDecFromPixelCoordsLSST(xpix, ypix, chipName=name_sample,
1039 obs_metadata=self._obs)
1042 ra_rad, dec_rad = _raDecFromPixelCoordsLSST(xpix, ypix, chipName=name_sample,
1043 obs_metadata=self._obs)
1046 valid = np.where(np.isfinite(ra_deg))
1047 np.testing.assert_array_equal(np.degrees(ra_rad[valid]), ra_deg[valid])
1048 np.testing.assert_array_equal(np.degrees(dec_rad[valid]), dec_deg[valid])
1049 self.assertGreater(len(valid[0]), n_samples//2)
1050 for ii in invalid[0]:
1051 self.assertTrue(np.isnan(ra_rad[ii]))
1052 self.assertTrue(np.isnan(dec_rad[ii]))
1053 for ii in range(n_samples):
1054 ra1, dec1 = _raDecFromPixelCoordsLSST(xpix[ii], ypix[ii],
1055 chipName=str(name_sample[ii]),
1056 obs_metadata=self._obs)
1058 self.assertIsInstance(ra1, numbers.Number)
1059 self.assertIsInstance(dec1, numbers.Number)
1060 if name_sample[ii] is None:
1061 self.assertTrue(np.isnan(ra1))
1062 self.assertTrue(np.isnan(dec1))
1063 else:
1064 self.assertAlmostEqual(ra1, ra_rad[ii], 10)
1065 self.assertAlmostEqual(dec1, dec_rad[ii], 10)
1067 def test_nans(self):
1068 """
1069 Test that points outside the focal plane get NaNs for pupil
1070 and focal plane coords
1071 """
1072 rng = np.random.RandomState(66)
1073 n_samples = 100
1074 rr = rng.random_sample(n_samples)*600.0
1075 theta = rng.random_sample(n_samples)*2.0*np.pi
1076 self.assertGreater(rr.max(), 500.0)
1077 xf = rr*np.cos(theta)
1078 yf = rr*np.sin(theta)
1079 xp, yp = pupilCoordsFromFocalPlaneCoordsLSST(xf, yf, band='g')
1080 name_list = chipNameFromPupilCoordsLSST(xp, yp, band='g')
1081 xpix, ypix = pixelCoordsFromPupilCoordsLSST(xp, yp,
1082 chipName='R:2,2 S:1,1',
1083 band='g')
1085 ra, dec = raDecFromPixelCoordsLSST(xpix, ypix, 'R:2,2 S:1,1',
1086 obs_metadata=self._obs,
1087 band='g')
1089 xpix2, ypix2 = pixelCoordsFromPupilCoordsLSST(xp, yp,
1090 band='g')
1091 invalid = np.where(rr>500.0)[0]
1092 self.assertGreater(len(invalid), 0)
1093 self.assertLess(len(invalid), n_samples)
1094 non_nan_pix = 0
1095 non_none_name = 0
1096 for ii in range(n_samples):
1097 if ii in invalid:
1098 self.assertTrue(np.isnan(xp[ii]))
1099 self.assertTrue(np.isnan(yp[ii]))
1100 self.assertTrue(np.isnan(xpix[ii]))
1101 self.assertTrue(np.isnan(ypix[ii]))
1102 self.assertTrue(np.isnan(xpix2[ii]))
1103 self.assertTrue(np.isnan(ypix2[ii]))
1104 self.assertTrue(np.isnan(ra[ii]))
1105 self.assertTrue(np.isnan(dec[ii]))
1106 self.assertIsNone(name_list[ii])
1107 else:
1108 self.assertFalse(np.isnan(xp[ii]))
1109 self.assertFalse(np.isnan(yp[ii]))
1110 self.assertFalse(np.isnan(xpix[ii]))
1111 self.assertFalse(np.isnan(ypix[ii]))
1112 self.assertFalse(np.isnan(ra[ii]))
1113 self.assertFalse(np.isnan(dec[ii]))
1115 # this test is because, even if an object
1116 # has finite pupil or focal plane coordinates,
1117 # it could still land in a chip gap, causing
1118 # chip_name=None, xpix=ypix=NaN
1119 if not np.isnan(xpix2[ii]) and not np.isnan(ypix2[ii]):
1120 non_nan_pix += 1
1121 if name_list[ii] is not None:
1122 non_none_name += 1
1124 self.assertGreater(non_nan_pix, 0)
1125 self.assertGreater(non_none_name, 0)
1127 rr = rng.random_sample(n_samples)*0.05
1128 xp = rr*np.cos(theta)
1129 yp = rr*np.sin(theta)
1131 xf2, yf2 = focalPlaneCoordsFromPupilCoordsLSST(xp, yp, band='i')
1132 xpix, ypix = pixelCoordsFromPupilCoordsLSST(xp, yp, chipName='R:2,2 S:1,1',
1133 band='i')
1135 ra, dec = raDecFromPixelCoordsLSST(xpix, ypix, 'R:2,2 S:1,1',
1136 obs_metadata=self._obs,
1137 band='i')
1139 xpix2, ypix2 = pixelCoordsFromPupilCoordsLSST(xp, yp,
1140 band='g')
1142 invalid = np.where(rr>0.04841)[0]
1143 self.assertGreater(len(invalid), 0)
1144 self.assertLess(len(invalid), n_samples)
1145 non_nan_pix = 0
1146 for ii in range(n_samples):
1147 if ii in invalid:
1148 self.assertTrue(np.isnan(xf2[ii]))
1149 self.assertTrue(np.isnan(yf2[ii]))
1150 self.assertTrue(np.isnan(xpix[ii]))
1151 self.assertTrue(np.isnan(ypix[ii]))
1152 self.assertTrue(np.isnan(xpix2[ii]))
1153 self.assertTrue(np.isnan(ypix2[ii]))
1154 self.assertTrue(np.isnan(ra[ii]))
1155 self.assertTrue(np.isnan(dec[ii]))
1156 else:
1157 self.assertFalse(np.isnan(xf2[ii]))
1158 self.assertFalse(np.isnan(yf2[ii]))
1159 self.assertFalse(np.isnan(xpix[ii]))
1160 self.assertFalse(np.isnan(ypix[ii]))
1161 self.assertFalse(np.isnan(ra[ii]))
1162 self.assertFalse(np.isnan(dec[ii]))
1164 # this test is because, even if an object
1165 # has finite pupil or focal plane coordinates,
1166 # it could still land in a chip gap, causing
1167 # chip_name=None, xpix=ypix=NaN
1168 if not np.isnan(xpix2[ii]) and not np.isnan(ypix2[ii]):
1169 non_nan_pix += 1
1171 self.assertGreater(non_nan_pix, 0)
1173 xf = np.array([1.1, 2.1, np.NaN, 4.5])
1174 yf = np.array([2.1, np.NaN, 1.2, 3.0])
1175 xp, yp = pupilCoordsFromFocalPlaneCoordsLSST(xf, yf, band='r')
1176 self.assertTrue(np.isnan(xp[2]))
1177 self.assertTrue(np.isnan(yp[2]))
1178 self.assertTrue(np.isnan(xp[1]))
1179 self.assertTrue(np.isnan(yp[1]))
1180 self.assertFalse(np.isnan(xp[0]))
1181 self.assertFalse(np.isnan(yp[0]))
1182 self.assertFalse(np.isnan(xp[3]))
1183 self.assertFalse(np.isnan(yp[3]))
1185 xp, yp = pupilCoordsFromFocalPlaneCoordsLSST(np.NaN, 1.0, band='g')
1186 self.assertTrue(np.isnan(xp))
1187 self.assertTrue(np.isnan(yp))
1189 xp, yp = pupilCoordsFromFocalPlaneCoordsLSST(2.1, np.NaN, band='g')
1190 self.assertTrue(np.isnan(xp))
1191 self.assertTrue(np.isnan(yp))
1193 xp = np.array([0.0011, 0.0021, np.NaN, 0.0045])
1194 yp = np.array([0.0021, np.NaN, 0.0012, 0.0030])
1195 xf, yf = focalPlaneCoordsFromPupilCoordsLSST(xp, yp, band='r')
1196 self.assertTrue(np.isnan(xf[2]))
1197 self.assertTrue(np.isnan(yf[2]))
1198 self.assertTrue(np.isnan(xf[1]))
1199 self.assertTrue(np.isnan(yf[1]))
1200 self.assertFalse(np.isnan(xf[0]))
1201 self.assertFalse(np.isnan(yf[0]))
1202 self.assertFalse(np.isnan(xf[3]))
1203 self.assertFalse(np.isnan(yf[3]))
1205 xf, yf = focalPlaneCoordsFromPupilCoordsLSST(np.NaN, 0.001, band='g')
1206 self.assertTrue(np.isnan(xf))
1207 self.assertTrue(np.isnan(yf))
1209 xf, yf = pupilCoordsFromFocalPlaneCoordsLSST(0.002, np.NaN, band='g')
1210 self.assertTrue(np.isnan(xf))
1211 self.assertTrue(np.isnan(yf))
1214class MemoryTestClass(lsst.utils.tests.MemoryTestCase):
1215 pass
1218if __name__ == "__main__": 1218 ↛ 1219line 1218 didn't jump to line 1219, because the condition on line 1218 was never true
1219 lsst.utils.tests.init()
1220 unittest.main()