Coverage for tests/test_testPipeline.py: 19%

159 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-12-23 09:59 +0000

1# 

2# This file is part of ap_verify. 

3# 

4# Developed for the LSST Data Management System. 

5# This product includes software developed by the LSST Project 

6# (http://www.lsst.org). 

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

8# for details of code ownership. 

9# 

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

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

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

13# (at your option) any later version. 

14# 

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

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

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

18# GNU General Public License for more details. 

19# 

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

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

22# 

23 

24import shutil 

25import tempfile 

26import unittest 

27 

28import pandas 

29 

30import lsst.utils.tests 

31import lsst.geom 

32import lsst.afw.image as afwImage 

33import lsst.afw.math as afwMath 

34import lsst.afw.table as afwTable 

35import lsst.skymap 

36import lsst.daf.butler.tests as butlerTests 

37import lsst.pipe.base.testUtils as pipelineTests 

38from lsst.ap.verify.testPipeline import MockIsrTask, MockCharacterizeImageTask, \ 

39 MockCalibrateTask, MockGetTemplateTask, \ 

40 MockAlardLuptonSubtractTask, MockDetectAndMeasureTask, MockTransformDiaSourceCatalogTask, \ 

41 MockDiaPipelineTask 

42 

43 

44class MockTaskTestSuite(unittest.TestCase): 

45 """Test that mock tasks have the correct inputs and outputs for the task 

46 they are replacing. 

47 

48 These tests assume that the mock tasks use real config and connection 

49 classes, and therefore out-of-date mocks won't match their connections. 

50 """ 

51 

52 @classmethod 

53 def setUpClass(cls): 

54 super().setUpClass() 

55 

56 repoDir = tempfile.mkdtemp() 

57 cls.addClassCleanup(shutil.rmtree, repoDir, ignore_errors=True) 

58 cls.repo = butlerTests.makeTestRepo(repoDir) 

59 

60 INSTRUMENT = "notACam" 

61 VISIT = 42 

62 CCD = 101 

63 HTM = 42 

64 SKYMAP = "TreasureMap" 

65 TRACT = 28 

66 PATCH = 4 

67 BAND = 'k' 

68 PHYSICAL = 'k2022' 

69 SUB_FILTER = 9 

70 # Mock instrument by hand, because some tasks care about parameters 

71 instrumentRecord = cls.repo.registry.dimensions["instrument"].RecordClass( 

72 name=INSTRUMENT, visit_max=256, exposure_max=256, detector_max=128) 

73 cls.repo.registry.syncDimensionData("instrument", instrumentRecord) 

74 butlerTests.addDataIdValue(cls.repo, "physical_filter", PHYSICAL, band=BAND) 

75 butlerTests.addDataIdValue(cls.repo, "subfilter", SUB_FILTER) 

76 butlerTests.addDataIdValue(cls.repo, "exposure", VISIT) 

77 butlerTests.addDataIdValue(cls.repo, "visit", VISIT) 

78 butlerTests.addDataIdValue(cls.repo, "detector", CCD) 

79 butlerTests.addDataIdValue(cls.repo, "skymap", SKYMAP) 

80 butlerTests.addDataIdValue(cls.repo, "tract", TRACT) 

81 butlerTests.addDataIdValue(cls.repo, "patch", PATCH) 

82 

83 cls.exposureId = cls.repo.registry.expandDataId( 

84 {"instrument": INSTRUMENT, "exposure": VISIT, "detector": CCD}) 

85 cls.visitId = cls.repo.registry.expandDataId( 

86 {"instrument": INSTRUMENT, "visit": VISIT, "detector": CCD}) 

87 cls.visitOnlyId = cls.repo.registry.expandDataId( 

88 {"instrument": INSTRUMENT, "visit": VISIT}) 

89 cls.skymapId = cls.repo.registry.expandDataId({"skymap": SKYMAP}) 

90 cls.skymapVisitId = cls.repo.registry.expandDataId( 

91 {"instrument": INSTRUMENT, "visit": VISIT, "detector": CCD, "skymap": SKYMAP}) 

92 cls.patchId = cls.repo.registry.expandDataId( 

93 {"skymap": SKYMAP, "tract": TRACT, "patch": PATCH, "band": BAND}) 

94 cls.subfilterId = cls.repo.registry.expandDataId( 

95 {"skymap": SKYMAP, "tract": TRACT, "patch": PATCH, "band": BAND, "subfilter": SUB_FILTER}) 

96 cls.htmId = cls.repo.registry.expandDataId({"htm7": HTM}) 

97 

98 butlerTests.addDatasetType(cls.repo, "postISRCCD", cls.exposureId.keys(), "Exposure") 

99 butlerTests.addDatasetType(cls.repo, "icExp", cls.visitId.keys(), "ExposureF") 

100 butlerTests.addDatasetType(cls.repo, "icSrc", cls.visitId.keys(), "SourceCatalog") 

101 butlerTests.addDatasetType(cls.repo, "icExpBackground", cls.visitId.keys(), "Background") 

102 butlerTests.addDatasetType(cls.repo, "gaia_dr2_20200414", cls.htmId.keys(), "SimpleCatalog") 

103 butlerTests.addDatasetType(cls.repo, "ps1_pv3_3pi_20170110", cls.htmId.keys(), "SimpleCatalog") 

104 butlerTests.addDatasetType(cls.repo, "calexp", cls.visitId.keys(), "ExposureF") 

105 butlerTests.addDatasetType(cls.repo, "src", cls.visitId.keys(), "SourceCatalog") 

106 butlerTests.addDatasetType(cls.repo, "calexpBackground", cls.visitId.keys(), "Background") 

107 butlerTests.addDatasetType(cls.repo, "srcMatch", cls.visitId.keys(), "Catalog") 

108 butlerTests.addDatasetType(cls.repo, "srcMatchFull", cls.visitId.keys(), "Catalog") 

109 butlerTests.addDatasetType(cls.repo, lsst.skymap.BaseSkyMap.SKYMAP_DATASET_TYPE_NAME, 

110 cls.skymapId.keys(), "SkyMap") 

111 butlerTests.addDatasetType(cls.repo, "goodSeeingCoadd", cls.patchId.keys(), "ExposureF") 

112 butlerTests.addDatasetType(cls.repo, "deepDiff_differenceExp", cls.visitId.keys(), "ExposureF") 

113 butlerTests.addDatasetType(cls.repo, "deepDiff_differenceTempExp", cls.visitId.keys(), "ExposureF") 

114 butlerTests.addDatasetType(cls.repo, "deepDiff_templateExp", cls.visitId.keys(), "ExposureF") 

115 butlerTests.addDatasetType(cls.repo, "goodSeeingDiff_templateExp", cls.visitId.keys(), "ExposureF") 

116 butlerTests.addDatasetType(cls.repo, "deepDiff_matchedExp", cls.visitId.keys(), "ExposureF") 

117 butlerTests.addDatasetType(cls.repo, "deepDiff_diaSrc", cls.visitId.keys(), "SourceCatalog") 

118 butlerTests.addDatasetType(cls.repo, "deepDiff_diaSrcTable", cls.visitId.keys(), "DataFrame") 

119 butlerTests.addDatasetType(cls.repo, "visitSsObjects", cls.visitOnlyId.keys(), "DataFrame") 

120 butlerTests.addDatasetType(cls.repo, "apdb_marker", cls.visitId.keys(), "Config") 

121 butlerTests.addDatasetType(cls.repo, "deepDiff_associDiaSrc", cls.visitId.keys(), "DataFrame") 

122 

123 def setUp(self): 

124 super().setUp() 

125 self.butler = butlerTests.makeTestCollection(self.repo, uniqueId=self.id()) 

126 

127 def testMockIsr(self): 

128 # Testing MockIsrTask is tricky because the real ISR has an unstable 

129 # interface with dozens of potential inputs, too many to pass through 

130 # runTestQuantum. I don't see a good way to test the inputs; 

131 # fortunately, this is unlikely to matter for the overall goal of 

132 # testing ap_verify's interaction with the AP pipeline. 

133 task = MockIsrTask() 

134 pipelineTests.assertValidInitOutput(task) 

135 result = task.run(afwImage.ExposureF()) 

136 pipelineTests.assertValidOutput(task, result) 

137 # Skip runTestQuantum 

138 

139 def testMockCharacterizeImageTask(self): 

140 task = MockCharacterizeImageTask() 

141 pipelineTests.assertValidInitOutput(task) 

142 result = task.run(afwImage.ExposureF()) 

143 pipelineTests.assertValidOutput(task, result) 

144 

145 self.butler.put(afwImage.ExposureF(), "postISRCCD", self.exposureId) 

146 quantum = pipelineTests.makeQuantum( 

147 task, self.butler, self.visitId, 

148 {"exposure": self.exposureId, 

149 "characterized": self.visitId, 

150 "sourceCat": self.visitId, 

151 "backgroundModel": self.visitId, 

152 }) 

153 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False) 

154 

155 def testMockCalibrateTask(self): 

156 task = MockCalibrateTask() 

157 pipelineTests.assertValidInitOutput(task) 

158 # Even the real CalibrateTask won't pass assertValidOutput, because for 

159 # some reason the outputs are injected in runQuantum rather than run. 

160 

161 self.butler.put(afwImage.ExposureF(), "icExp", self.visitId) 

162 self.butler.put(afwMath.BackgroundList(), "icExpBackground", self.visitId) 

163 self.butler.put(afwTable.SourceCatalog(), "icSrc", self.visitId) 

164 self.butler.put(afwTable.SimpleCatalog(), "gaia_dr2_20200414", self.htmId) 

165 self.butler.put(afwTable.SimpleCatalog(), "ps1_pv3_3pi_20170110", self.htmId) 

166 quantum = pipelineTests.makeQuantum( 

167 task, self.butler, self.visitId, 

168 {"exposure": self.visitId, 

169 "background": self.visitId, 

170 "icSourceCat": self.visitId, 

171 "astromRefCat": [self.htmId], 

172 "photoRefCat": [self.htmId], 

173 "outputExposure": self.visitId, 

174 "outputCat": self.visitId, 

175 "outputBackground": self.visitId, 

176 "matches": self.visitId, 

177 "matchesDenormalized": self.visitId, 

178 }) 

179 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False) 

180 

181 def testMockGetTemplateTask(self): 

182 task = MockGetTemplateTask() 

183 pipelineTests.assertValidInitOutput(task) 

184 result = task.run(coaddExposures=[afwImage.ExposureF()], 

185 bbox=lsst.geom.Box2I(), 

186 wcs=None, # Should not be allowed, but too hard to fake a SkyWcs 

187 dataIds=[], 

188 ) 

189 pipelineTests.assertValidOutput(task, result) 

190 

191 self.butler.put(afwImage.ExposureF(), "calexp", self.visitId) 

192 skymap = lsst.skymap.DiscreteSkyMap(lsst.skymap.DiscreteSkyMapConfig()) 

193 self.butler.put(skymap, lsst.skymap.BaseSkyMap.SKYMAP_DATASET_TYPE_NAME, self.skymapId) 

194 self.butler.put(afwImage.ExposureF(), "goodSeeingCoadd", self.patchId) 

195 quantum = pipelineTests.makeQuantum( 

196 task, self.butler, self.skymapVisitId, 

197 {"bbox": self.visitId, 

198 "wcs": self.visitId, 

199 "skyMap": self.skymapId, 

200 "coaddExposures": [self.patchId], 

201 "template": self.visitId, 

202 }) 

203 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False) 

204 

205 def testMockAlardLuptonSubtractTask(self): 

206 task = MockAlardLuptonSubtractTask() 

207 pipelineTests.assertValidInitOutput(task) 

208 result = task.run(afwImage.ExposureF(), afwImage.ExposureF(), afwTable.SourceCatalog()) 

209 pipelineTests.assertValidOutput(task, result) 

210 

211 self.butler.put(afwImage.ExposureF(), "deepDiff_templateExp", self.visitId) 

212 self.butler.put(afwImage.ExposureF(), "calexp", self.visitId) 

213 self.butler.put(afwTable.SourceCatalog(), "src", self.visitId) 

214 quantum = pipelineTests.makeQuantum( 

215 task, self.butler, self.visitId, 

216 {"template": self.visitId, 

217 "science": self.visitId, 

218 "sources": self.visitId, 

219 "difference": self.visitId, 

220 "matchedTemplate": self.visitId, 

221 }) 

222 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False) 

223 

224 def testMockDetectAndMeasureTask(self): 

225 task = MockDetectAndMeasureTask() 

226 pipelineTests.assertValidInitOutput(task) 

227 result = task.run(science=afwImage.ExposureF(), 

228 matchedTemplate=afwImage.ExposureF(), 

229 difference=afwImage.ExposureF(), 

230 ) 

231 pipelineTests.assertValidOutput(task, result) 

232 

233 self.butler.put(afwImage.ExposureF(), "calexp", self.visitId) 

234 self.butler.put(afwImage.ExposureF(), "deepDiff_matchedExp", self.visitId) 

235 self.butler.put(afwImage.ExposureF(), "deepDiff_differenceTempExp", self.visitId) 

236 self.butler.put(afwTable.SourceCatalog(), "src", self.visitId) 

237 quantum = pipelineTests.makeQuantum( 

238 task, self.butler, self.visitId, 

239 {"science": self.visitId, 

240 "matchedTemplate": self.visitId, 

241 "difference": self.visitId, 

242 "diaSources": self.visitId, 

243 "subtractedMeasuredExposure": self.visitId, 

244 }) 

245 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False) 

246 

247 def testMockTransformDiaSourceCatalogTask(self): 

248 task = MockTransformDiaSourceCatalogTask(initInputs=afwTable.SourceCatalog()) 

249 pipelineTests.assertValidInitOutput(task) 

250 result = task.run(afwTable.SourceCatalog(), afwImage.ExposureF(), 'k', 42) 

251 pipelineTests.assertValidOutput(task, result) 

252 

253 self.butler.put(afwTable.SourceCatalog(), "deepDiff_diaSrc", self.visitId) 

254 self.butler.put(afwImage.ExposureF(), "deepDiff_differenceExp", self.visitId) 

255 quantum = pipelineTests.makeQuantum( 

256 task, self.butler, self.visitId, 

257 {"diaSourceCat": self.visitId, 

258 "diffIm": self.visitId, 

259 "diaSourceTable": self.visitId, 

260 }) 

261 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False) 

262 

263 def testMockDiaPipelineTask(self): 

264 config = MockDiaPipelineTask.ConfigClass() 

265 config.apdb.db_url = "testing_only" 

266 task = MockDiaPipelineTask(config=config) 

267 pipelineTests.assertValidInitOutput(task) 

268 result = task.run(pandas.DataFrame(), pandas.DataFrame(), afwImage.ExposureF(), 

269 afwImage.ExposureF(), afwImage.ExposureF(), 42, 'k') 

270 pipelineTests.assertValidOutput(task, result) 

271 

272 self.butler.put(pandas.DataFrame(), "deepDiff_diaSrcTable", self.visitId) 

273 self.butler.put(pandas.DataFrame(), "visitSsObjects", self.visitId) 

274 self.butler.put(afwImage.ExposureF(), "deepDiff_differenceExp", self.visitId) 

275 self.butler.put(afwImage.ExposureF(), "calexp", self.visitId) 

276 self.butler.put(afwImage.ExposureF(), "deepDiff_templateExp", self.visitId) 

277 quantum = pipelineTests.makeQuantum( 

278 task, self.butler, self.visitId, 

279 {"diaSourceTable": self.visitId, 

280 "solarSystemObjectTable": self.visitId, 

281 "diffIm": self.visitId, 

282 "exposure": self.visitId, 

283 "template": self.visitId, 

284 "apdbMarker": self.visitId, 

285 "associatedDiaSources": self.visitId, 

286 }) 

287 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False) 

288 

289 

290class MemoryTester(lsst.utils.tests.MemoryTestCase): 

291 pass 

292 

293 

294def setup_module(module): 

295 lsst.utils.tests.init() 

296 

297 

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

299 lsst.utils.tests.init() 

300 unittest.main()