Coverage for tests/test_ssoAssociationTask.py: 26%
61 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-19 02:58 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-19 02:58 -0800
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 numpy as np
23import pandas as pd
24import unittest
26from lsst.ap.association.ssoAssociation import SolarSystemAssociationTask
27import astshim as ast
28import lsst.geom as geom
29import lsst.afw.geom as afwGeom
30import lsst.meas.base.tests as measTests
31import lsst.utils.tests
34class TestSolarSystemAssociation(unittest.TestCase):
36 def setUp(self):
37 # Make fake sources
38 self.nSources = 10
39 self.bbox = geom.Box2I(geom.Point2I(0, 0),
40 geom.Extent2I(1024, 1153))
41 self.xyLoc = 100
42 dataset = measTests.TestDataset(self.bbox)
43 for srcIdx in range(self.nSources):
44 dataset.addSource(100000.0,
45 geom.Point2D(srcIdx*self.xyLoc,
46 srcIdx*self.xyLoc))
47 schema = dataset.makeMinimalSchema()
48 schema.addField("base_PixelFlags_flag", type="Flag")
49 schema.addField("base_PixelFlags_flag_offimage", type="Flag")
50 self.exposure, catalog = dataset.realize(
51 10.0, schema, randomSeed=1234)
52 for src in catalog:
53 src.setCoord(self.exposure.getWcs().pixelToSky(src.getCentroid()))
54 # Non-invertible WCS to test robustness to distortions.
55 # Coefficients transform (x - 1e-7*x^3 -> x, y -> y); see docs for PolyMap.
56 pixelCoeffs = np.array([[-1.0e-7, 1, 3, 0],
57 [1.0, 1, 1, 0],
58 [1.0, 2, 0, 1],
59 ])
60 self.exposure.setWcs(afwGeom.makeModifiedWcs(
61 afwGeom.TransformPoint2ToPoint2(ast.PolyMap(pixelCoeffs, 2, options="IterInverse=1")),
62 self.exposure.wcs,
63 modifyActualPixels=False
64 ))
66 # Convert to task required format
67 self.testDiaSources = catalog.asAstropy().to_pandas()
68 self.testDiaSources.rename(columns={"coord_ra": "ra",
69 "coord_dec": "decl"},
70 inplace=True,)
71 self.testDiaSources.loc[:, "ra"] = np.rad2deg(self.testDiaSources["ra"])
72 self.testDiaSources.loc[:, "decl"] = np.rad2deg(self.testDiaSources["decl"])
73 self.testDiaSources["ssObjectId"] = 0
75 # Grab a subset to treat as solar system objects
76 self.testSsObjects = self.testDiaSources[2:8].reset_index()
77 # Assign them ids starting from 1.
78 self.testSsObjects.loc[:, "ssObjectId"] = np.arange(
79 1, len(self.testSsObjects) + 1, dtype=int,)
80 self.testSsObjects["Err(arcsec)"] = np.ones(len(self.testSsObjects))
82 def test_run(self):
83 """Test that association and id assignment work as expected.
84 """
85 ssAssocTask = SolarSystemAssociationTask()
86 results = ssAssocTask.run(self.testDiaSources,
87 self.testSsObjects,
88 self.exposure)
89 self.assertEqual(self.nSources,
90 len(results.ssoAssocDiaSources)
91 + len(results.unAssocDiaSources))
92 self.assertEqual(len(self.testSsObjects),
93 len(results.ssoAssocDiaSources))
94 self.assertEqual(self.nSources - len(self.testSsObjects),
95 len(results.unAssocDiaSources))
96 for idx, ssObject in self.testSsObjects.iterrows():
97 self.assertEqual(
98 ssObject["ssObjectId"],
99 results.ssoAssocDiaSources.iloc[idx]["ssObjectId"])
101 def test_mask(self):
102 """Test that masking against the CCD bounding box works as expected.
103 """
104 ssAssocTask = SolarSystemAssociationTask()
105 # Test will all inside ccd
106 maskedObjects = ssAssocTask._maskToCcdRegion(self.testSsObjects,
107 self.exposure,
108 1.0)
109 self.assertEqual(len(maskedObjects), len(self.testSsObjects))
111 # Add a new SolarSystemObjects outside of the bbox and test that it
112 # is excluded.
113 testObjects = self.testSsObjects.loc[:2].reset_index(drop=True)
114 testObjects.loc[0, "ra"] = 150
115 testObjects.loc[0, "decl"] = 80
116 testObjects.loc[1, "ra"] = 150
117 testObjects.loc[1, "decl"] = -80
118 # Coordinates are chosen so that the inverse WCS erroneously maps them
119 # to inside the box (to (74.5, 600.6) instead of around (1745, 600.6)).
120 testObjects.loc[2, "ra"] = 44.91215199831453
121 testObjects.loc[2, "decl"] = 45.001331943391406
122 maskedObjects = ssAssocTask._maskToCcdRegion(
123 pd.concat([self.testSsObjects, testObjects]),
124 self.exposure,
125 1.0)
126 self.assertEqual(len(maskedObjects), len(self.testSsObjects))
129class MemoryTester(lsst.utils.tests.MemoryTestCase):
130 pass
133def setup_module(module):
134 lsst.utils.tests.init()
137if __name__ == "__main__": 137 ↛ 138line 137 didn't jump to line 138, because the condition on line 137 was never true
138 lsst.utils.tests.init()
139 unittest.main()