Coverage for python/lsst/obs/base/camera_tests.py: 29%

39 statements  

« prev     ^ index     » next       coverage.py v6.4, created at 2022-05-27 11:20 +0000

1# This file is part of obs_base. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <https://www.gnu.org/licenses/>. 

21 

22import abc 

23import collections 

24import math 

25 

26import lsst.geom 

27from lsst.afw.cameraGeom import FIELD_ANGLE, FOCAL_PLANE 

28 

29__all__ = ["CameraTests"] 

30 

31 

32class CameraTests(metaclass=abc.ABCMeta): 

33 """Tests that the butler returns a useable Camera. 

34 

35 In the subclasses's setUp(): 

36 * Call setUp_camera() to fill in required parameters. 

37 """ 

38 

39 def setUp_camera( 

40 self, 

41 camera_name=None, 

42 n_detectors=None, 

43 first_detector_name=None, 

44 plate_scale=None, 

45 ): 

46 """Set up the necessary variables for camera tests. 

47 

48 Parameters 

49 ---------- 

50 

51 camera_name : `str` 

52 name of this camera 

53 n_detectors : `int` 

54 number of detectors in this camera 

55 first_detector_name : `str` 

56 name of the first detector in this camera 

57 plate_scale : `lsst.geom.Angle` 

58 plate scale at center of focal plane, as angle-on-sky/mm 

59 """ 

60 fields = [ 

61 "camera_name", 

62 "n_detectors", 

63 "first_detector_name", 

64 "plate_scale", 

65 ] 

66 CameraData = collections.namedtuple("CameraData", fields) 

67 self.camera_data = CameraData( 

68 camera_name=camera_name, 

69 n_detectors=n_detectors, 

70 first_detector_name=first_detector_name, 

71 plate_scale=plate_scale, 

72 ) 

73 

74 def test_iterable(self): 

75 """Simplest camera test: can we get a Camera instance, and does 

76 iterating return Detectors?""" 

77 camera = self.butler.get("camera", immediate=True) 

78 self.assertIsInstance(camera, lsst.afw.cameraGeom.Camera) 

79 for detector in camera: 

80 msg = "Failed for detector={}".format(detector) 

81 self.assertIsInstance(detector, lsst.afw.cameraGeom.Detector, msg=msg) 

82 

83 def test_camera_butler(self): 

84 """Check that the butler returns the right type of camera.""" 

85 camera = self.butler.get("camera", immediate=True) 

86 self.assertEqual(camera.getName(), self.camera_data.camera_name) 

87 self.assertEqual(len(camera), self.camera_data.n_detectors) 

88 self.assertEqual(next(iter(camera)).getName(), self.camera_data.first_detector_name) 

89 

90 def test_plate_scale(self): 

91 """Check the plate scale at center of focal plane 

92 

93 Check plate_scale using the FOCAL_PLANE to FIELD_ANGLE transform 

94 from the camera. 

95 """ 

96 plate_scale = self.camera_data.plate_scale 

97 self.assertIsNotNone(plate_scale) 

98 camera = self.butler.get("camera", immediate=True) 

99 focalPlaneToFieldAngle = camera.getTransformMap().getTransform(FOCAL_PLANE, FIELD_ANGLE) 

100 focalPlaneRadiusMm = 0.001 # an offset small enough to be in the linear regime 

101 for offsetAngleRad in (0.0, 0.65, 1.3): # direction of offset; a few arbitrary angles 

102 cosAng = math.cos(offsetAngleRad) 

103 sinAng = math.sin(offsetAngleRad) 

104 fieldAngleRadians = focalPlaneToFieldAngle.applyForward( 

105 lsst.geom.Point2D(cosAng * focalPlaneRadiusMm, sinAng * focalPlaneRadiusMm) 

106 ) 

107 fieldAngleRadius = math.hypot(*fieldAngleRadians) * lsst.geom.radians 

108 measuredScale1 = fieldAngleRadius / focalPlaneRadiusMm 

109 self.assertAnglesAlmostEqual(measuredScale1, plate_scale) 

110 

111 focalPlanePos = focalPlaneToFieldAngle.applyInverse( 

112 lsst.geom.Point2D( 

113 fieldAngleRadius.asRadians() * cosAng, fieldAngleRadius.asRadians() * sinAng 

114 ) 

115 ) 

116 focalPlaneRadiusMm2 = math.hypot(*focalPlanePos) 

117 measureScale2 = fieldAngleRadius / focalPlaneRadiusMm2 

118 self.assertAnglesAlmostEqual(measureScale2, plate_scale)