Coverage for tests/test_testPipeline.py: 20%

160 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-25 13:58 +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 = "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.exposureId = cls.repo.registry.expandDataId( 

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

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

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

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

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

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

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

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

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

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

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

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

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

99 

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

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

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

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

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

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

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

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

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

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

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

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

112 cls.skymapId.dimensions, "SkyMap") 

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

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

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

116 "ExposureF") 

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

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

119 "ExposureF") 

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

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

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

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

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

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

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

127 

128 def setUp(self): 

129 super().setUp() 

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

131 

132 def testMockIsr(self): 

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

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

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

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

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

138 task = MockIsrTask() 

139 pipelineTests.assertValidInitOutput(task) 

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

141 pipelineTests.assertValidOutput(task, result) 

142 # Skip runTestQuantum 

143 

144 def testMockCharacterizeImageTask(self): 

145 task = MockCharacterizeImageTask() 

146 pipelineTests.assertValidInitOutput(task) 

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

148 pipelineTests.assertValidOutput(task, result) 

149 

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

151 quantum = pipelineTests.makeQuantum( 

152 task, self.butler, self.visitId, 

153 {"exposure": self.exposureId, 

154 "characterized": self.visitId, 

155 "sourceCat": self.visitId, 

156 "backgroundModel": self.visitId, 

157 }) 

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

159 

160 def testMockCalibrateTask(self): 

161 task = MockCalibrateTask() 

162 pipelineTests.assertValidInitOutput(task) 

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

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

165 

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

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

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

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

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

171 quantum = pipelineTests.makeQuantum( 

172 task, self.butler, self.visitId, 

173 {"exposure": self.visitId, 

174 "background": self.visitId, 

175 "icSourceCat": self.visitId, 

176 "astromRefCat": [self.htmId], 

177 "photoRefCat": [self.htmId], 

178 "outputExposure": self.visitId, 

179 "outputCat": self.visitId, 

180 "outputBackground": self.visitId, 

181 "matches": self.visitId, 

182 "matchesDenormalized": self.visitId, 

183 }) 

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

185 

186 def testMockGetTemplateTask(self): 

187 task = MockGetTemplateTask() 

188 pipelineTests.assertValidInitOutput(task) 

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

190 bbox=lsst.geom.Box2I(), 

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

192 dataIds=[], 

193 ) 

194 pipelineTests.assertValidOutput(task, result) 

195 

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

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

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

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

200 quantum = pipelineTests.makeQuantum( 

201 task, self.butler, self.skymapVisitId, 

202 {"bbox": self.visitId, 

203 "wcs": self.visitId, 

204 "skyMap": self.skymapId, 

205 "coaddExposures": [self.patchId], 

206 "template": self.visitId, 

207 }) 

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

209 

210 def testMockAlardLuptonSubtractTask(self): 

211 task = MockAlardLuptonSubtractTask() 

212 pipelineTests.assertValidInitOutput(task) 

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

214 pipelineTests.assertValidOutput(task, result) 

215 

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

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

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

219 quantum = pipelineTests.makeQuantum( 

220 task, self.butler, self.visitId, 

221 {"template": self.visitId, 

222 "science": self.visitId, 

223 "sources": self.visitId, 

224 "difference": self.visitId, 

225 "matchedTemplate": self.visitId, 

226 }) 

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

228 

229 def testMockDetectAndMeasureTask(self): 

230 task = MockDetectAndMeasureTask() 

231 pipelineTests.assertValidInitOutput(task) 

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

233 matchedTemplate=afwImage.ExposureF(), 

234 difference=afwImage.ExposureF(), 

235 ) 

236 pipelineTests.assertValidOutput(task, result) 

237 

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

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

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

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

242 quantum = pipelineTests.makeQuantum( 

243 task, self.butler, self.visitId, 

244 {"science": self.visitId, 

245 "matchedTemplate": self.visitId, 

246 "difference": self.visitId, 

247 "diaSources": self.visitId, 

248 "subtractedMeasuredExposure": self.visitId, 

249 }) 

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

251 

252 def testMockTransformDiaSourceCatalogTask(self): 

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

254 pipelineTests.assertValidInitOutput(task) 

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

256 pipelineTests.assertValidOutput(task, result) 

257 

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

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

260 quantum = pipelineTests.makeQuantum( 

261 task, self.butler, self.visitId, 

262 {"diaSourceCat": self.visitId, 

263 "diffIm": self.visitId, 

264 "diaSourceTable": self.visitId, 

265 }) 

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

267 

268 def testMockDiaPipelineTask(self): 

269 config = MockDiaPipelineTask.ConfigClass() 

270 config.apdb.db_url = "testing_only" 

271 task = MockDiaPipelineTask(config=config) 

272 pipelineTests.assertValidInitOutput(task) 

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

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

275 pipelineTests.assertValidOutput(task, result) 

276 

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

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

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

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

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

282 quantum = pipelineTests.makeQuantum( 

283 task, self.butler, self.visitId, 

284 {"diaSourceTable": self.visitId, 

285 "solarSystemObjectTable": self.visitId, 

286 "diffIm": self.visitId, 

287 "exposure": self.visitId, 

288 "template": self.visitId, 

289 "apdbMarker": self.visitId, 

290 "associatedDiaSources": self.visitId, 

291 "longTrailedSources": self.visitId, 

292 }) 

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

294 

295 

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

297 pass 

298 

299 

300def setup_module(module): 

301 lsst.utils.tests.init() 

302 

303 

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

305 lsst.utils.tests.init() 

306 unittest.main()