Coverage for tests/test_cameraGeom.py: 24%

Shortcuts 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

50 statements  

1# This file is part of jointcal. 

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 os.path 

23 

24import lsst.utils 

25 

26from lsst.afw.geom import SkyWcs 

27import lsst.afw.cameraGeom 

28import lsst.jointcal.cameraGeometry 

29import lsst.obs.hsc 

30 

31 

32class TestCameraGeom(lsst.utils.tests.TestCase): 

33 """Test jointcal's cameraGeom code on data from a jointcal HSC run. 

34 """ 

35 def setUp(self): 

36 path = os.path.join(os.path.dirname(__file__), "data/output/HSC-R/9615/") 

37 # Two WCS from the same visit, which should produce near identical results. 

38 # 49 is near the center of the focal plane 

39 self.detector1 = 49 

40 # 37 is on the west side of the focal plane 

41 self.detector2 = 37 

42 # 103 is on the NW edge of the focal plane and rotated 90 degrees 

43 self.detector3 = 103 

44 # 90 is on the NE corner of the focal plane 

45 self.detector4 = 90 

46 # a selection of WCSs to compare the calculations on 

47 self.wcs1 = SkyWcs.readFits(os.path.join(path, f"jointcal_wcs-0028976-{self.detector1:03}.fits")) 

48 self.wcs2 = SkyWcs.readFits(os.path.join(path, f"jointcal_wcs-0028976-{self.detector2:03}.fits")) 

49 wcs3 = SkyWcs.readFits(os.path.join(path, f"jointcal_wcs-0023924-{self.detector3:03}.fits")) 

50 wcs4 = SkyWcs.readFits(os.path.join(path, f"jointcal_wcs-0023900-{self.detector4:03}.fits")) 

51 self.wcsList = [self.wcs1, self.wcs2, wcs3, wcs4] 

52 self.detectors = [self.detector1, self.detector2, self.detector3, self.detector4] 

53 

54 cameraPath = os.path.join(lsst.utils.getPackageDir("obs_subaru"), "hsc/camera") 

55 cameraConfig = lsst.afw.cameraGeom.CameraConfig() 

56 cameraConfig.load(os.path.join(cameraPath, "camera.py")) 

57 self.camera = lsst.afw.cameraGeom.makeCameraFromPath(cameraConfig, cameraPath, lambda x: x, 

58 lsst.obs.hsc.HscPupilFactory) 

59 self.maxFocalPlaneRadius = self.camera.computeMaxFocalPlaneRadius() 

60 

61 def testComputeDetectorPixelScale(self): 

62 """Test CameraModel._computeDetectorPixelScale by comparing two 

63 detectors from the same visit: they should have near identical pixel 

64 scale variation. 

65 """ 

66 # don't need the wcs or detector lists for this test 

67 model = lsst.jointcal.cameraGeometry.CameraModel([], [], self.camera) 

68 angle1, radial1, tangential1 = model._computeDetectorPixelScale(self.detector1, 

69 self.wcs1) 

70 angle2, radial2, tangential2 = model._computeDetectorPixelScale(self.detector2, 

71 self.wcs2) 

72 # The angles really should be identical: this value is independent of distortion. 

73 self.assertFloatsEqual(angle1, angle2) 

74 # These should be identical, but we allow for machine-precision errors 

75 # due to possible complexity in the distortion model. 

76 self.assertFloatsAlmostEqual(radial1, radial2) 

77 self.assertFloatsAlmostEqual(tangential1, tangential2) 

78 # Check that the HSC pixel scale is approximately correct at the boresight. 

79 self.assertFloatsAlmostEqual(radial1[0], 0.168, rtol=1e-2) 

80 self.assertFloatsAlmostEqual(tangential1[0], 0.168, rtol=1e-2) 

81 

82 def testComputeCameraPixelScale(self): 

83 """Test CameraModel.computeCameraPixelScale by comparing two 

84 detectors: they should have near identical pixel scale variation. 

85 """ 

86 # don't need the wcs or detector lists for this test 

87 model = lsst.jointcal.cameraGeometry.CameraModel([], [], self.camera) 

88 angle1, radial1, tangential1 = model.computeCameraPixelScale(self.detector1) 

89 angle2, radial2, tangential2 = model.computeCameraPixelScale(self.detector2) 

90 # For the camera calculation, there can be machine-precision 

91 # differences between different detectors, so "almost" here. 

92 self.assertFloatsAlmostEqual(angle1, angle2) 

93 self.assertFloatsAlmostEqual(radial1, radial2) 

94 self.assertFloatsAlmostEqual(tangential1, tangential2) 

95 # Check that the HSC pixel scale is approximately correct at the boresight. 

96 self.assertFloatsAlmostEqual(radial1[0], 0.168, rtol=1e-3) 

97 self.assertFloatsAlmostEqual(tangential1[0], 0.168, rtol=1e-3) 

98 

99 def testComputePixelScale(self): 

100 """Test that the pixel scale calculation produces something sensible. 

101 """ 

102 model = lsst.jointcal.cameraGeometry.CameraModel(self.wcsList, self.detectors, self.camera) 

103 model.computePixelScale() 

104 angle2, radial2, tangential2 = model._computeDetectorPixelScale(self.detector2, 

105 self.wcs2) 

106 # TOOD: If we ever go with a more careful approach to the mean 

107 # fieldAngle question, this may have to change. 

108 self.assertFloatsAlmostEqual(model.fieldAngle, angle2, rtol=1e-4) 

109 

110 # spot check the second array elements 

111 self.assertFloatsEqual(model.fieldAngles[1], angle2) 

112 self.assertFloatsEqual(model.radialScales[1], radial2) 

113 self.assertFloatsEqual(model.tangentialScales[1], tangential2)