Coverage for tests/test_cModelPlugins.py: 29%
58 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-23 03:34 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-23 03:34 -0800
1#
2# LSST Data Management System
3#
4# Copyright 2008-2016 AURA/LSST.
5#
6# This product includes software developed by the
7# LSST Project (http://www.lsst.org/).
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the LSST License Statement and
20# the GNU General Public License along with this program. If not,
21# see <https://www.lsstcorp.org/LegalNotices/>.
22#
23import unittest
25import lsst.afw.geom
26import lsst.geom
27import lsst.afw.table
28import lsst.utils.tests
29import lsst.meas.modelfit
31import lsst.meas.base.tests
34# n.b. Some tests here depend on the noise realization in the test data
35# or from the numpy random number generator.
36# For the current test data and seed value, they pass, but they may not
37# if the test data is regenerated or the seed value changes. I've marked
38# these with an "rng dependent" comment. In most cases, they test that
39# the measured flux lies within 2 sigma of the correct value, which we
40# should expect to fail sometimes.
42class CModelTestCase(lsst.meas.base.tests.AlgorithmTestCase, lsst.utils.tests.TestCase):
43 """Test case for the CModel measurement plugins
44 """
46 def setUp(self):
47 self.bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
48 lsst.geom.Extent2I(200, 100))
49 self.dataset = lsst.meas.base.tests.TestDataset(self.bbox)
50 # first source is a point
51 self.dataset.addSource(100000.0, lsst.geom.Point2D(50.1, 49.8))
52 # second source is extended
53 self.dataset.addSource(100000.0, lsst.geom.Point2D(149.9, 50.3),
54 lsst.afw.geom.ellipses.Quadrupole(8, 9, 3))
56 def tearDown(self):
57 del self.bbox
58 del self.dataset
60 def checkOutputs(self, measCat, truthCat=None):
61 """Test that the outputs of the CModel plugins are reasonable, and that the bookkeeping works.
63 Science-quality tests either in testCModel.py (where we call the same code via a different interface)
64 or something we have to do statistically on real data.
65 """
66 if truthCat is None:
67 truthCat = measCat
68 for measRecord, truthRecord in zip(measCat, truthCat):
69 trueFlux = truthRecord.get("truth_instFlux")
70 self.assertFalse(measRecord.get("modelfit_CModel_initial_flag"))
71 self.assertFalse(measRecord.get("modelfit_CModel_exp_flag"))
72 self.assertFalse(measRecord.get("modelfit_CModel_dev_flag"))
73 self.assertFalse(measRecord.get("modelfit_CModel_flag"))
74 self.assertFloatsAlmostEqual(measRecord.get("modelfit_CModel_instFlux"), trueFlux, rtol=0.5)
75 self.assertGreater(measRecord.get("modelfit_CModel_instFluxErr"), 0.0)
76 self.assertFloatsAlmostEqual(measRecord.get("modelfit_CModel_initial_instFlux"),
77 trueFlux, rtol=0.5)
78 self.assertGreater(measRecord.get("modelfit_CModel_initial_instFluxErr"), 0.0)
79 self.assertFloatsAlmostEqual(measRecord.get("modelfit_CModel_exp_instFlux"), trueFlux, rtol=0.5)
80 self.assertGreater(measRecord.get("modelfit_CModel_exp_instFluxErr"), 0.0)
81 self.assertFloatsAlmostEqual(measRecord.get("modelfit_CModel_dev_instFlux"), trueFlux, rtol=0.5)
82 self.assertGreater(measRecord.get("modelfit_CModel_dev_instFluxErr"), 0.0)
84 def testPlugins(self):
85 """Test that the plugin for single-frame measurement works, then use those outputs to test
86 that the forced measurement plugin works."""
87 plugin = "modelfit_CModel"
88 dependencies = ("modelfit_DoubleShapeletPsfApprox", "base_PsfFlux")
89 sfmTask = self.makeSingleFrameMeasurementTask(plugin, dependencies=dependencies)
90 forcedTask = self.makeForcedMeasurementTask(plugin, dependencies=dependencies,
91 refSchema=sfmTask.schema)
92 # catalog1 will contain both the SFM outputs and the truth catalog for sources in exposure 1.
93 # Those SFM outputs will also be used as the references for the forced task.
94 exposure1, catalog1 = self.dataset.realize(10.0, sfmTask.schema, randomSeed=0)
95 sfmTask.run(catalog1, exposure1)
96 self.checkOutputs(catalog1)
97 if False: # this line should be re-enabled on DM-5405
98 wcs2 = self.dataset.makePerturbedWcs(self.dataset.exposure.getWcs(), randomSeed=0)
99 else:
100 wcs2 = self.dataset.exposure.getWcs()
101 dataset2 = self.dataset.transform(wcs2)
102 # catalog2 will contain only the truth catalog for sources in exposure 1; the structure of
103 # ForcedMeasurementTask means we can't put the outputs in the same catalog.
104 exposure2, catalog2 = dataset2.realize(10.0, dataset2.makeMinimalSchema(), randomSeed=1)
105 refWcs = exposure1.getWcs()
106 refCat = catalog1
107 measCat = forcedTask.generateMeasCat(exposure2, refCat, refWcs)
108 forcedTask.attachTransformedFootprints(measCat, refCat, exposure2, refWcs)
109 forcedTask.run(measCat, exposure2, refCat, refWcs)
110 self.checkOutputs(measCat, catalog2)
113class TestMemory(lsst.utils.tests.MemoryTestCase):
114 pass
117def setup_module(module):
118 lsst.utils.tests.init()
121if __name__ == "__main__": 121 ↛ 122line 121 didn't jump to line 122, because the condition on line 121 was never true
122 lsst.utils.tests.init()
123 unittest.main()