Coverage for tests/test_NoiseReplacer.py: 39%
62 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-19 04:56 -0700
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-19 04:56 -0700
1# This file is part of meas_base.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
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 GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22import unittest
24import numpy as np
26import lsst.geom
27import lsst.afw.geom
28import lsst.afw.detection
29import lsst.afw.table
30import lsst.meas.base.tests
31import lsst.utils.tests
32from lsst.daf.base import PropertyList
33from lsst.utils.tests import methodParameters
36@lsst.meas.base.register("test_NoiseReplacer")
37class NoiseReplacerTestPlugin(lsst.meas.base.SingleFramePlugin):
38 """Plugin that sums instFlux inside and outside the source footprint.
39 """
41 @staticmethod
42 def getExecutionOrder():
43 return 2.0
45 def __init__(self, config, name, schema, metadata):
46 lsst.meas.base.SingleFramePlugin.__init__(self, config, name, schema, metadata)
47 self.insideKey = schema.addField("%s_inside" % (name,), type=np.float64,
48 doc="instFlux inside footprint")
49 self.outsideKey = schema.addField("%s_outside" % (name,), type=np.float64,
50 doc="instFlux outside footprint")
52 def measure(self, measRecord, exposure):
53 footprint = measRecord.getFootprint()
54 fullArray = exposure.getMaskedImage().getImage().getArray()
55 insideArray = np.zeros(footprint.getArea(), dtype=fullArray.dtype)
56 footprint.spans.flatten(insideArray, fullArray, exposure.getXY0())
57 insideFlux = float(insideArray.sum())
58 outsideFlux = float(fullArray.sum()) - insideFlux
59 measRecord.set(self.insideKey, insideFlux)
60 measRecord.set(self.outsideKey, outsideFlux)
63class NoiseReplacerTestCase(lsst.meas.base.tests.AlgorithmTestCase, lsst.utils.tests.TestCase):
65 def setUp(self):
66 self.bbox = lsst.geom.Box2I(lsst.geom.Point2I(-20, -30),
67 lsst.geom.Extent2I(240, 260))
68 self.dataset = lsst.meas.base.tests.TestDataset(self.bbox)
69 # first source is a point
70 self.dataset.addSource(100000.0, lsst.geom.Point2D(50.1, 49.8))
71 # second source is extended
72 self.dataset.addSource(120000.0, lsst.geom.Point2D(149.9, 50.3),
73 lsst.afw.geom.Quadrupole(8, 9, 3))
74 with self.dataset.addBlend() as family:
75 family.addChild(110000.0, lsst.geom.Point2D(65.2, 150.7),
76 lsst.afw.geom.Quadrupole(7, 5, -1))
77 family.addChild(140000.0, lsst.geom.Point2D(72.3, 149.1))
78 family.addChild(90000.0, lsst.geom.Point2D(68.5, 156.9))
80 @methodParameters(noiseSource=['measure', 'variance', 'meta', 'variance_median'],
81 variance=[1.0, 1.0, 2.0, 1.0])
82 def testNoiseReplacer(self, noiseSource, variance):
83 """Test noise replacement in SFM with ''measure'' mode.
85 We compare the instFlux inside and outside source Footprints on an
86 extremely high S/N image.
87 """
88 # We choose a random seed which causes the test to pass.
89 task = self.makeSingleFrameMeasurementTask("test_NoiseReplacer")
90 task.config.noiseReplacer.noiseSource = noiseSource
91 exposure, catalog = self.dataset.realize(variance, task.schema, randomSeed=0)
92 if noiseSource == 'meta':
93 md = PropertyList()
94 md['BGMEAN'] = variance
95 exposure.setMetadata(md)
96 task.run(catalog, exposure)
97 sumVariance = exposure.getMaskedImage().getVariance().getArray().sum()
98 for record in catalog:
99 self.assertFloatsAlmostEqual(record.get("test_NoiseReplacer_inside"),
100 record.get("truth_instFlux"), rtol=1E-3)
102 # N.B. Next line checks that a random value is correct to a
103 # statistical 1-sigma prediction; some RNG seeds may cause it to
104 # fail (indeed, 67% should)
105 self.assertLess(record.get("test_NoiseReplacer_outside"), np.sqrt(sumVariance))
107 def tearDown(self):
108 del self.bbox
109 del self.dataset
112class TestMemory(lsst.utils.tests.MemoryTestCase):
113 pass
116def setup_module(module):
117 lsst.utils.tests.init()
120if __name__ == "__main__": 120 ↛ 121line 120 didn't jump to line 121, because the condition on line 120 was never true
121 lsst.utils.tests.init()
122 unittest.main()