Coverage for tests/test_astrometrySourceSelector.py: 22%
96 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-23 02:20 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-23 02:20 -0700
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#
24import unittest
25import numpy as np
27import lsst.afw.table as afwTable
28from lsst.meas.algorithms import sourceSelector
29import lsst.meas.base.tests
30import lsst.utils.tests
32# badFlags are flags that, if the bad flag is set the object should be
33# immediately thrown out. This is as opposed to combinations of flags
34# signifying good or bad data. Such flags should then be a part of the
35# isGood test.
36badFlags = ["base_PixelFlags_flag_edge",
37 "base_PixelFlags_flag_interpolatedCenter",
38 "base_PixelFlags_flag_saturated",
39 "base_PixelFlags_flag_saturatedCenter",
40 "base_PixelFlags_flag_crCenter",
41 "base_PixelFlags_flag_bad",
42 "slot_Centroid_flag",
43 "slot_ApFlux_flag",
44 ]
46# goodFlags are flags that should NOT cause the object to be immediately
47# thrown out, despite their possibly ominous-sounding names.
48goodFlags = ["base_PixelFlags_flag_interpolated"]
51def add_good_source(src, num=0):
52 """Insert a likely-good source into the catalog."""
53 """
54 num is added to various values to distinguish them in catalogs with multiple objects.
55 """
56 src.addNew()
57 src['coord_ra'][-1] = 1. + num
58 src['coord_dec'][-1] = 2. + num
59 src['slot_Centroid_x'][-1] = 10. + num
60 src['slot_Centroid_y'][-1] = 20. + num
61 src['slot_Centroid_xErr'][-1] = 1. + num
62 src['slot_Centroid_yErr'][-1] = 2. + num
63 src['slot_Centroid_x_y_Cov'][-1] = 3. + num
64 src['slot_ApFlux_instFlux'][-1] = 100. + num
65 src['slot_ApFlux_instFluxErr'][-1] = 1.
68class TestAstrometrySourceSelector(lsst.utils.tests.TestCase):
70 def setUp(self):
71 schema = lsst.meas.base.tests.TestDataset.makeMinimalSchema()
72 schema.addField("slot_ApFlux_instFlux", type=np.float64)
73 schema.addField("slot_ApFlux_instFluxErr", type=np.float64)
74 for flag in badFlags + goodFlags:
75 schema.addField(flag, type="Flag")
77 self.src = afwTable.SourceCatalog(schema)
78 self.sourceSelector = sourceSelector.sourceSelectorRegistry['astrometry']()
80 def tearDown(self):
81 del self.src
82 del self.sourceSelector
84 def testSelectSources_good(self):
85 for i in range(5):
86 add_good_source(self.src, i)
87 for flag in goodFlags:
88 self.src[i].set(flag, True)
89 result = self.sourceSelector.selectSources(self.src)
90 # TODO: assertEqual doesn't work correctly on source catalogs.
91 # self.assertEqual(self.src[result.selected], self.src)
92 for x in self.src['id']:
93 self.assertIn(x, self.src[result.selected]['id'])
95 def testSelectSources_bad(self):
96 for i, flag in enumerate(badFlags):
97 add_good_source(self.src, i)
98 self.src[i].set(flag, True)
99 result = self.sourceSelector.selectSources(self.src)
100 for i, x in enumerate(self.src['id']):
101 self.assertNotIn(x, self.src[result.selected]['id'], "should not have found %s" % badFlags[i])
103 def testSelectSources_bad_centroid(self):
104 """NaN centroids should just assert."""
105 add_good_source(self.src, 1)
106 self.src[0].set('slot_Centroid_x', np.nan)
107 with self.assertRaises(AssertionError):
108 self.sourceSelector.selectSources(self.src)
109 self.src[0].set('slot_Centroid_x', 5.0)
110 self.src[0].set('slot_Centroid_y', np.nan)
111 with self.assertRaises(AssertionError):
112 self.sourceSelector.selectSources(self.src)
114 def testSelectSources_bad_centroid_Sigma(self):
115 """Reject sources with NaN centroid_[xy]Sigma.
116 Currently, there is no guarantee that a valid centroid_flag implies
117 a finite variance."""
118 add_good_source(self.src, 1)
119 add_good_source(self.src, 2)
120 self.src[0].set('slot_Centroid_xErr', np.nan)
121 self.src[1].set('slot_Centroid_yErr', np.nan)
122 result = self.sourceSelector.selectSources(self.src)
123 self.assertNotIn(self.src['id'][0], self.src[result.selected]['id'])
124 self.assertNotIn(self.src['id'][1], self.src[result.selected]['id'])
126 def testSelectSources_is_parent(self):
127 add_good_source(self.src, 1)
128 self.src[0].set('parent', 1)
129 result = self.sourceSelector.selectSources(self.src)
130 self.assertNotIn(self.src['id'][0], self.src[result.selected]['id'])
132 def testSelectSources_has_children(self):
133 add_good_source(self.src, 1)
134 self.src[0].set('deblend_nChild', 1)
135 result = self.sourceSelector.selectSources(self.src)
136 self.assertNotIn(self.src['id'][0], self.src[result.selected]['id'])
138 def testSelectSources_highSN_cut(self):
139 add_good_source(self.src, 1)
140 add_good_source(self.src, 2)
141 self.src['slot_ApFlux_instFlux'][0] = 20.
142 self.src['slot_ApFlux_instFlux'][1] = 1000.
144 self.sourceSelector.config.minSnr = 100
145 result = self.sourceSelector.selectSources(self.src)
146 self.assertNotIn(self.src[0]['id'], self.src[result.selected]['id'])
147 self.assertIn(self.src[1]['id'], self.src[result.selected]['id'])
149 def testSelectSources_no_SN_cut(self):
150 self.sourceSelector.config.minSnr = 0
151 add_good_source(self.src, 1)
152 self.src['slot_ApFlux_instFlux'][0] = 0
153 result = self.sourceSelector.selectSources(self.src)
154 self.assertIn(self.src[0]['id'], self.src[result.selected]['id'])
157class TestMemory(lsst.utils.tests.MemoryTestCase):
158 pass
161def setup_module(module):
162 lsst.utils.tests.init()
165if __name__ == "__main__": 165 ↛ 166line 165 didn't jump to line 166, because the condition on line 165 was never true
166 lsst.utils.tests.init()
167 unittest.main()