Coverage for tests/test_calibrate.py: 30%

88 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2022-07-15 03:31 -0700

1# This file is part of pipe_tasks. 

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 

22"""Test ProcessCcdTask and its immediate subtasks. 

23""" 

24import shutil 

25import tempfile 

26import unittest 

27 

28import lsst.utils.tests 

29import lsst.afw.image 

30import lsst.afw.math 

31import lsst.afw.table 

32import lsst.daf.butler.tests as butlerTests 

33from lsst.pipe.base import testUtils 

34from lsst.pipe.tasks.calibrate import CalibrateTask, CalibrateConfig 

35 

36 

37class CalibrateTaskTestCaseWithButler(lsst.utils.tests.TestCase): 

38 

39 @classmethod 

40 def _makeTestRepo(cls, root): 

41 """Create a repository with the metadata assumed by CalibrateTask. 

42 """ 

43 # In-memory for performance 

44 config = lsst.daf.butler.Config() 

45 config["datastore", "cls"] = "lsst.daf.butler.datastores.inMemoryDatastore.InMemoryDatastore" 

46 config["datastore", "checksum"] = False 

47 config["registry", "db"] = "sqlite:///:memory:" 

48 

49 butler = lsst.daf.butler.Butler(lsst.daf.butler.Butler.makeRepo(root, config=config), writeable=True) 

50 butler.registry.insertDimensionData( 

51 "instrument", 

52 {"name": "notACam", "visit_max": 256, "exposure_max": 256, "detector_max": 64}) 

53 butler.registry.insertDimensionData( 

54 "physical_filter", 

55 {"instrument": "notACam", "name": "r", "band": "r"}, 

56 ) 

57 butler.registry.insertDimensionData( 

58 "visit", 

59 {"instrument": "notACam", "id": 101, "name": "101", "physical_filter": "r"}, 

60 ) 

61 butler.registry.insertDimensionData("detector", 

62 {"instrument": "notACam", "id": 42, "full_name": "42"}) 

63 return butler 

64 

65 @classmethod 

66 def setUpClass(cls): 

67 super().setUpClass() 

68 

69 cls.root = tempfile.mkdtemp() 

70 cls.repo = cls._makeTestRepo(cls.root) 

71 

72 butlerTests.addDatasetType( 

73 cls.repo, "icExp", {"instrument", "visit", "detector"}, 

74 "ExposureF") 

75 butlerTests.addDatasetType( 

76 cls.repo, "icExpBackground", {"instrument", "visit", "detector"}, 

77 "Background") 

78 butlerTests.addDatasetType( 

79 cls.repo, "icSrc", {"instrument", "visit", "detector"}, 

80 "SourceCatalog") 

81 butlerTests.addDatasetType( 

82 cls.repo, "cal_ref_cat", {"htm7"}, 

83 "SimpleCatalog") 

84 butlerTests.addDatasetType( 

85 cls.repo, "calexp", {"instrument", "visit", "detector"}, 

86 "ExposureF") 

87 butlerTests.addDatasetType( 

88 cls.repo, "src", {"instrument", "visit", "detector"}, 

89 "SourceCatalog") 

90 butlerTests.addDatasetType( 

91 cls.repo, "calexpBackground", {"instrument", "visit", "detector"}, 

92 "Background") 

93 butlerTests.addDatasetType( 

94 cls.repo, "srcMatch", {"instrument", "visit", "detector"}, 

95 "Catalog") 

96 butlerTests.addDatasetType( 

97 cls.repo, "srcMatchFull", {"instrument", "visit", "detector"}, 

98 "Catalog") 

99 

100 @classmethod 

101 def tearDownClass(cls): 

102 shutil.rmtree(cls.root, ignore_errors=True) 

103 super().tearDownClass() 

104 

105 def setUp(self): 

106 super().setUp() 

107 self.butler = butlerTests.makeTestCollection(self.repo) 

108 

109 self.dataId = {"instrument": "notACam", "visit": 101, "detector": 42} 

110 # CalibrateTask absolutely requires an ExpandedDataCoordinate 

111 self.dataId = self.butler.registry.expandDataId(self.dataId) 

112 self.refcatId = {"htm7": 189584} 

113 

114 # Tests do no processing, so we don't need real data 

115 self.exposure = lsst.afw.image.ExposureF(10, 10) 

116 background = lsst.afw.math.BackgroundMI(self.exposure.getBBox(), self.exposure.getMaskedImage()) 

117 self.backgroundlist = lsst.afw.math.BackgroundList( 

118 (background, lsst.afw.math.Interpolate.UNKNOWN, lsst.afw.math.UndersampleStyle.THROW_EXCEPTION, 

119 lsst.afw.math.ApproximateControl.UNKNOWN, 0, 0, 1)) 

120 self.icSrc = lsst.afw.table.SourceCatalog() 

121 self.refcat = lsst.afw.table.SimpleCatalog() 

122 

123 self.butler.put(self.exposure, "icExp", self.dataId) 

124 self.butler.put(self.backgroundlist, "icExpBackground", self.dataId) 

125 self.butler.put(self.icSrc, "icSrc", self.dataId) 

126 self.butler.put(self.refcat, "cal_ref_cat", self.refcatId) 

127 

128 def testDoAstrometry(self): 

129 """Ensure correct inputs passed to run whether or not doAstrometry 

130 is set. 

131 """ 

132 allIds = {key: self.dataId for key in { 

133 "exposure", "background", "icSourceCat", "outputExposure", "outputCat", "outputBackground", 

134 "matches", "matchesDenormalized" 

135 }} 

136 allIds.update({key: [self.refcatId] for key in {"astromRefCat", "photoRefCat"}}) 

137 

138 self._checkDoRefcats(doAstrometry=True, doPhotoCal=True, ids=allIds) 

139 self._checkDoRefcats(doAstrometry=False, doPhotoCal=True, ids=allIds) 

140 

141 def testDoPhotoCal(self): 

142 """Ensure correct inputs passed to run whether or not doPhotoCal 

143 is set. 

144 """ 

145 allIds = {key: self.dataId for key in { 

146 "exposure", "background", "icSourceCat", "outputExposure", "outputCat", "outputBackground", 

147 "matches", "matchesDenormalized" 

148 }} 

149 allIds.update({key: [self.refcatId] for key in {"astromRefCat", "photoRefCat"}}) 

150 

151 self._checkDoRefcats(doAstrometry=True, doPhotoCal=True, ids=allIds) 

152 self._checkDoRefcats(doAstrometry=True, doPhotoCal=False, ids=allIds) 

153 

154 def _checkDoRefcats(self, doAstrometry, doPhotoCal, ids): 

155 """Test whether run is called with the correct arguments. 

156 

157 In the case of `CalibrateTask`, the inputs should not depend on the 

158 task configuration. 

159 

160 Parameters 

161 ---------- 

162 doAstrometry, doPhotoCal : `bool` 

163 Values of the config flags of the same name. 

164 ids : `dict` [`str`] 

165 A mapping from the input dataset type to the data ID of the 

166 dataset to process. 

167 """ 

168 config = CalibrateConfig() 

169 config.doWriteMatches = False # no real output to write 

170 config.doAstrometry = doAstrometry 

171 config.doPhotoCal = doPhotoCal 

172 config.connections.photoRefCat = "cal_ref_cat" 

173 config.connections.astromRefCat = "cal_ref_cat" 

174 task = CalibrateTask(config=config) 

175 quantumId = ids["exposure"] 

176 

177 quantum = testUtils.makeQuantum(task, self.butler, quantumId, ids) 

178 run = testUtils.runTestQuantum(task, self.butler, quantum) 

179 

180 run.assert_called_once() 

181 self.assertEqual(run.call_args[0], ()) 

182 # Some arguments unprintable because we don't have a full environment 

183 # So just check which ones were passed in 

184 self.assertEqual(run.call_args[1].keys(), 

185 {"exposure", "exposureIdInfo", "background", "icSourceCat"}) 

186 

187 

188def setup_module(module): 

189 lsst.utils.tests.init() 

190 

191 

192class MemoryTestCase(lsst.utils.tests.MemoryTestCase): 

193 pass 

194 

195 

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

197 lsst.utils.tests.init() 

198 unittest.main()