Coverage for tests/test_cameraGeom.py: 23%

48 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-02-23 12:54 +0000

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 

29from lsst.obs.subaru import HyperSuprimeCam 

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 hsc = HyperSuprimeCam() 

55 self.camera = hsc.getCamera() 

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

57 

58 def testComputeDetectorPixelScale(self): 

59 """Test CameraModel._computeDetectorPixelScale by comparing two 

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

61 scale variation. 

62 """ 

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

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

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

66 self.wcs1) 

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

68 self.wcs2) 

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

70 self.assertFloatsEqual(angle1, angle2) 

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

72 # due to possible complexity in the distortion model. 

73 self.assertFloatsAlmostEqual(radial1, radial2) 

74 self.assertFloatsAlmostEqual(tangential1, tangential2) 

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

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

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

78 

79 def testComputeCameraPixelScale(self): 

80 """Test CameraModel.computeCameraPixelScale by comparing two 

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

82 """ 

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

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

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

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

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

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

89 self.assertFloatsAlmostEqual(angle1, angle2) 

90 self.assertFloatsAlmostEqual(radial1, radial2) 

91 self.assertFloatsAlmostEqual(tangential1, tangential2) 

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

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

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

95 

96 def testComputePixelScale(self): 

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

98 """ 

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

100 model.computePixelScale() 

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

102 self.wcs2) 

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

104 # fieldAngle question, this may have to change. 

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

106 

107 # spot check the second array elements 

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

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

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