Coverage for tests/test_chebyshev.py: 30%
64 statements
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-15 03:54 -0700
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-15 03:54 -0700
1# See COPYRIGHT file at the top of the source tree.
2#
3# This file is part of fgcmcal.
4#
5# Developed for the LSST Data Management System.
6# This product includes software developed by the LSST Project
7# (https://www.lsst.org).
8# See the COPYRIGHT file at the top-level directory of this distribution
9# for details of code ownership.
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation, either version 3 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program. If not, see <https://www.gnu.org/licenses/>.
23"""Test the fgcm and fgcmcal (stack) chebyshev polynomial code.
25Run small tests to ensure that the two chebyshev implementations are
26equivalent. The fgcm chebyshev polynomial code
27(`fgcm.fgcmUtilities.Cheb2dField`) was developed independently of the stack
28`lsst.afw.math.ChebyshevBoundedField`, so as to avoid dependencies.
29"""
31import unittest
32import numpy as np
34import lsst.afw.math as afwMath
35import lsst.geom
37import matplotlib
38matplotlib.use("Agg")
40import fgcm # noqa: E402
43class FgcmChebyshevTest(lsst.utils.tests.TestCase):
44 """
45 Test the fgcm and fgcmcal (stack) chebyshev polynomial code.
46 """
47 def setUp(self):
48 """
49 Set up test class.
50 """
51 self.xSize = 2000
52 self.ySize = 4000
53 self.nStar = 1000
55 self.order = 2
56 self.pars = np.zeros((self.order + 1, self.order + 1))
57 self.pars[0, 0] = 1.0
58 self.pars[0, 1] = 3e-3
59 self.pars[0, 2] = 1e-5
60 self.pars[1, 0] = 5e-3
61 self.pars[1, 1] = 7e-6
62 self.pars[1, 2] = 0.0
63 self.pars[2, 0] = 3e-5
64 self.pars[2, 1] = 0.0
65 self.pars[2, 2] = 0.0
67 self.order2 = 1
68 self.pars2 = np.zeros((self.order2 + 1, self.order2 + 1))
69 self.pars2[0, 0] = 0.98
70 self.pars2[0, 1] = 5e-3
71 self.pars2[1, 0] = 2e-2
73 def test_chebyshev_evaluate(self, seed=1000):
74 """
75 Test the evaluation of chebyshev polynomials.
77 Parameters
78 ----------
79 seed: `int`, optional
80 Numpy random seed
81 """
82 # Set numpy seed for stability
83 np.random.seed(seed=seed)
85 xPos = self.xSize * np.random.rand(self.nStar)
86 yPos = self.ySize * np.random.rand(self.nStar)
88 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
89 lsst.geom.Point2I(self.xSize - 1, self.ySize - 1))
91 # Compute the chebyshev values using the fgcm code
92 fgcmField = fgcm.fgcmUtilities.Cheb2dField(self.xSize, self.ySize,
93 self.pars)
94 fgcmValues = fgcmField.evaluate(xPos, yPos)
96 # Compute the chebyshev values using the afw code
97 field = afwMath.ChebyshevBoundedField(bbox, self.pars)
98 fieldValues = field.evaluate(xPos, yPos)
100 self.assertFloatsAlmostEqual(fieldValues, fgcmValues, rtol=1e-14)
102 def test_chebyshev_fit(self, seed=1000):
103 """
104 Test the fitting of chebyshev polynomials.
106 Parameters
107 ----------
108 seed: `int`, optional
109 Numpy random seed
110 """
111 # Set numpy seed for stability
112 np.random.seed(seed=seed)
114 # Generate some points to fit
115 xPos = self.xSize * np.random.rand(self.nStar)
116 yPos = self.ySize * np.random.rand(self.nStar)
117 fgcmField = fgcm.fgcmUtilities.Cheb2dField(self.xSize, self.ySize,
118 self.pars)
119 fgcmValues = fgcmField.evaluate(xPos, yPos)
121 # Fit the points using the fgcm code
122 fgcmField = fgcm.fgcmUtilities.Cheb2dField.fit(self.xSize, self.ySize,
123 self.order, xPos, yPos,
124 fgcmValues)
126 # Fit the points using the afw code
127 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
128 lsst.geom.Point2I(self.xSize - 1, self.ySize - 1))
130 ctrl = afwMath.ChebyshevBoundedFieldControl()
131 ctrl.orderX = self.order
132 ctrl.orderY = self.order
133 ctrl.triangular = True
134 field = afwMath.ChebyshevBoundedField.fit(bbox, xPos, yPos,
135 fgcmValues, ctrl)
137 # Compare the fit parameters
138 # The tolerance here must be looser than the application, I believe
139 # because of rounding errors in the fit implementations. But the
140 # good news is that a tolerance of 1e-9 in parameters in these
141 # tests yields a recovered tolerance of < 1e-14.
142 self.assertFloatsAlmostEqual(fgcmField.pars, field.getCoefficients(),
143 rtol=1e-9)
145 # And compare the input and output
146 fgcmValues2 = fgcmField.evaluate(xPos, yPos)
147 fieldValues2 = field.evaluate(xPos, yPos)
149 self.assertFloatsAlmostEqual(fgcmValues, fgcmValues2, rtol=1e-14)
150 self.assertFloatsAlmostEqual(fgcmValues2, fieldValues2, rtol=1e-14)
153class TestMemory(lsst.utils.tests.MemoryTestCase):
154 pass
157def setup_module(module):
158 lsst.utils.tests.init()
161if __name__ == "__main__": 161 ↛ 162line 161 didn't jump to line 162, because the condition on line 161 was never true
162 lsst.utils.tests.init()
163 unittest.main()