Coverage for tests/test_testPipeline.py: 18%

194 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-20 12:15 +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 MockRBTransiNetTask, MockDiaPipelineTask, MockFilterDiaSourceCatalogTask, \ 

42 MockSpatiallySampledMetricsTask 

43 

44 

45class MockTaskTestSuite(unittest.TestCase): 

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

47 they are replacing. 

48 

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

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

51 """ 

52 

53 @classmethod 

54 def setUpClass(cls): 

55 super().setUpClass() 

56 

57 repoDir = tempfile.mkdtemp() 

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

59 cls.repo = butlerTests.makeTestRepo(repoDir) 

60 

61 INSTRUMENT = "DummyCam" 

62 VISIT = 42 

63 CCD = 101 

64 HTM = 42 

65 SKYMAP = "TreasureMap" 

66 TRACT = 28 

67 PATCH = 4 

68 BAND = 'k' 

69 PHYSICAL = 'k2022' 

70 SUB_FILTER = 9 

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

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

73 name=INSTRUMENT, visit_max=256, exposure_max=256, detector_max=128, 

74 class_name="lsst.obs.base.instrument_tests.DummyCam", 

75 ) 

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

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

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

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

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

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

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

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

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

85 

86 cls.emptyId = cls.repo.registry.expandDataId({}) 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

101 

102 butlerTests.addDatasetType(cls.repo, "postISRCCD", cls.exposureId.dimensions, "Exposure") 

103 butlerTests.addDatasetType(cls.repo, "icExp", cls.visitId.dimensions, "ExposureF") 

104 butlerTests.addDatasetType(cls.repo, "icSrc", cls.visitId.dimensions, "SourceCatalog") 

105 butlerTests.addDatasetType(cls.repo, "icExpBackground", cls.visitId.dimensions, "Background") 

106 butlerTests.addDatasetType(cls.repo, "gaia_dr3_20230707", cls.htmId.dimensions, "SimpleCatalog") 

107 butlerTests.addDatasetType(cls.repo, "ps1_pv3_3pi_20170110", cls.htmId.dimensions, "SimpleCatalog") 

108 butlerTests.addDatasetType(cls.repo, "calexp", cls.visitId.dimensions, "ExposureF") 

109 butlerTests.addDatasetType(cls.repo, "src", cls.visitId.dimensions, "SourceCatalog") 

110 butlerTests.addDatasetType(cls.repo, "calexpBackground", cls.visitId.dimensions, "Background") 

111 butlerTests.addDatasetType(cls.repo, "srcMatch", cls.visitId.dimensions, "Catalog") 

112 butlerTests.addDatasetType(cls.repo, "srcMatchFull", cls.visitId.dimensions, "Catalog") 

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

114 cls.skymapId.dimensions, "SkyMap") 

115 butlerTests.addDatasetType(cls.repo, "goodSeeingCoadd", cls.patchId.dimensions, "ExposureF") 

116 butlerTests.addDatasetType(cls.repo, "deepDiff_differenceExp", cls.visitId.dimensions, "ExposureF") 

117 butlerTests.addDatasetType(cls.repo, "deepDiff_differenceTempExp", cls.visitId.dimensions, 

118 "ExposureF") 

119 butlerTests.addDatasetType(cls.repo, "deepDiff_templateExp", cls.visitId.dimensions, "ExposureF") 

120 butlerTests.addDatasetType(cls.repo, "goodSeeingDiff_templateExp", cls.visitId.dimensions, 

121 "ExposureF") 

122 butlerTests.addDatasetType(cls.repo, "deepDiff_psfMatchKernel", cls.visitId.dimensions, 

123 "MatchingKernel") 

124 butlerTests.addDatasetType(cls.repo, "deepDiff_matchedExp", cls.visitId.dimensions, "ExposureF") 

125 butlerTests.addDatasetType(cls.repo, "deepDiff_diaSrc", cls.visitId.dimensions, "SourceCatalog") 

126 butlerTests.addDatasetType(cls.repo, "deepDiff_diaSrcTable", cls.visitId.dimensions, "DataFrame") 

127 butlerTests.addDatasetType(cls.repo, "deepDiff_spatiallySampledMetrics", cls.visitId.dimensions, 

128 "ArrowAstropy") 

129 butlerTests.addDatasetType(cls.repo, "deepDiff_candidateDiaSrc", cls.visitId.dimensions, 

130 "SourceCatalog") 

131 butlerTests.addDatasetType(cls.repo, "visitSsObjects", cls.visitOnlyId.dimensions, "DataFrame") 

132 butlerTests.addDatasetType(cls.repo, "apdb_marker", cls.visitId.dimensions, "Config") 

133 butlerTests.addDatasetType(cls.repo, "deepDiff_assocDiaSrc", cls.visitId.dimensions, "DataFrame") 

134 butlerTests.addDatasetType(cls.repo, "deepDiff_longTrailedSrc", cls.visitId.dimensions, "DataFrame") 

135 butlerTests.addDatasetType(cls.repo, "deepRealBogusSources", cls.visitId.dimensions, "Catalog") 

136 butlerTests.addDatasetType(cls.repo, "deepDiff_diaForcedSrc", cls.visitId.dimensions, "DataFrame") 

137 butlerTests.addDatasetType(cls.repo, "deepDiff_diaObject", cls.visitId.dimensions, "DataFrame") 

138 

139 def setUp(self): 

140 super().setUp() 

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

142 

143 def testMockIsr(self): 

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

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

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

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

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

149 task = MockIsrTask() 

150 pipelineTests.assertValidInitOutput(task) 

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

152 pipelineTests.assertValidOutput(task, result) 

153 # Skip runTestQuantum 

154 

155 def testMockCharacterizeImageTask(self): 

156 task = MockCharacterizeImageTask() 

157 pipelineTests.assertValidInitOutput(task) 

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

159 pipelineTests.assertValidOutput(task, result) 

160 

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

162 quantum = pipelineTests.makeQuantum( 

163 task, self.butler, self.visitId, 

164 {"exposure": self.exposureId, 

165 "characterized": self.visitId, 

166 "sourceCat": self.visitId, 

167 "backgroundModel": self.visitId, 

168 }) 

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

170 

171 def testMockCalibrateTask(self): 

172 task = MockCalibrateTask() 

173 pipelineTests.assertValidInitOutput(task) 

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

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

176 

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

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

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

180 self.butler.put(afwTable.SimpleCatalog(), "gaia_dr3_20230707", self.htmId) 

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

182 quantum = pipelineTests.makeQuantum( 

183 task, self.butler, self.visitId, 

184 {"exposure": self.visitId, 

185 "background": self.visitId, 

186 "icSourceCat": self.visitId, 

187 "astromRefCat": [self.htmId], 

188 "photoRefCat": [self.htmId], 

189 "outputExposure": self.visitId, 

190 "outputCat": self.visitId, 

191 "outputBackground": self.visitId, 

192 "matches": self.visitId, 

193 "matchesDenormalized": self.visitId, 

194 }) 

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

196 

197 def testMockGetTemplateTask(self): 

198 task = MockGetTemplateTask() 

199 pipelineTests.assertValidInitOutput(task) 

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

201 bbox=lsst.geom.Box2I(), 

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

203 dataIds=[], 

204 ) 

205 pipelineTests.assertValidOutput(task, result) 

206 

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

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

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

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

211 quantum = pipelineTests.makeQuantum( 

212 task, self.butler, self.skymapVisitId, 

213 {"bbox": self.visitId, 

214 "wcs": self.visitId, 

215 "skyMap": self.skymapId, 

216 "coaddExposures": [self.patchId], 

217 "template": self.visitId, 

218 }) 

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

220 

221 def testMockAlardLuptonSubtractTask(self): 

222 task = MockAlardLuptonSubtractTask() 

223 pipelineTests.assertValidInitOutput(task) 

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

225 pipelineTests.assertValidOutput(task, result) 

226 

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

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

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

230 quantum = pipelineTests.makeQuantum( 

231 task, self.butler, self.visitId, 

232 {"template": self.visitId, 

233 "science": self.visitId, 

234 "sources": self.visitId, 

235 "difference": self.visitId, 

236 "matchedTemplate": self.visitId, 

237 "psfMatchingKernel": self.visitId, 

238 }) 

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

240 

241 def testMockDetectAndMeasureTask(self): 

242 task = MockDetectAndMeasureTask() 

243 pipelineTests.assertValidInitOutput(task) 

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

245 matchedTemplate=afwImage.ExposureF(), 

246 difference=afwImage.ExposureF(), 

247 ) 

248 pipelineTests.assertValidOutput(task, result) 

249 

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

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

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

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

254 quantum = pipelineTests.makeQuantum( 

255 task, self.butler, self.visitId, 

256 {"science": self.visitId, 

257 "matchedTemplate": self.visitId, 

258 "difference": self.visitId, 

259 "diaSources": self.visitId, 

260 "subtractedMeasuredExposure": self.visitId, 

261 }) 

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

263 

264 def testMockFilterDiaSourceCatalogTask(self): 

265 task = MockFilterDiaSourceCatalogTask() 

266 pipelineTests.assertValidInitOutput(task) 

267 result = task.run(afwTable.SourceCatalog()) 

268 pipelineTests.assertValidOutput(task, result) 

269 

270 def testMockSpatiallySampledMetricsTask(self): 

271 task = MockSpatiallySampledMetricsTask() 

272 result = task.run( 

273 afwImage.ExposureF(), 

274 afwImage.ExposureF(), 

275 afwImage.ExposureF(), 

276 afwImage.ExposureF(), 

277 afwTable.SourceCatalog(), 

278 ) 

279 pipelineTests.assertValidOutput(task, result) 

280 

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

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

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

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

285 self.butler.put(afwTable.SourceCatalog(), "deepDiff_candidateDiaSrc", self.visitId) 

286 quantum = pipelineTests.makeQuantum( 

287 task, self.butler, self.visitId, 

288 {"science": self.visitId, 

289 "matchedTemplate": self.visitId, 

290 "template": self.visitId, 

291 "difference": self.visitId, 

292 "diaSources": self.visitId, 

293 "spatiallySampledMetrics": self.visitId, 

294 }) 

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

296 

297 def testMockRBTransiNetTask(self): 

298 task = MockRBTransiNetTask() 

299 pipelineTests.assertValidInitOutput(task) 

300 result = task.run(template=afwImage.ExposureF(), 

301 science=afwImage.ExposureF(), 

302 difference=afwImage.ExposureF(), 

303 diaSources=afwTable.SourceCatalog(), 

304 ) 

305 pipelineTests.assertValidOutput(task, result) 

306 

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

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

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

310 self.butler.put(afwTable.SourceCatalog(), "deepDiff_candidateDiaSrc", self.visitId) 

311 quantum = pipelineTests.makeQuantum( 

312 task, self.butler, self.visitId, 

313 {"template": self.visitId, 

314 "science": self.visitId, 

315 "difference": self.visitId, 

316 "diaSources": self.visitId, 

317 "pretrainedModel": self.emptyId, 

318 "classifications": self.visitId, 

319 }) 

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

321 

322 def testMockTransformDiaSourceCatalogTask(self): 

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

324 pipelineTests.assertValidInitOutput(task) 

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

326 pipelineTests.assertValidOutput(task, result) 

327 

328 self.butler.put(afwTable.SourceCatalog(), "deepDiff_candidateDiaSrc", self.visitId) 

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

330 quantum = pipelineTests.makeQuantum( 

331 task, self.butler, self.visitId, 

332 {"diaSourceCat": self.visitId, 

333 "diffIm": self.visitId, 

334 "diaSourceTable": self.visitId, 

335 }) 

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

337 

338 def testMockDiaPipelineTask(self): 

339 config = MockDiaPipelineTask.ConfigClass() 

340 config.apdb.db_url = "testing_only" 

341 task = MockDiaPipelineTask(config=config) 

342 pipelineTests.assertValidInitOutput(task) 

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

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

345 pipelineTests.assertValidOutput(task, result) 

346 

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

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

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

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

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

352 quantum = pipelineTests.makeQuantum( 

353 task, self.butler, self.visitId, 

354 {"diaSourceTable": self.visitId, 

355 "solarSystemObjectTable": self.visitId, 

356 "diffIm": self.visitId, 

357 "exposure": self.visitId, 

358 "template": self.visitId, 

359 "apdbMarker": self.visitId, 

360 "associatedDiaSources": self.visitId, 

361 "longTrailedSources": self.visitId, 

362 "diaForcedSources": self.visitId, 

363 "diaObjects": self.visitId, 

364 }) 

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

366 

367 

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

369 pass 

370 

371 

372def setup_module(module): 

373 lsst.utils.tests.init() 

374 

375 

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

377 lsst.utils.tests.init() 

378 unittest.main()