Coverage for python/lsst/obs/base/butler_tests.py: 21%

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

78 statements  

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 inspect 

25import unittest 

26 

27__all__ = ["ButlerGetTests"] 

28 

29 

30class ButlerGetTests(metaclass=abc.ABCMeta): 

31 """Tests of obs_* Butler get() functionality. 

32 

33 In the subclasses's setUp(): 

34 * Call setUp_butler_get() to fill in required parameters. 

35 """ 

36 

37 def setUp_butler_get( 

38 self, 

39 ccdExposureId_bits=None, 

40 exposureIds=None, 

41 filters=None, 

42 exptimes=None, 

43 detectorIds=None, 

44 detector_names=None, 

45 detector_serials=None, 

46 dimensions=None, 

47 sky_origin=None, 

48 raw_subsets=None, 

49 good_detectorIds=None, 

50 bad_detectorIds=None, 

51 linearizer_type=None, 

52 raw_header_wcs=None, 

53 ): 

54 """ 

55 Set up the necessary variables for butlerGet tests. 

56 

57 All "exposure name" entries below should correspond to an entry in 

58 self.dataIds. 

59 

60 Parameters 

61 ---------- 

62 

63 ccdExposureId_bits : `int` 

64 expected value of ccdExposureId_bits 

65 exposureIds : `dict` 

66 dict of exposure name : ccdExposureId (the number as returned by 

67 the butler) 

68 filters : `dict` 

69 dict of exposure name : filter name 

70 exptimes : `dict` 

71 dict of exposure name : exposure time 

72 detector_names : `dict` 

73 dict of exposure name : detector name 

74 detectorIds : `dict` 

75 dict of exposure name : detectorId 

76 detector_serials : `dict` 

77 dict of exposure name : detector serial 

78 dimensions : `dict` 

79 dict of exposure name : dimensions (as a geom.Extent2I) 

80 sky_origin : `tuple` of `float` 

81 Longitude, Latitude of 'raw' exposure 

82 raw_subsets : `tuple` of (kwargs, `int`) 

83 keyword args and expected number of subsets for 

84 ``butler.subset('raw', **kwargs)`` 

85 good_detectorIds : `list` of `int` 

86 list of valid ccd numbers 

87 bad_detectorIds : `list` of `int` 

88 list of invalid ccd numbers 

89 linearizer_type : `dict` 

90 dict of detectorId (usually `int`): LinearizerType 

91 (e.g. lsst.ip.isr.LinearizeLookupTable.LinearityType), 

92 or unittest.SkipTest to skip all linearizer tests. 

93 raw_header_wcs : `lsst.afw.geom.SkyWcs` 

94 The SkyWcs object that should be returned by 

95 ``butler.get("raw_header_wcs", dataId=self.dataIds["raw"])`` 

96 """ 

97 

98 fields = [ 

99 "ccdExposureId_bits", 

100 "exposureIds", 

101 "filters", 

102 "exptimes", 

103 "detector_names", 

104 "detectorIds", 

105 "detector_serials", 

106 "dimensions", 

107 "sky_origin", 

108 "raw_subsets", 

109 "good_detectorIds", 

110 "bad_detectorIds", 

111 "linearizer_type", 

112 "raw_header_wcs", 

113 ] 

114 ButlerGet = collections.namedtuple("ButlerGetData", fields) 

115 

116 self.butler_get_data = ButlerGet( 

117 ccdExposureId_bits=ccdExposureId_bits, 

118 exposureIds=exposureIds, 

119 filters=filters, 

120 exptimes=exptimes, 

121 detectorIds=detectorIds, 

122 detector_names=detector_names, 

123 detector_serials=detector_serials, 

124 dimensions=dimensions, 

125 sky_origin=sky_origin, 

126 raw_subsets=raw_subsets, 

127 good_detectorIds=good_detectorIds, 

128 bad_detectorIds=bad_detectorIds, 

129 linearizer_type=linearizer_type, 

130 raw_header_wcs=raw_header_wcs, 

131 ) 

132 

133 def test_exposureId_bits(self): 

134 bits = self.butler.get("ccdExposureId_bits") 

135 self.assertEqual(bits, self.butler_get_data.ccdExposureId_bits) 

136 

137 def _test_exposure(self, name): 

138 if self.dataIds[name] is unittest.SkipTest: 

139 self.skipTest("Skipping %s as requested" % (inspect.currentframe().f_code.co_name)) 

140 exp = self.butler.get(name, self.dataIds[name]) 

141 

142 exp_md = self.butler.get(name + "_md", self.dataIds[name]) 

143 self.assertEqual(type(exp_md), type(exp.getMetadata())) 

144 

145 self.assertEqual(exp.getDimensions(), self.butler_get_data.dimensions[name]) 

146 self.assertEqual(exp.getDetector().getId(), self.butler_get_data.detectorIds[name]) 

147 self.assertEqual(exp.getDetector().getName(), self.butler_get_data.detector_names[name]) 

148 self.assertEqual(exp.getDetector().getSerial(), self.butler_get_data.detector_serials[name]) 

149 # obs_test does not have physical filters, so include a fallback 

150 exposureFilter = exp.getFilterLabel() 

151 if exposureFilter: 

152 if exposureFilter.hasPhysicalLabel(): 

153 filterName = exposureFilter.physicalLabel 

154 else: 

155 filterName = exposureFilter.bandLabel 

156 else: 

157 filterName = "_unknown_" 

158 self.assertEqual(filterName, self.butler_get_data.filters[name]) 

159 exposureId = self.butler.get("ccdExposureId", dataId=self.dataIds[name]) 

160 self.assertEqual(exposureId, self.butler_get_data.exposureIds[name]) 

161 self.assertEqual(exp.getInfo().getVisitInfo().getExposureTime(), self.butler_get_data.exptimes[name]) 

162 return exp 

163 

164 def test_raw(self): 

165 exp = self._test_exposure("raw") 

166 # We only test the existence of WCS in the raw files, since it's only 

167 # well-defined for raw, and other exposure types could have or not 

168 # have a WCS depending on various implementation details. 

169 # Even for raw, there are data that do not have a WCS, e.g. teststand 

170 # data 

171 if self.butler_get_data.sky_origin is not unittest.SkipTest: 

172 self.assertEqual(exp.hasWcs(), True) 

173 origin = exp.getWcs().getSkyOrigin() 

174 self.assertAlmostEqual(origin.getLongitude().asDegrees(), self.butler_get_data.sky_origin[0]) 

175 self.assertAlmostEqual(origin.getLatitude().asDegrees(), self.butler_get_data.sky_origin[1]) 

176 

177 def test_bias(self): 

178 self._test_exposure("bias") 

179 

180 def test_dark(self): 

181 self._test_exposure("dark") 

182 

183 def test_flat(self): 

184 self._test_exposure("flat") 

185 

186 def test_raw_header_wcs(self): 

187 """Test that `raw_header_wcs` returns the unmodified header of the raw 

188 image.""" 

189 if self.butler_get_data.raw_header_wcs is not None: 

190 wcs = self.butler.get("raw_header_wcs", self.dataIds["raw"]) 

191 self.assertEqual(wcs, self.butler_get_data.raw_header_wcs) 

192 

193 @unittest.skip("Cannot test this, as there is a bug in the butler! DM-8097") 

194 def test_raw_sub_bbox(self): 

195 exp = self.butler.get("raw", self.dataIds["raw"], immediate=True) 

196 bbox = exp.getBBox() 

197 bbox.grow(-1) 

198 sub = self.butler.get("raw_sub", self.dataIds["raw"], bbox=bbox, immediate=True) 

199 self.assertEqual(sub.getImage().getBBox(), bbox) 

200 self.assertImagesEqual(sub, exp.Factory(exp, bbox)) 

201 

202 def test_subset_raw(self): 

203 for kwargs, expect in self.butler_get_data.raw_subsets: 

204 subset = self.butler.subset("raw", **kwargs) 

205 self.assertEqual(len(subset), expect, msg="Failed for kwargs: {}".format(kwargs)) 

206 

207 def test_get_linearizer(self): 

208 """Test that we can get a linearizer for good detectorIds.""" 

209 if self.butler_get_data.linearizer_type is unittest.SkipTest: 

210 self.skipTest("Skipping %s as requested" % (inspect.currentframe().f_code.co_name)) 

211 

212 camera = self.butler.get("camera") 

213 for detectorId in self.butler_get_data.good_detectorIds: 

214 detector = camera[detectorId] 

215 linearizer = self.butler.get("linearizer", dataId=dict(ccd=detectorId), immediate=True) 

216 self.assertEqual(linearizer.LinearityType, self.butler_get_data.linearizer_type[detectorId]) 

217 linearizer.checkDetector(detector) 

218 

219 def test_get_linearizer_bad_detectorIds(self): 

220 """Do bad detectorIds raise?""" 

221 if self.butler_get_data.linearizer_type is unittest.SkipTest: 

222 self.skipTest("Skipping %s as requested" % (inspect.currentframe().f_code.co_name)) 

223 

224 for badccd in self.butler_get_data.bad_detectorIds: 

225 with self.assertRaises(RuntimeError): 

226 self.butler.get("linearizer", dataId=dict(ccd=badccd), immediate=True)