Coverage for tests/test_testPipeline.py: 19%
159 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-04 06:16 -0700
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-04 06:16 -0700
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#
24import shutil
25import tempfile
26import unittest
28import pandas
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
44class MockTaskTestSuite(unittest.TestCase):
45 """Test that mock tasks have the correct inputs and outputs for the task
46 they are replacing.
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 """
52 @classmethod
53 def setUpClass(cls):
54 super().setUpClass()
56 repoDir = tempfile.mkdtemp()
57 cls.addClassCleanup(shutil.rmtree, repoDir, ignore_errors=True)
58 cls.repo = butlerTests.makeTestRepo(repoDir)
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.registry.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)
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})
100 butlerTests.addDatasetType(cls.repo, "postISRCCD", cls.exposureId.keys(), "Exposure")
101 butlerTests.addDatasetType(cls.repo, "icExp", cls.visitId.keys(), "ExposureF")
102 butlerTests.addDatasetType(cls.repo, "icSrc", cls.visitId.keys(), "SourceCatalog")
103 butlerTests.addDatasetType(cls.repo, "icExpBackground", cls.visitId.keys(), "Background")
104 butlerTests.addDatasetType(cls.repo, "gaia_dr2_20200414", cls.htmId.keys(), "SimpleCatalog")
105 butlerTests.addDatasetType(cls.repo, "ps1_pv3_3pi_20170110", cls.htmId.keys(), "SimpleCatalog")
106 butlerTests.addDatasetType(cls.repo, "calexp", cls.visitId.keys(), "ExposureF")
107 butlerTests.addDatasetType(cls.repo, "src", cls.visitId.keys(), "SourceCatalog")
108 butlerTests.addDatasetType(cls.repo, "calexpBackground", cls.visitId.keys(), "Background")
109 butlerTests.addDatasetType(cls.repo, "srcMatch", cls.visitId.keys(), "Catalog")
110 butlerTests.addDatasetType(cls.repo, "srcMatchFull", cls.visitId.keys(), "Catalog")
111 butlerTests.addDatasetType(cls.repo, lsst.skymap.BaseSkyMap.SKYMAP_DATASET_TYPE_NAME,
112 cls.skymapId.keys(), "SkyMap")
113 butlerTests.addDatasetType(cls.repo, "goodSeeingCoadd", cls.patchId.keys(), "ExposureF")
114 butlerTests.addDatasetType(cls.repo, "deepDiff_differenceExp", cls.visitId.keys(), "ExposureF")
115 butlerTests.addDatasetType(cls.repo, "deepDiff_differenceTempExp", cls.visitId.keys(), "ExposureF")
116 butlerTests.addDatasetType(cls.repo, "deepDiff_templateExp", cls.visitId.keys(), "ExposureF")
117 butlerTests.addDatasetType(cls.repo, "goodSeeingDiff_templateExp", cls.visitId.keys(), "ExposureF")
118 butlerTests.addDatasetType(cls.repo, "deepDiff_matchedExp", cls.visitId.keys(), "ExposureF")
119 butlerTests.addDatasetType(cls.repo, "deepDiff_diaSrc", cls.visitId.keys(), "SourceCatalog")
120 butlerTests.addDatasetType(cls.repo, "deepDiff_diaSrcTable", cls.visitId.keys(), "DataFrame")
121 butlerTests.addDatasetType(cls.repo, "visitSsObjects", cls.visitOnlyId.keys(), "DataFrame")
122 butlerTests.addDatasetType(cls.repo, "apdb_marker", cls.visitId.keys(), "Config")
123 butlerTests.addDatasetType(cls.repo, "deepDiff_associDiaSrc", cls.visitId.keys(), "DataFrame")
125 def setUp(self):
126 super().setUp()
127 self.butler = butlerTests.makeTestCollection(self.repo, uniqueId=self.id())
129 def testMockIsr(self):
130 # Testing MockIsrTask is tricky because the real ISR has an unstable
131 # interface with dozens of potential inputs, too many to pass through
132 # runTestQuantum. I don't see a good way to test the inputs;
133 # fortunately, this is unlikely to matter for the overall goal of
134 # testing ap_verify's interaction with the AP pipeline.
135 task = MockIsrTask()
136 pipelineTests.assertValidInitOutput(task)
137 result = task.run(afwImage.ExposureF())
138 pipelineTests.assertValidOutput(task, result)
139 # Skip runTestQuantum
141 def testMockCharacterizeImageTask(self):
142 task = MockCharacterizeImageTask()
143 pipelineTests.assertValidInitOutput(task)
144 result = task.run(afwImage.ExposureF())
145 pipelineTests.assertValidOutput(task, result)
147 self.butler.put(afwImage.ExposureF(), "postISRCCD", self.exposureId)
148 quantum = pipelineTests.makeQuantum(
149 task, self.butler, self.visitId,
150 {"exposure": self.exposureId,
151 "characterized": self.visitId,
152 "sourceCat": self.visitId,
153 "backgroundModel": self.visitId,
154 })
155 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False)
157 def testMockCalibrateTask(self):
158 task = MockCalibrateTask()
159 pipelineTests.assertValidInitOutput(task)
160 # Even the real CalibrateTask won't pass assertValidOutput, because for
161 # some reason the outputs are injected in runQuantum rather than run.
163 self.butler.put(afwImage.ExposureF(), "icExp", self.visitId)
164 self.butler.put(afwMath.BackgroundList(), "icExpBackground", self.visitId)
165 self.butler.put(afwTable.SourceCatalog(), "icSrc", self.visitId)
166 self.butler.put(afwTable.SimpleCatalog(), "gaia_dr2_20200414", self.htmId)
167 self.butler.put(afwTable.SimpleCatalog(), "ps1_pv3_3pi_20170110", self.htmId)
168 quantum = pipelineTests.makeQuantum(
169 task, self.butler, self.visitId,
170 {"exposure": self.visitId,
171 "background": self.visitId,
172 "icSourceCat": self.visitId,
173 "astromRefCat": [self.htmId],
174 "photoRefCat": [self.htmId],
175 "outputExposure": self.visitId,
176 "outputCat": self.visitId,
177 "outputBackground": self.visitId,
178 "matches": self.visitId,
179 "matchesDenormalized": self.visitId,
180 })
181 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False)
183 def testMockGetTemplateTask(self):
184 task = MockGetTemplateTask()
185 pipelineTests.assertValidInitOutput(task)
186 result = task.run(coaddExposures=[afwImage.ExposureF()],
187 bbox=lsst.geom.Box2I(),
188 wcs=None, # Should not be allowed, but too hard to fake a SkyWcs
189 dataIds=[],
190 )
191 pipelineTests.assertValidOutput(task, result)
193 self.butler.put(afwImage.ExposureF(), "calexp", self.visitId)
194 skymap = lsst.skymap.DiscreteSkyMap(lsst.skymap.DiscreteSkyMapConfig())
195 self.butler.put(skymap, lsst.skymap.BaseSkyMap.SKYMAP_DATASET_TYPE_NAME, self.skymapId)
196 self.butler.put(afwImage.ExposureF(), "goodSeeingCoadd", self.patchId)
197 quantum = pipelineTests.makeQuantum(
198 task, self.butler, self.skymapVisitId,
199 {"bbox": self.visitId,
200 "wcs": self.visitId,
201 "skyMap": self.skymapId,
202 "coaddExposures": [self.patchId],
203 "template": self.visitId,
204 })
205 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False)
207 def testMockAlardLuptonSubtractTask(self):
208 task = MockAlardLuptonSubtractTask()
209 pipelineTests.assertValidInitOutput(task)
210 result = task.run(afwImage.ExposureF(), afwImage.ExposureF(), afwTable.SourceCatalog())
211 pipelineTests.assertValidOutput(task, result)
213 self.butler.put(afwImage.ExposureF(), "deepDiff_templateExp", self.visitId)
214 self.butler.put(afwImage.ExposureF(), "calexp", self.visitId)
215 self.butler.put(afwTable.SourceCatalog(), "src", self.visitId)
216 quantum = pipelineTests.makeQuantum(
217 task, self.butler, self.visitId,
218 {"template": self.visitId,
219 "science": self.visitId,
220 "sources": self.visitId,
221 "difference": self.visitId,
222 "matchedTemplate": self.visitId,
223 })
224 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False)
226 def testMockDetectAndMeasureTask(self):
227 task = MockDetectAndMeasureTask()
228 pipelineTests.assertValidInitOutput(task)
229 result = task.run(science=afwImage.ExposureF(),
230 matchedTemplate=afwImage.ExposureF(),
231 difference=afwImage.ExposureF(),
232 )
233 pipelineTests.assertValidOutput(task, result)
235 self.butler.put(afwImage.ExposureF(), "calexp", self.visitId)
236 self.butler.put(afwImage.ExposureF(), "deepDiff_matchedExp", self.visitId)
237 self.butler.put(afwImage.ExposureF(), "deepDiff_differenceTempExp", self.visitId)
238 self.butler.put(afwTable.SourceCatalog(), "src", self.visitId)
239 quantum = pipelineTests.makeQuantum(
240 task, self.butler, self.visitId,
241 {"science": self.visitId,
242 "matchedTemplate": self.visitId,
243 "difference": self.visitId,
244 "diaSources": self.visitId,
245 "subtractedMeasuredExposure": self.visitId,
246 })
247 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False)
249 def testMockTransformDiaSourceCatalogTask(self):
250 task = MockTransformDiaSourceCatalogTask(initInputs=afwTable.SourceCatalog())
251 pipelineTests.assertValidInitOutput(task)
252 result = task.run(afwTable.SourceCatalog(), afwImage.ExposureF(), 'k', 42)
253 pipelineTests.assertValidOutput(task, result)
255 self.butler.put(afwTable.SourceCatalog(), "deepDiff_diaSrc", self.visitId)
256 self.butler.put(afwImage.ExposureF(), "deepDiff_differenceExp", self.visitId)
257 quantum = pipelineTests.makeQuantum(
258 task, self.butler, self.visitId,
259 {"diaSourceCat": self.visitId,
260 "diffIm": self.visitId,
261 "diaSourceTable": self.visitId,
262 })
263 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False)
265 def testMockDiaPipelineTask(self):
266 config = MockDiaPipelineTask.ConfigClass()
267 config.apdb.db_url = "testing_only"
268 task = MockDiaPipelineTask(config=config)
269 pipelineTests.assertValidInitOutput(task)
270 result = task.run(pandas.DataFrame(), pandas.DataFrame(), afwImage.ExposureF(),
271 afwImage.ExposureF(), afwImage.ExposureF(), 42, 'k')
272 pipelineTests.assertValidOutput(task, result)
274 self.butler.put(pandas.DataFrame(), "deepDiff_diaSrcTable", self.visitId)
275 self.butler.put(pandas.DataFrame(), "visitSsObjects", self.visitId)
276 self.butler.put(afwImage.ExposureF(), "deepDiff_differenceExp", self.visitId)
277 self.butler.put(afwImage.ExposureF(), "calexp", self.visitId)
278 self.butler.put(afwImage.ExposureF(), "deepDiff_templateExp", self.visitId)
279 quantum = pipelineTests.makeQuantum(
280 task, self.butler, self.visitId,
281 {"diaSourceTable": self.visitId,
282 "solarSystemObjectTable": self.visitId,
283 "diffIm": self.visitId,
284 "exposure": self.visitId,
285 "template": self.visitId,
286 "apdbMarker": self.visitId,
287 "associatedDiaSources": self.visitId,
288 })
289 pipelineTests.runTestQuantum(task, self.butler, quantum, mockRun=False)
292class MemoryTester(lsst.utils.tests.MemoryTestCase):
293 pass
296def setup_module(module):
297 lsst.utils.tests.init()
300if __name__ == "__main__": 300 ↛ 301line 300 didn't jump to line 301, because the condition on line 300 was never true
301 lsst.utils.tests.init()
302 unittest.main()