Coverage for tests/test_objectSizeStarSelector.py: 18%
96 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-23 08:56 +0000
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-23 08:56 +0000
1# This file is part of meas_algorithms.
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
23import numpy as np
25import lsst.afw.table as afwTable
26from lsst.meas.algorithms import sourceSelector
27import lsst.meas.base.tests
28import lsst.utils.tests
30fluxField = "base_GaussianFlux_instFlux"
33def addGoodSource(sourceCat, num=0):
34 """Insert a likely-good source into the catalog.
36 Parameters
37 ----------
38 sourceCat : `lsst.afw.table.SourceCatalog`
39 The source catalog for which a "good" source is to be added for testing.
40 num : `float` or `int`
41 A number that is added to various values to distinguish them in catalogs with multiple objects.
42 """
43 sourceCat.addNew()
44 sourceCat["coord_ra"][-1] = 1.0 + num
45 sourceCat["coord_dec"][-1] = 2.0 + num
46 # Add some variability to the fluxes to form a cluster with non-finite "width" in the mag-size plane
47 fluxFactor = np.random.uniform(low=0.98, high=1.02)
48 sourceCat[fluxField][-1] = 100.0*fluxFactor # We set fluxMin = 50 in setUp
49 sourceCat[fluxField + "Err"][-1] = 1.0
50 # Add some variability to the shapes to form a cluster with non-finite "width" in the mag-size plane
51 widthFactor = np.random.uniform(low=0.98, high=1.02)
52 sourceCat["truth_xx"][-1] = 3.0*widthFactor
53 sourceCat["truth_yy"][-1] = 3.0*widthFactor
54 sourceCat["truth_xy"][-1] = 1.0
57class TestObjectSizeSourceSelector(lsst.utils.tests.TestCase):
59 def setUp(self):
60 np.random.seed(100)
62 self.sourceSelector = sourceSelector.sourceSelectorRegistry["objectSize"]()
63 self.badFlags = self.sourceSelector.config.badFlags
64 schema = lsst.meas.base.tests.TestDataset.makeMinimalSchema()
65 self.sourceSelector.config.sourceFluxField = fluxField
66 self.sourceSelector.config.fluxMin = 50.0
67 schema.addField(fluxField, type=np.float64)
68 schema.addField(fluxField + "Err", type=np.float64)
69 for flag in self.badFlags:
70 schema.addField(flag, type="Flag")
71 self.sourceCat = afwTable.SourceCatalog(schema)
73 def tearDown(self):
74 del self.sourceCat
75 del self.badFlags
76 del self.sourceSelector
78 def testSelectSourcesGood(self):
79 for i in range(5):
80 addGoodSource(self.sourceCat, i)
81 result = self.sourceSelector.selectSources(self.sourceCat)
82 for src in self.sourceCat["id"]:
83 self.assertIn(src, self.sourceCat[result.selected]["id"])
85 def testSelectSourcesIndividualBadFlags(self):
86 for i in range(len(self.badFlags)):
87 addGoodSource(self.sourceCat, i)
88 for i in range(len(self.badFlags)):
89 for j, flag in enumerate(self.badFlags):
90 self.sourceCat[j].set(flag, True) if i == j else self.sourceCat[j].set(flag, False)
91 result = self.sourceSelector.selectSources(self.sourceCat)
92 self.assertNotIn(self.sourceCat[i]["id"], self.sourceCat[result.selected]["id"],
93 "should not have found %s" % flag)
95 def testSelectSourcesAllBadFlags(self):
96 for i, flag in enumerate(self.badFlags):
97 addGoodSource(self.sourceCat, i)
98 self.sourceCat[i].set(flag, True)
99 with self.assertRaises(RuntimeError):
100 self.sourceSelector.selectSources(self.sourceCat)
102 def testSelectSourcesSignalToNoiseCuts(self):
103 for i in range(10):
104 addGoodSource(self.sourceCat, i)
106 self.sourceCat[fluxField + "Err"][0] = self.sourceCat[fluxField][0]/20.0
107 self.sourceCat[fluxField + "Err"][1] = self.sourceCat[fluxField][1]/500.0
108 self.sourceCat[fluxField + "Err"][2] = self.sourceCat[fluxField][2]/2000.0
110 self.sourceSelector.config.doSignalToNoiseLimit = True
111 self.sourceSelector.config.doFluxLimit = False
112 self.sourceSelector.config.signalToNoiseMin = 50
113 self.sourceSelector.config.signalToNoiseMax = 1000
114 result = self.sourceSelector.run(self.sourceCat)
115 self.assertNotIn(self.sourceCat[0]["id"], result.sourceCat["id"])
116 self.assertIn(self.sourceCat[1]["id"], result.sourceCat["id"])
117 self.assertNotIn(self.sourceCat[2]["id"], result.sourceCat["id"])
119 def testSelectSourcesNoSignalToNoiseCut(self):
120 for i in range(5):
121 addGoodSource(self.sourceCat, i)
122 self.sourceCat[fluxField + "Err"][0] = self.sourceCat[fluxField][0]*1e+9 # S/N ~1e-9
123 self.sourceSelector.config.signalToNoiseMin = 0
124 result = self.sourceSelector.run(self.sourceCat)
125 self.assertIn(self.sourceCat[0]["id"], result.sourceCat["id"])
127 def testSelectSourcesFluxCuts(self):
128 for i in range(10):
129 addGoodSource(self.sourceCat, i)
131 self.sourceSelector.config.doSignalToNoiseLimit = False
132 self.sourceSelector.config.doFluxLimit = True
133 self.sourceSelector.config.fluxMin = 98.0 # Just outside of range allowed in addGoodSource()
134 self.sourceCat[fluxField][0] = 97.9
135 self.sourceSelector.config.fluxMax = 101.3 # Just outside of range allowed in addGoodSource()
136 self.sourceCat[fluxField][2] = 101.4
137 result = self.sourceSelector.run(self.sourceCat)
138 self.assertNotIn(self.sourceCat[0]["id"], result.sourceCat["id"])
139 self.assertIn(self.sourceCat[1]["id"], result.sourceCat["id"])
140 self.assertNotIn(self.sourceCat[2]["id"], result.sourceCat["id"])
143class TestMemory(lsst.utils.tests.MemoryTestCase):
144 pass
147def setup_module(module):
148 lsst.utils.tests.init()
151if __name__ == "__main__": 151 ↛ 152line 151 didn't jump to line 152, because the condition on line 151 was never true
152 lsst.utils.tests.init()
153 unittest.main()