Coverage for tests/test_focalPlaneProjector.py: 25%

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

85 statements  

1# See COPYRIGHT file at the top of the source tree. 

2# 

3# This file is part of fgcmcal. 

4# 

5# Developed for the LSST Data Management System. 

6# This product includes software developed by the LSST Project 

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

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

9# for details of code ownership. 

10# 

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

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

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

14# (at your option) any later version. 

15# 

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

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

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

19# GNU General Public License for more details. 

20# 

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

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

23"""Test the fgcmcal FocalPlaneProjector code with testdata_jointcal/hsc. 

24""" 

25import unittest 

26import os 

27import tempfile 

28import numpy as np 

29import warnings 

30 

31import lsst.utils 

32import lsst.daf.butler as dafButler 

33import lsst.fgcmcal as fgcmcal 

34 

35import fgcmcalTestBase 

36 

37 

38ROOT = os.path.abspath(os.path.dirname(__file__)) 

39 

40 

41class FgcmFocalPlaneProjectorTestHsc(fgcmcalTestBase.FgcmcalTestBase, lsst.utils.tests.TestCase): 

42 @classmethod 

43 def setUpClass(cls): 

44 try: 

45 cls.dataDir = lsst.utils.getPackageDir('testdata_jointcal') 

46 except LookupError: 

47 raise unittest.SkipTest('testdata_jointcal not setup.') 

48 try: 

49 lsst.utils.getPackageDir('obs_subaru') 

50 except LookupError: 

51 raise unittest.SkipTest("obs_subaru not setup") 

52 

53 cls.testDir = tempfile.mkdtemp(dir=ROOT, prefix="TestFgcm-") 

54 

55 cls._importRepository('lsst.obs.subaru.HyperSuprimeCam', 

56 os.path.join(cls.dataDir, 'hsc'), 

57 os.path.join(cls.dataDir, 'hsc', 'exports.yaml')) 

58 

59 def test_focalPlaneProjector(self): 

60 """ 

61 Test focal plane projector code for HSC. 

62 """ 

63 butler = dafButler.Butler(os.path.join(self.testDir, 'testrepo'), 

64 instrument='HSC', 

65 collections=['HSC/calib/unbounded', 'HSC/testdata']) 

66 camera = butler.get('camera', instrument='HSC') 

67 

68 visit = 36236 

69 detector = 87 

70 

71 visitInfo = butler.get('calexp.visitInfo', visit=visit, detector=detector) 

72 wcs = butler.get('calexp.wcs', visit=visit, detector=detector) 

73 rotAngle = visitInfo.getBoresightRotAngle().asDegrees() 

74 

75 defaultRotation = 270.0 

76 self.assertAlmostEqual(rotAngle, defaultRotation) 

77 

78 focalPlaneProjector = fgcmcal.FocalPlaneProjector(camera, defaultRotation) 

79 self.assertAlmostEqual(focalPlaneProjector.defaultOrientation, defaultRotation) 

80 

81 focalPlaneProjector2 = fgcmcal.FocalPlaneProjector(camera, -90.0) 

82 self.assertAlmostEqual(focalPlaneProjector2.defaultOrientation, defaultRotation) 

83 

84 # Load a delta mapper at the default angle 

85 deltaMapper = focalPlaneProjector(int(defaultRotation)) 

86 

87 # Spot check relative orientations of some of the ccds 

88 # This is based on 

89 # https://subarutelescope.org/Observing/Instruments/HSC/CCDPosition_20170212.png 

90 # The goal here is to check that North is Up, South is Down, 

91 # East is Left, and West is Right. 

92 self.assertLess(deltaMapper['delta_ra_cent'][15], deltaMapper['delta_ra_cent'][10]) 

93 self.assertLess(deltaMapper['delta_ra_cent'][95], deltaMapper['delta_ra_cent'][90]) 

94 self.assertGreater(deltaMapper['delta_ra_cent'][46], 0.0) 

95 

96 # Check that loading at NaN gives the same default (with a warning) 

97 self.assertWarns(UserWarning, focalPlaneProjector, np.nan) 

98 with warnings.catch_warnings(): 

99 warnings.simplefilter('ignore') 

100 deltaMapperDefault = focalPlaneProjector(np.nan) 

101 

102 np.testing.assert_array_almost_equal(deltaMapperDefault['delta_ra_cent'], 

103 deltaMapper['delta_ra_cent']) 

104 np.testing.assert_array_almost_equal(deltaMapperDefault['delta_dec_cent'], 

105 deltaMapper['delta_dec_cent']) 

106 

107 # Compare the ra/dec to x/y mapping for the one detector from the wcs. 

108 wcsRa, wcsDec = wcs.pixelToSkyArray(deltaMapper['x'][detector, :], 

109 deltaMapper['y'][detector, :], 

110 degrees=True) 

111 boresightRa = visitInfo.getBoresightRaDec().getRa().asDegrees() 

112 boresightDec = visitInfo.getBoresightRaDec().getDec().asDegrees() 

113 

114 wcsDeltaRa = (wcsRa - boresightRa)*np.cos(np.deg2rad(boresightDec)) 

115 wcsDeltaDec = wcsDec - boresightDec 

116 

117 meanDeltaRa = np.mean(wcsDeltaRa - deltaMapper['delta_ra'][detector, :]) 

118 meanDeltaDec = np.mean(wcsDeltaDec - deltaMapper['delta_dec'][detector, :]) 

119 

120 # Check that these offsets are reasonable (they will not be zero 

121 # because the boresight is not updated after the WCS is fit...) 

122 self.assertLess(np.abs(meanDeltaRa), 0.002) 

123 self.assertLess(np.abs(meanDeltaDec), 0.002) 

124 

125 self.assertLess(np.abs(wcsDeltaRa - deltaMapper['delta_ra'][detector, :] - meanDeltaRa).max(), 

126 0.0005) 

127 self.assertLess(np.abs(wcsDeltaDec - deltaMapper['delta_dec'][detector, :] - meanDeltaDec).max(), 

128 0.0005) 

129 

130 # Check the sizes 

131 # The projected size of the ccds varies with radius over the large 

132 # HSC field-of-view. Empirically, the x size is between 0.07 and 0.10 deg 

133 # and the y size is between 0.17 and 0.20 deg for the non-rotated CCDs. 

134 # This test checks that the orientations of the CCDs are as expected for 

135 # rotated/non-rotated CCDs (relative size of RA/DEC), and that the size 

136 # is roughly correct. 

137 

138 rotatedDetectors = [100, 101, 102, 103] 

139 

140 for i, detectorId in enumerate(deltaMapper['id']): 

141 ra_size = np.max(deltaMapper['delta_ra'][i, :]) - np.min(deltaMapper['delta_ra'][i, :]) 

142 dec_size = np.max(deltaMapper['delta_dec'][i, :]) - np.min(deltaMapper['delta_dec'][i, :]) 

143 if detectorId in rotatedDetectors: 

144 self.assertLess(ra_size, dec_size) 

145 self.assertGreater(dec_size, 0.17) 

146 self.assertLess(dec_size, 0.20) 

147 self.assertGreater(ra_size, 0.07) 

148 self.assertLess(ra_size, 0.10) 

149 else: 

150 self.assertGreater(ra_size, dec_size) 

151 self.assertGreater(ra_size, 0.17) 

152 self.assertLess(ra_size, 0.20) 

153 self.assertGreater(dec_size, 0.07) 

154 self.assertLess(dec_size, 0.10) 

155 

156 # And spin it around, testing the reverse of the test above. 

157 deltaMapperRot = focalPlaneProjector(defaultRotation + 180.0) 

158 self.assertGreater(deltaMapperRot['delta_ra_cent'][15], deltaMapperRot['delta_ra_cent'][10]) 

159 self.assertGreater(deltaMapperRot['delta_ra_cent'][95], deltaMapperRot['delta_ra_cent'][90]) 

160 self.assertLess(deltaMapperRot['delta_ra_cent'][46], 0.0) 

161 

162 

163class TestMemory(lsst.utils.tests.MemoryTestCase): 

164 pass 

165 

166 

167def setup_module(module): 

168 lsst.utils.tests.init() 

169 

170 

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

172 lsst.utils.tests.init() 

173 unittest.main()