Coverage for tests/test_testPipeline.py: 19%

179 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-17 13:17 +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 

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 = "DummyCam" 

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.dimensions["instrument"].RecordClass( 

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

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

74 ) 

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

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

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

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

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

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

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

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

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

84 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

100 

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

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

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

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

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

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

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

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

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

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

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

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

113 cls.skymapId.dimensions, "SkyMap") 

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

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

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

117 "ExposureF") 

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

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

120 "ExposureF") 

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

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

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

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

125 "SourceCatalog") 

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

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

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

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

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

131 

132 def setUp(self): 

133 super().setUp() 

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

135 

136 def testMockIsr(self): 

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

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

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

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

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

142 task = MockIsrTask() 

143 pipelineTests.assertValidInitOutput(task) 

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

145 pipelineTests.assertValidOutput(task, result) 

146 # Skip runTestQuantum 

147 

148 def testMockCharacterizeImageTask(self): 

149 task = MockCharacterizeImageTask() 

150 pipelineTests.assertValidInitOutput(task) 

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

152 pipelineTests.assertValidOutput(task, result) 

153 

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

155 quantum = pipelineTests.makeQuantum( 

156 task, self.butler, self.visitId, 

157 {"exposure": self.exposureId, 

158 "characterized": self.visitId, 

159 "sourceCat": self.visitId, 

160 "backgroundModel": self.visitId, 

161 }) 

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

163 

164 def testMockCalibrateTask(self): 

165 task = MockCalibrateTask() 

166 pipelineTests.assertValidInitOutput(task) 

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

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

169 

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

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

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

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

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

175 quantum = pipelineTests.makeQuantum( 

176 task, self.butler, self.visitId, 

177 {"exposure": self.visitId, 

178 "background": self.visitId, 

179 "icSourceCat": self.visitId, 

180 "astromRefCat": [self.htmId], 

181 "photoRefCat": [self.htmId], 

182 "outputExposure": self.visitId, 

183 "outputCat": self.visitId, 

184 "outputBackground": self.visitId, 

185 "matches": self.visitId, 

186 "matchesDenormalized": self.visitId, 

187 }) 

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

189 

190 def testMockGetTemplateTask(self): 

191 task = MockGetTemplateTask() 

192 pipelineTests.assertValidInitOutput(task) 

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

194 bbox=lsst.geom.Box2I(), 

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

196 dataIds=[], 

197 ) 

198 pipelineTests.assertValidOutput(task, result) 

199 

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

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

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

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

204 quantum = pipelineTests.makeQuantum( 

205 task, self.butler, self.skymapVisitId, 

206 {"bbox": self.visitId, 

207 "wcs": self.visitId, 

208 "skyMap": self.skymapId, 

209 "coaddExposures": [self.patchId], 

210 "template": self.visitId, 

211 }) 

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

213 

214 def testMockAlardLuptonSubtractTask(self): 

215 task = MockAlardLuptonSubtractTask() 

216 pipelineTests.assertValidInitOutput(task) 

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

218 pipelineTests.assertValidOutput(task, result) 

219 

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

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

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

223 quantum = pipelineTests.makeQuantum( 

224 task, self.butler, self.visitId, 

225 {"template": self.visitId, 

226 "science": self.visitId, 

227 "sources": self.visitId, 

228 "difference": self.visitId, 

229 "matchedTemplate": self.visitId, 

230 }) 

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

232 

233 def testMockDetectAndMeasureTask(self): 

234 task = MockDetectAndMeasureTask() 

235 pipelineTests.assertValidInitOutput(task) 

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

237 matchedTemplate=afwImage.ExposureF(), 

238 difference=afwImage.ExposureF(), 

239 ) 

240 pipelineTests.assertValidOutput(task, result) 

241 

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

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

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

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

246 quantum = pipelineTests.makeQuantum( 

247 task, self.butler, self.visitId, 

248 {"science": self.visitId, 

249 "matchedTemplate": self.visitId, 

250 "difference": self.visitId, 

251 "diaSources": self.visitId, 

252 "subtractedMeasuredExposure": self.visitId, 

253 }) 

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

255 

256 def testMockFilterDiaSourceCatalogTask(self): 

257 task = MockFilterDiaSourceCatalogTask() 

258 pipelineTests.assertValidInitOutput(task) 

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

260 pipelineTests.assertValidOutput(task, result) 

261 

262 def testMockRBTransiNetTask(self): 

263 task = MockRBTransiNetTask() 

264 pipelineTests.assertValidInitOutput(task) 

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

266 science=afwImage.ExposureF(), 

267 difference=afwImage.ExposureF(), 

268 diaSources=afwTable.SourceCatalog(), 

269 ) 

270 pipelineTests.assertValidOutput(task, result) 

271 

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

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

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

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

276 quantum = pipelineTests.makeQuantum( 

277 task, self.butler, self.visitId, 

278 {"template": self.visitId, 

279 "science": self.visitId, 

280 "difference": self.visitId, 

281 "diaSources": self.visitId, 

282 "pretrainedModel": self.emptyId, 

283 "classifications": self.visitId, 

284 }) 

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

286 

287 def testMockTransformDiaSourceCatalogTask(self): 

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

289 pipelineTests.assertValidInitOutput(task) 

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

291 pipelineTests.assertValidOutput(task, result) 

292 

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

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

295 quantum = pipelineTests.makeQuantum( 

296 task, self.butler, self.visitId, 

297 {"diaSourceCat": self.visitId, 

298 "diffIm": self.visitId, 

299 "diaSourceTable": self.visitId, 

300 }) 

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

302 

303 def testMockDiaPipelineTask(self): 

304 config = MockDiaPipelineTask.ConfigClass() 

305 config.apdb.db_url = "testing_only" 

306 task = MockDiaPipelineTask(config=config) 

307 pipelineTests.assertValidInitOutput(task) 

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

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

310 pipelineTests.assertValidOutput(task, result) 

311 

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

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

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

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

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

317 quantum = pipelineTests.makeQuantum( 

318 task, self.butler, self.visitId, 

319 {"diaSourceTable": self.visitId, 

320 "solarSystemObjectTable": self.visitId, 

321 "diffIm": self.visitId, 

322 "exposure": self.visitId, 

323 "template": self.visitId, 

324 "apdbMarker": self.visitId, 

325 "associatedDiaSources": self.visitId, 

326 "longTrailedSources": self.visitId, 

327 }) 

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

329 

330 

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

332 pass 

333 

334 

335def setup_module(module): 

336 lsst.utils.tests.init() 

337 

338 

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

340 lsst.utils.tests.init() 

341 unittest.main()