Coverage for tests/test_testPipeline.py: 18%

181 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-03-29 13:34 +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 butlerTests.addDatasetType(cls.repo, "deepDiff_diaForcedSrc", cls.visitId.dimensions, "DataFrame") 

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

133 

134 def setUp(self): 

135 super().setUp() 

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

137 

138 def testMockIsr(self): 

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

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

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

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

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

144 task = MockIsrTask() 

145 pipelineTests.assertValidInitOutput(task) 

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

147 pipelineTests.assertValidOutput(task, result) 

148 # Skip runTestQuantum 

149 

150 def testMockCharacterizeImageTask(self): 

151 task = MockCharacterizeImageTask() 

152 pipelineTests.assertValidInitOutput(task) 

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

154 pipelineTests.assertValidOutput(task, result) 

155 

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

157 quantum = pipelineTests.makeQuantum( 

158 task, self.butler, self.visitId, 

159 {"exposure": self.exposureId, 

160 "characterized": self.visitId, 

161 "sourceCat": self.visitId, 

162 "backgroundModel": self.visitId, 

163 }) 

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

165 

166 def testMockCalibrateTask(self): 

167 task = MockCalibrateTask() 

168 pipelineTests.assertValidInitOutput(task) 

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

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

171 

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

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

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

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

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

177 quantum = pipelineTests.makeQuantum( 

178 task, self.butler, self.visitId, 

179 {"exposure": self.visitId, 

180 "background": self.visitId, 

181 "icSourceCat": self.visitId, 

182 "astromRefCat": [self.htmId], 

183 "photoRefCat": [self.htmId], 

184 "outputExposure": self.visitId, 

185 "outputCat": self.visitId, 

186 "outputBackground": self.visitId, 

187 "matches": self.visitId, 

188 "matchesDenormalized": self.visitId, 

189 }) 

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

191 

192 def testMockGetTemplateTask(self): 

193 task = MockGetTemplateTask() 

194 pipelineTests.assertValidInitOutput(task) 

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

196 bbox=lsst.geom.Box2I(), 

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

198 dataIds=[], 

199 ) 

200 pipelineTests.assertValidOutput(task, result) 

201 

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

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

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

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

206 quantum = pipelineTests.makeQuantum( 

207 task, self.butler, self.skymapVisitId, 

208 {"bbox": self.visitId, 

209 "wcs": self.visitId, 

210 "skyMap": self.skymapId, 

211 "coaddExposures": [self.patchId], 

212 "template": self.visitId, 

213 }) 

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

215 

216 def testMockAlardLuptonSubtractTask(self): 

217 task = MockAlardLuptonSubtractTask() 

218 pipelineTests.assertValidInitOutput(task) 

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

220 pipelineTests.assertValidOutput(task, result) 

221 

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

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

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

225 quantum = pipelineTests.makeQuantum( 

226 task, self.butler, self.visitId, 

227 {"template": self.visitId, 

228 "science": self.visitId, 

229 "sources": self.visitId, 

230 "difference": self.visitId, 

231 "matchedTemplate": self.visitId, 

232 }) 

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

234 

235 def testMockDetectAndMeasureTask(self): 

236 task = MockDetectAndMeasureTask() 

237 pipelineTests.assertValidInitOutput(task) 

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

239 matchedTemplate=afwImage.ExposureF(), 

240 difference=afwImage.ExposureF(), 

241 ) 

242 pipelineTests.assertValidOutput(task, result) 

243 

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

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

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

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

248 quantum = pipelineTests.makeQuantum( 

249 task, self.butler, self.visitId, 

250 {"science": self.visitId, 

251 "matchedTemplate": self.visitId, 

252 "difference": self.visitId, 

253 "diaSources": self.visitId, 

254 "subtractedMeasuredExposure": self.visitId, 

255 }) 

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

257 

258 def testMockFilterDiaSourceCatalogTask(self): 

259 task = MockFilterDiaSourceCatalogTask() 

260 pipelineTests.assertValidInitOutput(task) 

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

262 pipelineTests.assertValidOutput(task, result) 

263 

264 def testMockRBTransiNetTask(self): 

265 task = MockRBTransiNetTask() 

266 pipelineTests.assertValidInitOutput(task) 

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

268 science=afwImage.ExposureF(), 

269 difference=afwImage.ExposureF(), 

270 diaSources=afwTable.SourceCatalog(), 

271 ) 

272 pipelineTests.assertValidOutput(task, result) 

273 

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

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

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

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

278 quantum = pipelineTests.makeQuantum( 

279 task, self.butler, self.visitId, 

280 {"template": self.visitId, 

281 "science": self.visitId, 

282 "difference": self.visitId, 

283 "diaSources": self.visitId, 

284 "pretrainedModel": self.emptyId, 

285 "classifications": self.visitId, 

286 }) 

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

288 

289 def testMockTransformDiaSourceCatalogTask(self): 

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

291 pipelineTests.assertValidInitOutput(task) 

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

293 pipelineTests.assertValidOutput(task, result) 

294 

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

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

297 quantum = pipelineTests.makeQuantum( 

298 task, self.butler, self.visitId, 

299 {"diaSourceCat": self.visitId, 

300 "diffIm": self.visitId, 

301 "diaSourceTable": self.visitId, 

302 }) 

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

304 

305 def testMockDiaPipelineTask(self): 

306 config = MockDiaPipelineTask.ConfigClass() 

307 config.apdb.db_url = "testing_only" 

308 task = MockDiaPipelineTask(config=config) 

309 pipelineTests.assertValidInitOutput(task) 

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

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

312 pipelineTests.assertValidOutput(task, result) 

313 

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

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

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

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

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

319 quantum = pipelineTests.makeQuantum( 

320 task, self.butler, self.visitId, 

321 {"diaSourceTable": self.visitId, 

322 "solarSystemObjectTable": self.visitId, 

323 "diffIm": self.visitId, 

324 "exposure": self.visitId, 

325 "template": self.visitId, 

326 "apdbMarker": self.visitId, 

327 "associatedDiaSources": self.visitId, 

328 "longTrailedSources": self.visitId, 

329 "diaForcedSources": self.visitId, 

330 "diaObjects": self.visitId, 

331 }) 

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

333 

334 

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

336 pass 

337 

338 

339def setup_module(module): 

340 lsst.utils.tests.init() 

341 

342 

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

344 lsst.utils.tests.init() 

345 unittest.main()