Coverage for tests/test_filterDiaSourceCatalog.py: 19%
85 statements
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-10 10:38 +0000
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-10 10:38 +0000
1# This file is part of ap_association.
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
24from lsst.ap.association.filterDiaSourceCatalog import (FilterDiaSourceCatalogConfig,
25 FilterDiaSourceCatalogTask)
26import lsst.geom as geom
27import lsst.meas.base.tests as measTests
28import lsst.utils.tests
29import lsst.afw.image as afwImage
30import lsst.daf.base as dafBase
33class TestFilterDiaSourceCatalogTask(unittest.TestCase):
35 def setUp(self):
36 self.nSources = 15
37 self.nSkySources = 5
38 self.yLoc = 100
39 self.expId = 4321
40 self.bbox = geom.Box2I(geom.Point2I(0, 0),
41 geom.Extent2I(1024, 1153))
42 dataset = measTests.TestDataset(self.bbox)
43 for srcIdx in range(self.nSources):
44 dataset.addSource(10000.0, geom.Point2D(srcIdx, self.yLoc))
45 schema = dataset.makeMinimalSchema()
46 schema.addField("sky_source", type="Flag", doc="Sky objects.")
47 schema.addField('ext_trailedSources_Naive_flag_off_image', type="Flag",
48 doc="Trail extends off image")
49 schema.addField('ext_trailedSources_Naive_flag_suspect_long_trail',
50 type="Flag", doc="Trail length is greater than three times the psf radius")
51 schema.addField('ext_trailedSources_Naive_flag_edge', type="Flag",
52 doc="Trail contains edge pixels")
53 schema.addField('ext_trailedSources_Naive_flag_nan', type="Flag",
54 doc="One or more trail coordinates are missing")
55 schema.addField('ext_trailedSources_Naive_length', type="F",
56 doc="Length of the source trail")
57 _, self.diaSourceCat = dataset.realize(10.0, schema, randomSeed=1234)
58 self.diaSourceCat[0:self.nSkySources]["sky_source"] = True
59 # The last 10 sources will all contained trail length measurements,
60 # increasing in size by 1.5 arcseconds. Only the last three will have
61 # lengths which are too long and will be filtered out.
62 self.nFilteredTrailedSources = 0
63 for srcIdx in range(5, 15):
64 self.diaSourceCat[srcIdx]["ext_trailedSources_Naive_length"] = 1.5*(srcIdx-4)
65 if 1.5*(srcIdx-4) > 36000/3600.0/24.0 * 30.0:
66 self.nFilteredTrailedSources += 1
67 # Setting a combination of flags for filtering in tests
68 self.diaSourceCat[5]["ext_trailedSources_Naive_flag_off_image"] = True
69 self.diaSourceCat[6]["ext_trailedSources_Naive_flag_suspect_long_trail"] = True
70 self.diaSourceCat[6]["ext_trailedSources_Naive_flag_edge"] = True
71 # As only two of these flags are set, the total number of filtered
72 # sources will be self.nFilteredTrailedSources + 2
73 self.nFilteredTrailedSources += 2
74 self.config = FilterDiaSourceCatalogConfig()
75 mjd = 57071.0
76 self.utc_jd = mjd + 2_400_000.5 - 35.0 / (24.0 * 60.0 * 60.0)
78 self.visitInfo = afwImage.VisitInfo(
79 # This incomplete visitInfo is sufficient for testing because the
80 # Python constructor sets all other required values to some
81 # default.
82 exposureTime=30.0,
83 darkTime=3.0,
84 date=dafBase.DateTime(mjd, system=dafBase.DateTime.MJD),
85 boresightRaDec=geom.SpherePoint(0.0, 0.0, geom.degrees),
86 )
88 def test_run_without_filter(self):
89 """Test that when all filters are turned off all sources in the catalog
90 are returned.
91 """
92 self.config.doRemoveSkySources = False
93 self.config.doWriteRejectedSkySources = False
94 self.config.doTrailedSourceFilter = False
95 filterDiaSourceCatalogTask = FilterDiaSourceCatalogTask(config=self.config)
96 result = filterDiaSourceCatalogTask.run(self.diaSourceCat, self.visitInfo)
97 self.assertEqual(len(result.filteredDiaSourceCat), len(self.diaSourceCat))
98 self.assertEqual(len(result.rejectedDiaSources), 0)
99 self.assertEqual(len(self.diaSourceCat), self.nSources)
101 def test_run_with_filter_sky_only(self):
102 """Test that when only the sky filter is turned on the first five
103 sources which are flagged as sky objects are filtered out of the
104 catalog and the rest are returned.
105 """
106 self.config.doRemoveSkySources = True
107 self.config.doWriteRejectedSkySources = True
108 self.config.doTrailedSourceFilter = False
109 filterDiaSourceCatalogTask = FilterDiaSourceCatalogTask(config=self.config)
110 result = filterDiaSourceCatalogTask.run(self.diaSourceCat, self.visitInfo)
111 nExpectedFilteredSources = self.nSources - self.nSkySources
112 self.assertEqual(len(result.filteredDiaSourceCat),
113 len(self.diaSourceCat[~self.diaSourceCat['sky_source']]))
114 self.assertEqual(len(result.filteredDiaSourceCat), nExpectedFilteredSources)
115 self.assertEqual(len(result.rejectedDiaSources), self.nSkySources)
116 self.assertEqual(len(self.diaSourceCat), self.nSources)
118 def test_run_with_filter_trailed_sources_only(self):
119 """Test that when only the trail filter is turned on the correct number
120 of sources are filtered out. The filtered sources should be the last
121 three sources which have long trails, one source where both the suspect
122 trail and edge trail flag are set, and one source where off_image is
123 set. All sky objects should remain in the catalog.
124 """
125 self.config.doRemoveSkySources = False
126 self.config.doWriteRejectedSkySources = False
127 self.config.doTrailedSourceFilter = True
128 filterDiaSourceCatalogTask = FilterDiaSourceCatalogTask(config=self.config)
129 result = filterDiaSourceCatalogTask.run(self.diaSourceCat, self.visitInfo)
130 nExpectedFilteredSources = self.nSources - self.nFilteredTrailedSources
131 self.assertEqual(len(result.filteredDiaSourceCat), nExpectedFilteredSources)
132 self.assertEqual(len(self.diaSourceCat), self.nSources)
134 def test_run_with_all_filters(self):
135 """Test that all sources are filtered out correctly. Only six sources
136 should remain in the catalog after filtering.
137 """
138 self.config.doRemoveSkySources = True
139 self.config.doWriteRejectedSkySources = True
140 self.config.doTrailedSourceFilter = True
141 filterDiaSourceCatalogTask = FilterDiaSourceCatalogTask(config=self.config)
142 result = filterDiaSourceCatalogTask.run(self.diaSourceCat, self.visitInfo)
143 nExpectedFilteredSources = self.nSources - self.nSkySources - self.nFilteredTrailedSources
144 # 5 filtered out sky sources
145 # 4 filtered out trailed sources, 2 with long trails 2 with flags
146 # 6 sources left
147 self.assertEqual(len(result.filteredDiaSourceCat), nExpectedFilteredSources)
148 self.assertEqual(len(result.rejectedDiaSources), self.nSkySources)
149 self.assertEqual(len(self.diaSourceCat), self.nSources)
152class MemoryTester(lsst.utils.tests.MemoryTestCase):
153 pass
156def setup_module(module):
157 lsst.utils.tests.init()
160if __name__ == "__main__": 160 ↛ 161line 160 didn't jump to line 161, because the condition on line 160 was never true
161 lsst.utils.tests.init()
162 unittest.main()