Coverage for tests/test_tableUtils.py: 19%
98 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-29 02:27 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-29 02:27 -0700
1# LSST Data Management System
2# Copyright 2016 LSST Corporation.
3#
4# This product includes software developed by the
5# LSST Project (http://www.lsst.org/).
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the LSST License Statement and
18# the GNU General Public License along with this program. If not,
19# see <http://www.lsstcorp.org/LegalNotices/>.
20#
21# The classes in this test are a little non-standard to reduce code
22# duplication and support automated unittest discovery.
23# A base class includes all the code that implements the testing and
24# itself inherits from unittest.TestCase. unittest automated discovery
25# will scan all classes that inherit from unittest.TestCase and invoke
26# any test methods found. To prevent this base class from being executed
27# the test methods are placed in a different class that does not inherit
28# from unittest.TestCase. The actual test classes then inherit from
29# both the testing class and the implementation class allowing test
30# discovery to only run tests found in the subclasses.
32import math
33import unittest
35import numpy as np
37import lsst.utils.tests
38import lsst.geom
39import lsst.afw.geom as afwGeom
40import lsst.afw.table as afwTable
43class UpdateTestCase(lsst.utils.tests.TestCase):
44 """A test case for the lsst.afw.table.updateRefCentroids and updateSourceCoords
45 """
47 def setUp(self):
48 self.crval = lsst.geom.SpherePoint(44.0, 45.0, lsst.geom.degrees)
49 self.crpix = lsst.geom.Point2D(15000, 4000)
51 arcsecPerPixel = 1/3600.0
52 cdMatrix = afwGeom.makeCdMatrix(arcsecPerPixel * lsst.geom.arcseconds)
53 self.wcs = afwGeom.makeSkyWcs(crval=self.crval, crpix=self.crpix, cdMatrix=cdMatrix)
55 refSchema = afwTable.SimpleTable.makeMinimalSchema()
56 self.refCentroidKey = afwTable.Point2DKey.addFields(
57 refSchema, "centroid", "centroid", "pixels")
58 self.refCoordKey = afwTable.CoordKey(refSchema["coord"])
59 self.refHasCentroidKey = refSchema.addField("hasCentroid", type="Flag")
60 self.refCat = afwTable.SimpleCatalog(refSchema)
62 # an alias is required to make src.getCentroid() work;
63 # simply defining a field named "slot_Centroid" doesn't suffice
64 srcSchema = afwTable.SourceTable.makeMinimalSchema()
65 self.srcCentroidKey = afwTable.Point2DKey.addFields(srcSchema, "base_SdssCentroid",
66 "centroid", "pixels")
67 srcAliases = srcSchema.getAliasMap()
68 srcAliases.set("slot_Centroid", "base_SdssCentroid")
69 self.srcCoordKey = afwTable.CoordKey(srcSchema["coord"])
70 self.sourceCat = afwTable.SourceCatalog(srcSchema)
72 def tearDown(self):
73 del self.wcs
74 del self.refCat
75 del self.sourceCat
77 def testNull(self):
78 """Check that an empty list causes no problems for either function"""
79 afwTable.updateRefCentroids(self.wcs, [])
80 afwTable.updateSourceCoords(self.wcs, [])
82 def testRefCenter(self):
83 """Check that a ref obj at the center is handled as expected"""
84 refObj = self.refCat.addNew()
85 refObj.set(self.refCoordKey, self.crval)
87 # initial centroid should be nan and hasCentroid False
88 nanRefCentroid = self.refCat[0].get(self.refCentroidKey)
89 for val in nanRefCentroid:
90 self.assertTrue(math.isnan(val))
91 self.assertFalse(self.refCat[0].get(self.refHasCentroidKey))
93 # computed centroid should be crpix and hasCentroid True
94 afwTable.updateRefCentroids(self.wcs, self.refCat)
95 refCentroid = self.refCat[0].get(self.refCentroidKey)
96 self.assertPairsAlmostEqual(refCentroid, self.crpix)
97 self.assertTrue(self.refCat[0].get(self.refHasCentroidKey))
99 # coord should not be changed
100 self.assertEqual(self.refCat[0].get(self.refCoordKey), self.crval)
102 def testSourceCenter(self):
103 """Check that a source at the center is handled as expected"""
104 src = self.sourceCat.addNew()
105 src.set(self.srcCentroidKey, self.crpix)
107 # initial coord should be nan; as a sanity-check
108 nanSourceCoord = self.sourceCat[0].get(self.srcCoordKey)
109 for val in nanSourceCoord:
110 self.assertTrue(math.isnan(val))
112 # compute coord should be crval
113 afwTable.updateSourceCoords(self.wcs, self.sourceCat)
114 srcCoord = self.sourceCat[0].get(self.srcCoordKey)
115 self.assertPairsAlmostEqual(srcCoord, self.crval)
117 # centroid should not be changed; also make sure that getCentroid words
118 self.assertEqual(self.sourceCat[0].getCentroid(), self.crpix)
120 def testLists(self):
121 """Check updating lists of reference objects and sources"""
122 # arbitrary but reasonable values that are intentionally different than
123 # testCatalogs
124 maxPix = 1000
125 numPoints = 10
126 self.setCatalogs(maxPix=maxPix, numPoints=numPoints)
128 # update the catalogs as lists
129 afwTable.updateSourceCoords(self.wcs, [s for s in self.sourceCat])
130 afwTable.updateRefCentroids(self.wcs, [r for r in self.refCat])
132 self.checkCatalogs()
134 def testCatalogs(self):
135 """Check updating catalogs of reference objects and sources"""
136 # arbitrary but reasonable values that are intentionally different than
137 # testLists
138 maxPix = 2000
139 numPoints = 9
140 self.setCatalogs(maxPix=maxPix, numPoints=numPoints)
142 # update the catalogs
143 afwTable.updateSourceCoords(self.wcs, self.sourceCat)
144 afwTable.updateRefCentroids(self.wcs, self.refCat)
146 # check that centroids and coords match
147 self.checkCatalogs()
149 def checkCatalogs(self, maxPixDiff=1e-5, maxSkyDiff=0.001*lsst.geom.arcseconds):
150 """Check that the source and reference object catalogs have equal centroids and coords"""
151 self.assertEqual(len(self.sourceCat), len(self.refCat))
153 for src, refObj in zip(self.sourceCat, self.refCat):
154 self.assertTrue(refObj.get(self.refHasCentroidKey))
155 srcCentroid = src.get(self.srcCentroidKey)
156 refCentroid = refObj.get(self.refCentroidKey)
157 self.assertPairsAlmostEqual(
158 srcCentroid, refCentroid, maxDiff=maxPixDiff)
160 srcCoord = src.get(self.srcCoordKey)
161 refCoord = refObj.get(self.refCoordKey)
162 self.assertSpherePointsAlmostEqual(
163 srcCoord, refCoord, maxSep=maxSkyDiff)
165 def setCatalogs(self, maxPix, numPoints):
166 """Set the source centroids and reference object coords
168 Set self.sourceCat centroids to a square grid of points
169 and set self.refCat coords to the corresponding sky positions
171 The catalogs must be empty to start
173 @param[in] maxPix maximum pixel position; used for both x and y;
174 the min is the negative of maxPix
175 @param[in] numPoints number of points in x or y; total points = numPoints*numPoints
176 """
177 if len(self.sourceCat) != 0:
178 raise RuntimeError("self.sourceCat must be empty")
179 if len(self.refCat) != 0:
180 raise RuntimeError("self.refCat must be empty")
182 for i in np.linspace(-maxPix, maxPix, numPoints):
183 for j in np.linspace(-maxPix, maxPix, numPoints):
184 centroid = lsst.geom.Point2D(i, j)
185 src = self.sourceCat.addNew()
186 src.set(self.srcCentroidKey, centroid)
188 refObj = self.refCat.addNew()
189 coord = self.wcs.pixelToSky(centroid)
190 refObj.set(self.refCoordKey, coord)
193class MemoryTester(lsst.utils.tests.MemoryTestCase):
194 pass
197def setup_module(module):
198 lsst.utils.tests.init()
201if __name__ == "__main__": 201 ↛ 202line 201 didn't jump to line 202, because the condition on line 201 was never true
202 lsst.utils.tests.init()
203 unittest.main()