Coverage for tests/test_interpolate.py: 16%
97 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-27 02:52 -0700
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-27 02:52 -0700
1#
2# LSST Data Management System
3# Copyright 2008, 2009, 2010 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#
23"""
24Tests for Interpolate
26Run with:
27 python test_interpolate.py
28or
29 pytest test_interpolate.py
30"""
32import unittest
34import numpy as np
36import lsst.utils.tests
37import lsst.afw.math as afwMath
38import lsst.pex.exceptions as pexExcept
41class InterpolateTestCase(lsst.utils.tests.TestCase):
43 """A test case for Interpolate Linear"""
45 def setUp(self):
46 self.n = 10
47 self.x = np.zeros(self.n, dtype=float)
48 self.y1 = np.zeros(self.n, dtype=float)
49 self.y2 = np.zeros(self.n, dtype=float)
50 self.y0 = 1.0
51 self.dydx = 1.0
52 self.d2ydx2 = 0.5
54 for i in range(0, self.n, 1):
55 self.x[i] = i
56 self.y1[i] = self.dydx*self.x[i] + self.y0
57 self.y2[i] = self.d2ydx2*self.x[i] * \
58 self.x[i] + self.dydx*self.x[i] + self.y0
60 self.xtest = 4.5
61 self.y1test = self.dydx*self.xtest + self.y0
62 self.y2test = self.d2ydx2*self.xtest*self.xtest + self.dydx*self.xtest + self.y0
64 def tearDown(self):
65 del self.x
66 del self.y1
67 del self.y2
69 def testLinearRamp(self):
71 # === test the Linear Interpolator ============================
72 # default is akima spline
73 yinterpL = afwMath.makeInterpolate(self.x, self.y1)
74 youtL = yinterpL.interpolate(self.xtest)
76 self.assertEqual(youtL, self.y1test)
78 def testNaturalSplineRamp(self):
80 # === test the Spline interpolator =======================
81 # specify interp type with the string interface
82 yinterpS = afwMath.makeInterpolate(
83 self.x, self.y1, afwMath.Interpolate.NATURAL_SPLINE)
84 youtS = yinterpS.interpolate(self.xtest)
86 self.assertEqual(youtS, self.y1test)
88 def testAkimaSplineParabola(self):
89 """test the Spline interpolator"""
90 # specify interp type with the enum style interface
91 yinterpS = afwMath.makeInterpolate(
92 self.x, self.y2, afwMath.Interpolate.AKIMA_SPLINE)
93 youtS = yinterpS.interpolate(self.xtest)
95 self.assertEqual(youtS, self.y2test)
97 def testConstant(self):
98 """test the constant interpolator"""
99 # [xy]vec: point samples
100 # [xy]vec_c: centered values
101 xvec = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
102 xvec_c = np.array(
103 [-0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5])
104 yvec = np.array([1.0, 2.4, 5.0, 8.4, 13.0,
105 18.4, 25.0, 32.6, 41.0, 50.6])
106 yvec_c = np.array([1.0, 1.7, 3.7, 6.7, 10.7, 15.7,
107 21.7, 28.8, 36.8, 45.8, 50.6])
109 interp = afwMath.makeInterpolate(
110 xvec, yvec, afwMath.Interpolate.CONSTANT)
112 for x, y in zip(xvec_c, yvec_c):
113 self.assertAlmostEqual(interp.interpolate(x + 0.1), y)
114 self.assertAlmostEqual(interp.interpolate(x), y)
116 self.assertEqual(interp.interpolate(xvec[0] - 10), yvec[0])
117 n = len(yvec)
118 self.assertEqual(interp.interpolate(xvec[n - 1] + 10), yvec[n - 1])
120 # test caching as we go backwards
121 for x, y in reversed(list(zip(xvec_c, yvec_c))):
122 self.assertAlmostEqual(interp.interpolate(x + 0.1), y)
123 self.assertAlmostEqual(interp.interpolate(x), y)
125 i = 2
126 for x in np.arange(xvec_c[i], xvec_c[i + 1], 10):
127 self.assertEqual(interp.interpolate(x), yvec_c[i])
129 def testInvalidInputs(self):
130 """Test that invalid inputs cause an abort"""
132 with self.assertRaises(pexExcept.OutOfRangeError):
133 afwMath.makeInterpolate(np.array([], dtype=float), np.array([], dtype=float),
134 afwMath.Interpolate.CONSTANT)
136 afwMath.makeInterpolate(np.array([0], dtype=float), np.array([1], dtype=float),
137 afwMath.Interpolate.CONSTANT)
139 with self.assertRaises(pexExcept.OutOfRangeError):
140 afwMath.makeInterpolate(np.array([0], dtype=float), np.array([1], dtype=float),
141 afwMath.Interpolate.LINEAR)
143 def testLookupMaxInterpStyle(self):
144 for numPoints in range(1, 6):
145 maxInterpStyle = afwMath.lookupMaxInterpStyle(numPoints)
146 desiredMax = {
147 1: afwMath.Interpolate.Style.CONSTANT,
148 2: afwMath.Interpolate.Style.LINEAR,
149 3: afwMath.Interpolate.Style.CUBIC_SPLINE,
150 4: afwMath.Interpolate.Style.CUBIC_SPLINE,
151 }.get(numPoints, afwMath.Interpolate.Style.AKIMA_SPLINE)
152 self.assertEqual(maxInterpStyle, desiredMax)
154 for badNumPoints in (-5, -1, 0):
155 with self.assertRaises(pexExcept.InvalidParameterError):
156 afwMath.lookupMaxInterpStyle(badNumPoints)
158 def testLookupMinInterpPoints(self):
159 for style in afwMath.Interpolate.Style.__members__.values():
160 if style in (afwMath.Interpolate.Style.UNKNOWN, afwMath.Interpolate.Style.NUM_STYLES):
161 with self.assertRaises(pexExcept.OutOfRangeError):
162 afwMath.lookupMinInterpPoints(style)
163 else:
164 minPoints = afwMath.lookupMinInterpPoints(style)
165 desiredMin = {
166 afwMath.Interpolate.Style.CONSTANT: 1,
167 afwMath.Interpolate.Style.LINEAR: 2,
168 afwMath.Interpolate.Style.NATURAL_SPLINE: 3,
169 afwMath.Interpolate.Style.CUBIC_SPLINE: 3,
170 afwMath.Interpolate.Style.CUBIC_SPLINE_PERIODIC: 3,
171 afwMath.Interpolate.Style.AKIMA_SPLINE: 5,
172 afwMath.Interpolate.Style.AKIMA_SPLINE_PERIODIC: 5,
173 }.get(style, None)
174 if desiredMin is None:
175 self.fail(f"Unrecognized style: {style}")
176 self.assertEqual(minPoints, desiredMin)
178 def testStringToInterpStyle(self):
179 for name, desiredStyle in afwMath.Interpolate.Style.__members__.items():
180 if name in ("UNKNOWN", "NUM_STYLES"):
181 with self.assertRaises(pexExcept.InvalidParameterError):
182 afwMath.stringToInterpStyle(name)
183 else:
184 style = afwMath.stringToInterpStyle(name)
185 self.assertEqual(style, desiredStyle)
187 for badName in ("BOGUS", ""):
188 with self.assertRaises(pexExcept.InvalidParameterError):
189 afwMath.stringToInterpStyle(badName)
192class TestMemory(lsst.utils.tests.MemoryTestCase):
193 pass
196def setup_module(module):
197 lsst.utils.tests.init()
200if __name__ == "__main__": 200 ↛ 201line 200 didn't jump to line 201, because the condition on line 200 was never true
201 lsst.utils.tests.init()
202 unittest.main()