Coverage for tests/test_astrometrySourceSelector.py: 22%
98 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-05 09:34 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-05 09:34 +0000
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.
66 src['detect_isPrimary'] = True
69class TestAstrometrySourceSelector(lsst.utils.tests.TestCase):
71 def setUp(self):
72 schema = lsst.meas.base.tests.TestDataset.makeMinimalSchema()
73 schema.addField("slot_ApFlux_instFlux", type=np.float64)
74 schema.addField("slot_ApFlux_instFluxErr", type=np.float64)
75 schema.addField("detect_isPrimary", type="Flag")
76 for flag in badFlags + goodFlags:
77 schema.addField(flag, type="Flag")
79 self.src = afwTable.SourceCatalog(schema)
80 self.sourceSelector = sourceSelector.sourceSelectorRegistry['astrometry']()
82 def tearDown(self):
83 del self.src
84 del self.sourceSelector
86 def testSelectSources_good(self):
87 for i in range(5):
88 add_good_source(self.src, i)
89 for flag in goodFlags:
90 self.src[i].set(flag, True)
91 result = self.sourceSelector.selectSources(self.src)
92 # TODO: assertEqual doesn't work correctly on source catalogs.
93 # self.assertEqual(self.src[result.selected], self.src)
94 for x in self.src['id']:
95 self.assertIn(x, self.src[result.selected]['id'])
97 def testSelectSources_bad(self):
98 for i, flag in enumerate(badFlags):
99 add_good_source(self.src, i)
100 self.src[i].set(flag, True)
101 result = self.sourceSelector.selectSources(self.src)
102 for i, x in enumerate(self.src['id']):
103 self.assertNotIn(x, self.src[result.selected]['id'], "should not have found %s" % badFlags[i])
105 def testSelectSources_bad_centroid(self):
106 """NaN centroids should just assert."""
107 add_good_source(self.src, 1)
108 self.src[0].set('slot_Centroid_x', np.nan)
109 with self.assertRaises(AssertionError):
110 self.sourceSelector.selectSources(self.src)
111 self.src[0].set('slot_Centroid_x', 5.0)
112 self.src[0].set('slot_Centroid_y', np.nan)
113 with self.assertRaises(AssertionError):
114 self.sourceSelector.selectSources(self.src)
116 def testSelectSources_bad_centroid_Sigma(self):
117 """Reject sources with NaN centroid_[xy]Sigma.
118 Currently, there is no guarantee that a valid centroid_flag implies
119 a finite variance."""
120 add_good_source(self.src, 1)
121 add_good_source(self.src, 2)
122 self.src[0].set('slot_Centroid_xErr', np.nan)
123 self.src[1].set('slot_Centroid_yErr', np.nan)
124 result = self.sourceSelector.selectSources(self.src)
125 self.assertNotIn(self.src['id'][0], self.src[result.selected]['id'])
126 self.assertNotIn(self.src['id'][1], self.src[result.selected]['id'])
128 def testSelectSources_is_parent(self):
129 add_good_source(self.src, 1)
130 self.src[0].set('parent', 1)
131 result = self.sourceSelector.selectSources(self.src)
132 self.assertNotIn(self.src['id'][0], self.src[result.selected]['id'])
134 def testSelectSources_has_children(self):
135 add_good_source(self.src, 1)
136 self.src[0].set('deblend_nChild', 1)
137 result = self.sourceSelector.selectSources(self.src)
138 self.assertNotIn(self.src['id'][0], self.src[result.selected]['id'])
140 def testSelectSources_highSN_cut(self):
141 add_good_source(self.src, 1)
142 add_good_source(self.src, 2)
143 self.src['slot_ApFlux_instFlux'][0] = 20.
144 self.src['slot_ApFlux_instFlux'][1] = 1000.
146 self.sourceSelector.config.minSnr = 100
147 result = self.sourceSelector.selectSources(self.src)
148 self.assertNotIn(self.src[0]['id'], self.src[result.selected]['id'])
149 self.assertIn(self.src[1]['id'], self.src[result.selected]['id'])
151 def testSelectSources_no_SN_cut(self):
152 self.sourceSelector.config.minSnr = 0
153 add_good_source(self.src, 1)
154 self.src['slot_ApFlux_instFlux'][0] = 0
155 result = self.sourceSelector.selectSources(self.src)
156 self.assertIn(self.src[0]['id'], self.src[result.selected]['id'])
159class TestMemory(lsst.utils.tests.MemoryTestCase):
160 pass
163def setup_module(module):
164 lsst.utils.tests.init()
167if __name__ == "__main__": 167 ↛ 168line 167 didn't jump to line 168, because the condition on line 167 was never true
168 lsst.utils.tests.init()
169 unittest.main()