Coverage for tests/test_makeMatchStatistics.py: 18%
88 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-06 02:32 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-06 02:32 -0800
1#
2# LSST Data Management System
3# Copyright 2015 LSST Corporation.
4#
5# This product includes software developed by the
6# LSST Project (http://www.lsst.org/).
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the LSST License Statement and
19# the GNU General Public License along with this program. If not,
20# see <http://www.lsstcorp.org/LegalNotices/>.
21#
22import unittest
23import math
25import numpy as np
27import lsst.utils.tests
28import lsst.geom
29import lsst.afw.geom as afwGeom
30import lsst.afw.math as afwMath
31import lsst.afw.table as afwTable
32from lsst.meas.base import SingleFrameMeasurementTask
33import lsst.meas.astrom as measAstrom
34from functools import reduce
37class TestAstrometricSolver(lsst.utils.tests.TestCase):
39 def setUp(self):
40 # make a nominal match list where the distances are 0; test can then modify
41 # source centroid, reference coord or distance field for each match, as desired
42 self.wcs = afwGeom.makeSkyWcs(crpix=lsst.geom.Point2D(1500, 1500),
43 crval=lsst.geom.SpherePoint(215.5, 53.0, lsst.geom.degrees),
44 cdMatrix=afwGeom.makeCdMatrix(scale=5.1e-5*lsst.geom.degrees))
45 self.bboxD = lsst.geom.Box2D(lsst.geom.Point2D(10, 100), lsst.geom.Extent2D(1000, 1500))
46 self.numMatches = 25
48 sourceSchema = afwTable.SourceTable.makeMinimalSchema()
49 # add centroid (and many other unwanted fields) to sourceSchema
50 SingleFrameMeasurementTask(schema=sourceSchema)
51 self.sourceCentroidKey = afwTable.Point2DKey(sourceSchema["slot_Centroid"])
52 self.sourceCat = afwTable.SourceCatalog(sourceSchema)
54 refSchema = afwTable.SourceTable.makeMinimalSchema()
55 self.refCoordKey = afwTable.CoordKey(refSchema["coord"])
56 self.refCat = afwTable.SourceCatalog(refSchema)
58 self.matchList = []
60 np.random.seed(5)
61 pixPointList = [lsst.geom.Point2D(pos) for pos in
62 np.random.random_sample([self.numMatches, 2])*self.bboxD.getDimensions()
63 + self.bboxD.getMin()]
64 for pixPoint in pixPointList:
65 src = self.sourceCat.addNew()
66 src.set(self.sourceCentroidKey, pixPoint)
67 ref = self.refCat.addNew()
68 ref.set(self.refCoordKey, self.wcs.pixelToSky(pixPoint))
70 match = afwTable.ReferenceMatch(ref, src, 0)
71 self.matchList.append(match)
73 def tearDown(self):
74 del self.wcs
75 del self.bboxD
76 del self.sourceCentroidKey
77 del self.sourceCat
78 del self.refCoordKey
79 del self.refCat
80 del self.matchList
82 def testMakeMatchStatistics(self):
83 """Test makeMatchStatistics
84 """
85 np.random.seed(47)
86 distList = list((np.random.random_sample([self.numMatches]) - 0.5) * 10)
87 for dist, match in zip(distList, self.matchList):
88 match.distance = dist
89 itemList = (afwMath.MEDIAN, afwMath.MEANCLIP, afwMath.STDEV)
90 itemMask = reduce(lambda a, b: a | b, itemList)
91 distStats = measAstrom.makeMatchStatistics(self.matchList, itemMask)
92 directStats = afwMath.makeStatistics(distList, itemMask)
93 for item in itemList:
94 self.assertAlmostEqual(distStats.getValue(item), directStats.getValue(item))
96 def testMakeMatchStatisticsInRadians(self):
97 """Test makeMatchStatisticsInRadians
98 """
99 np.random.seed(164)
100 offLenList = [val*lsst.geom.radians for val in np.random.random_sample([self.numMatches])]
101 offDirList = [val*lsst.geom.radians for val in np.random.random_sample([self.numMatches])*math.pi*2]
102 for offLen, offDir, match in zip(offLenList, offDirList, self.matchList):
103 coord = match.first.get(self.refCoordKey)
104 offsetCoord = coord.offset(offDir, offLen)
105 match.first.set(self.refCoordKey, offsetCoord)
106 itemList = (afwMath.MEDIAN, afwMath.MEANCLIP, afwMath.IQRANGE)
107 itemMask = reduce(lambda a, b: a | b, itemList)
108 distStats = measAstrom.makeMatchStatisticsInRadians(self.wcs, self.matchList, itemMask)
109 distRadiansList = [val.asRadians() for val in offLenList]
110 directStats = afwMath.makeStatistics(distRadiansList, itemMask)
111 for item in itemList:
112 self.assertAlmostEqual(distStats.getValue(item), directStats.getValue(item))
114 def testMakeMatchStatisticsInPixels(self):
115 """Test testMakeMatchStatisticsInPixels
116 """
117 np.random.seed(164)
118 offList = [lsst.geom.Extent2D(val) for val in (np.random.random_sample([self.numMatches, 2])-0.5)*10]
119 for off, match in zip(offList, self.matchList):
120 centroid = match.second.get(self.sourceCentroidKey)
121 offCentroid = centroid + off
122 match.second.set(self.sourceCentroidKey, offCentroid)
123 itemList = (afwMath.MEDIAN, afwMath.MEAN, afwMath.STDEVCLIP)
124 itemMask = reduce(lambda a, b: a | b, itemList)
125 distStats = measAstrom.makeMatchStatisticsInPixels(self.wcs, self.matchList, itemMask)
126 distList = [math.hypot(*val) for val in offList]
127 directStats = afwMath.makeStatistics(distList, itemMask)
128 for item in itemList:
129 self.assertAlmostEqual(distStats.getValue(item), directStats.getValue(item))
132class MemoryTester(lsst.utils.tests.MemoryTestCase):
133 pass
136def setup_module(module):
137 lsst.utils.tests.init()
140if __name__ == "__main__": 140 ↛ 141line 140 didn't jump to line 141, because the condition on line 140 was never true
141 lsst.utils.tests.init()
142 unittest.main()