test_fitpack2.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. # Created by Pearu Peterson, June 2003
  2. from __future__ import division, print_function, absolute_import
  3. import numpy as np
  4. from numpy.testing import (assert_equal, assert_almost_equal, assert_array_equal,
  5. assert_array_almost_equal, assert_allclose)
  6. from scipy._lib._numpy_compat import suppress_warnings
  7. from pytest import raises as assert_raises
  8. from numpy import array, diff, linspace, meshgrid, ones, pi, shape
  9. from scipy.interpolate.fitpack import bisplrep, bisplev
  10. from scipy.interpolate.fitpack2 import (UnivariateSpline,
  11. LSQUnivariateSpline, InterpolatedUnivariateSpline,
  12. LSQBivariateSpline, SmoothBivariateSpline, RectBivariateSpline,
  13. LSQSphereBivariateSpline, SmoothSphereBivariateSpline,
  14. RectSphereBivariateSpline)
  15. class TestUnivariateSpline(object):
  16. def test_linear_constant(self):
  17. x = [1,2,3]
  18. y = [3,3,3]
  19. lut = UnivariateSpline(x,y,k=1)
  20. assert_array_almost_equal(lut.get_knots(),[1,3])
  21. assert_array_almost_equal(lut.get_coeffs(),[3,3])
  22. assert_almost_equal(lut.get_residual(),0.0)
  23. assert_array_almost_equal(lut([1,1.5,2]),[3,3,3])
  24. def test_preserve_shape(self):
  25. x = [1, 2, 3]
  26. y = [0, 2, 4]
  27. lut = UnivariateSpline(x, y, k=1)
  28. arg = 2
  29. assert_equal(shape(arg), shape(lut(arg)))
  30. assert_equal(shape(arg), shape(lut(arg, nu=1)))
  31. arg = [1.5, 2, 2.5]
  32. assert_equal(shape(arg), shape(lut(arg)))
  33. assert_equal(shape(arg), shape(lut(arg, nu=1)))
  34. def test_linear_1d(self):
  35. x = [1,2,3]
  36. y = [0,2,4]
  37. lut = UnivariateSpline(x,y,k=1)
  38. assert_array_almost_equal(lut.get_knots(),[1,3])
  39. assert_array_almost_equal(lut.get_coeffs(),[0,4])
  40. assert_almost_equal(lut.get_residual(),0.0)
  41. assert_array_almost_equal(lut([1,1.5,2]),[0,1,2])
  42. def test_subclassing(self):
  43. # See #731
  44. class ZeroSpline(UnivariateSpline):
  45. def __call__(self, x):
  46. return 0*array(x)
  47. sp = ZeroSpline([1,2,3,4,5], [3,2,3,2,3], k=2)
  48. assert_array_equal(sp([1.5, 2.5]), [0., 0.])
  49. def test_empty_input(self):
  50. # Test whether empty input returns an empty output. Ticket 1014
  51. x = [1,3,5,7,9]
  52. y = [0,4,9,12,21]
  53. spl = UnivariateSpline(x, y, k=3)
  54. assert_array_equal(spl([]), array([]))
  55. def test_resize_regression(self):
  56. """Regression test for #1375."""
  57. x = [-1., -0.65016502, -0.58856235, -0.26903553, -0.17370892,
  58. -0.10011001, 0., 0.10011001, 0.17370892, 0.26903553, 0.58856235,
  59. 0.65016502, 1.]
  60. y = [1.,0.62928599, 0.5797223, 0.39965815, 0.36322694, 0.3508061,
  61. 0.35214793, 0.3508061, 0.36322694, 0.39965815, 0.5797223,
  62. 0.62928599, 1.]
  63. w = [1.00000000e+12, 6.88875973e+02, 4.89314737e+02, 4.26864807e+02,
  64. 6.07746770e+02, 4.51341444e+02, 3.17480210e+02, 4.51341444e+02,
  65. 6.07746770e+02, 4.26864807e+02, 4.89314737e+02, 6.88875973e+02,
  66. 1.00000000e+12]
  67. spl = UnivariateSpline(x=x, y=y, w=w, s=None)
  68. desired = array([0.35100374, 0.51715855, 0.87789547, 0.98719344])
  69. assert_allclose(spl([0.1, 0.5, 0.9, 0.99]), desired, atol=5e-4)
  70. def test_out_of_range_regression(self):
  71. # Test different extrapolation modes. See ticket 3557
  72. x = np.arange(5, dtype=float)
  73. y = x**3
  74. xp = linspace(-8, 13, 100)
  75. xp_zeros = xp.copy()
  76. xp_zeros[np.logical_or(xp_zeros < 0., xp_zeros > 4.)] = 0
  77. xp_clip = xp.copy()
  78. xp_clip[xp_clip < x[0]] = x[0]
  79. xp_clip[xp_clip > x[-1]] = x[-1]
  80. for cls in [UnivariateSpline, InterpolatedUnivariateSpline]:
  81. spl = cls(x=x, y=y)
  82. for ext in [0, 'extrapolate']:
  83. assert_allclose(spl(xp, ext=ext), xp**3, atol=1e-16)
  84. assert_allclose(cls(x, y, ext=ext)(xp), xp**3, atol=1e-16)
  85. for ext in [1, 'zeros']:
  86. assert_allclose(spl(xp, ext=ext), xp_zeros**3, atol=1e-16)
  87. assert_allclose(cls(x, y, ext=ext)(xp), xp_zeros**3, atol=1e-16)
  88. for ext in [2, 'raise']:
  89. assert_raises(ValueError, spl, xp, **dict(ext=ext))
  90. for ext in [3, 'const']:
  91. assert_allclose(spl(xp, ext=ext), xp_clip**3, atol=1e-16)
  92. assert_allclose(cls(x, y, ext=ext)(xp), xp_clip**3, atol=1e-16)
  93. # also test LSQUnivariateSpline [which needs explicit knots]
  94. t = spl.get_knots()[3:4] # interior knots w/ default k=3
  95. spl = LSQUnivariateSpline(x, y, t)
  96. assert_allclose(spl(xp, ext=0), xp**3, atol=1e-16)
  97. assert_allclose(spl(xp, ext=1), xp_zeros**3, atol=1e-16)
  98. assert_raises(ValueError, spl, xp, **dict(ext=2))
  99. assert_allclose(spl(xp, ext=3), xp_clip**3, atol=1e-16)
  100. # also make sure that unknown values for `ext` are caught early
  101. for ext in [-1, 'unknown']:
  102. spl = UnivariateSpline(x, y)
  103. assert_raises(ValueError, spl, xp, **dict(ext=ext))
  104. assert_raises(ValueError, UnivariateSpline,
  105. **dict(x=x, y=y, ext=ext))
  106. def test_lsq_fpchec(self):
  107. xs = np.arange(100) * 1.
  108. ys = np.arange(100) * 1.
  109. knots = np.linspace(0, 99, 10)
  110. bbox = (-1, 101)
  111. assert_raises(ValueError, LSQUnivariateSpline, xs, ys, knots,
  112. bbox=bbox)
  113. def test_derivative_and_antiderivative(self):
  114. # Thin wrappers to splder/splantider, so light smoke test only.
  115. x = np.linspace(0, 1, 70)**3
  116. y = np.cos(x)
  117. spl = UnivariateSpline(x, y, s=0)
  118. spl2 = spl.antiderivative(2).derivative(2)
  119. assert_allclose(spl(0.3), spl2(0.3))
  120. spl2 = spl.antiderivative(1)
  121. assert_allclose(spl2(0.6) - spl2(0.2),
  122. spl.integral(0.2, 0.6))
  123. def test_integral_out_of_bounds(self):
  124. # Regression test for gh-7906: .integral(a, b) is wrong if both
  125. # a and b are out-of-bounds
  126. x = np.linspace(0., 1., 7)
  127. for ext in range(4):
  128. f = UnivariateSpline(x, x, s=0, ext=ext)
  129. for (a, b) in [(1, 1), (1, 5), (2, 5),
  130. (0, 0), (-2, 0), (-2, -1)]:
  131. assert_allclose(f.integral(a, b), 0, atol=1e-15)
  132. def test_nan(self):
  133. # bail out early if the input data contains nans
  134. x = np.arange(10, dtype=float)
  135. y = x**3
  136. w = np.ones_like(x)
  137. # also test LSQUnivariateSpline [which needs explicit knots]
  138. spl = UnivariateSpline(x, y, check_finite=True)
  139. t = spl.get_knots()[3:4] # interior knots w/ default k=3
  140. y_end = y[-1]
  141. for z in [np.nan, np.inf, -np.inf]:
  142. y[-1] = z
  143. assert_raises(ValueError, UnivariateSpline,
  144. **dict(x=x, y=y, check_finite=True))
  145. assert_raises(ValueError, InterpolatedUnivariateSpline,
  146. **dict(x=x, y=y, check_finite=True))
  147. assert_raises(ValueError, LSQUnivariateSpline,
  148. **dict(x=x, y=y, t=t, check_finite=True))
  149. y[-1] = y_end # check valid y but invalid w
  150. w[-1] = z
  151. assert_raises(ValueError, UnivariateSpline,
  152. **dict(x=x, y=y, w=w, check_finite=True))
  153. assert_raises(ValueError, InterpolatedUnivariateSpline,
  154. **dict(x=x, y=y, w=w, check_finite=True))
  155. assert_raises(ValueError, LSQUnivariateSpline,
  156. **dict(x=x, y=y, t=t, w=w, check_finite=True))
  157. def test_increasing_x(self):
  158. xx = np.arange(10, dtype=float)
  159. yy = xx**3
  160. x = np.arange(10, dtype=float)
  161. x[1] = x[0]
  162. y = x**3
  163. w = np.ones_like(x)
  164. # also test LSQUnivariateSpline [which needs explicit knots]
  165. spl = UnivariateSpline(xx, yy, check_finite=True)
  166. t = spl.get_knots()[3:4] # interior knots w/ default k=3
  167. assert_raises(ValueError, UnivariateSpline,
  168. **dict(x=x, y=y, check_finite=True))
  169. assert_raises(ValueError, InterpolatedUnivariateSpline,
  170. **dict(x=x, y=y, check_finite=True))
  171. assert_raises(ValueError, LSQUnivariateSpline,
  172. **dict(x=x, y=y, t=t, w=w, check_finite=True))
  173. class TestLSQBivariateSpline(object):
  174. # NOTE: The systems in this test class are rank-deficient
  175. def test_linear_constant(self):
  176. x = [1,1,1,2,2,2,3,3,3]
  177. y = [1,2,3,1,2,3,1,2,3]
  178. z = [3,3,3,3,3,3,3,3,3]
  179. s = 0.1
  180. tx = [1+s,3-s]
  181. ty = [1+s,3-s]
  182. with suppress_warnings() as sup:
  183. r = sup.record(UserWarning, "\nThe coefficients of the spline")
  184. lut = LSQBivariateSpline(x,y,z,tx,ty,kx=1,ky=1)
  185. assert_equal(len(r), 1)
  186. assert_almost_equal(lut(2,2), 3.)
  187. def test_bilinearity(self):
  188. x = [1,1,1,2,2,2,3,3,3]
  189. y = [1,2,3,1,2,3,1,2,3]
  190. z = [0,7,8,3,4,7,1,3,4]
  191. s = 0.1
  192. tx = [1+s,3-s]
  193. ty = [1+s,3-s]
  194. with suppress_warnings() as sup:
  195. # This seems to fail (ier=1, see ticket 1642).
  196. sup.filter(UserWarning, "\nThe coefficients of the spline")
  197. lut = LSQBivariateSpline(x,y,z,tx,ty,kx=1,ky=1)
  198. tx, ty = lut.get_knots()
  199. for xa, xb in zip(tx[:-1], tx[1:]):
  200. for ya, yb in zip(ty[:-1], ty[1:]):
  201. for t in [0.1, 0.5, 0.9]:
  202. for s in [0.3, 0.4, 0.7]:
  203. xp = xa*(1-t) + xb*t
  204. yp = ya*(1-s) + yb*s
  205. zp = (+ lut(xa, ya)*(1-t)*(1-s)
  206. + lut(xb, ya)*t*(1-s)
  207. + lut(xa, yb)*(1-t)*s
  208. + lut(xb, yb)*t*s)
  209. assert_almost_equal(lut(xp,yp), zp)
  210. def test_integral(self):
  211. x = [1,1,1,2,2,2,8,8,8]
  212. y = [1,2,3,1,2,3,1,2,3]
  213. z = array([0,7,8,3,4,7,1,3,4])
  214. s = 0.1
  215. tx = [1+s,3-s]
  216. ty = [1+s,3-s]
  217. with suppress_warnings() as sup:
  218. r = sup.record(UserWarning, "\nThe coefficients of the spline")
  219. lut = LSQBivariateSpline(x, y, z, tx, ty, kx=1, ky=1)
  220. assert_equal(len(r), 1)
  221. tx, ty = lut.get_knots()
  222. tz = lut(tx, ty)
  223. trpz = .25*(diff(tx)[:,None]*diff(ty)[None,:]
  224. * (tz[:-1,:-1]+tz[1:,:-1]+tz[:-1,1:]+tz[1:,1:])).sum()
  225. assert_almost_equal(lut.integral(tx[0], tx[-1], ty[0], ty[-1]),
  226. trpz)
  227. def test_empty_input(self):
  228. # Test whether empty inputs returns an empty output. Ticket 1014
  229. x = [1,1,1,2,2,2,3,3,3]
  230. y = [1,2,3,1,2,3,1,2,3]
  231. z = [3,3,3,3,3,3,3,3,3]
  232. s = 0.1
  233. tx = [1+s,3-s]
  234. ty = [1+s,3-s]
  235. with suppress_warnings() as sup:
  236. r = sup.record(UserWarning, "\nThe coefficients of the spline")
  237. lut = LSQBivariateSpline(x, y, z, tx, ty, kx=1, ky=1)
  238. assert_equal(len(r), 1)
  239. assert_array_equal(lut([], []), np.zeros((0,0)))
  240. assert_array_equal(lut([], [], grid=False), np.zeros((0,)))
  241. class TestSmoothBivariateSpline(object):
  242. def test_linear_constant(self):
  243. x = [1,1,1,2,2,2,3,3,3]
  244. y = [1,2,3,1,2,3,1,2,3]
  245. z = [3,3,3,3,3,3,3,3,3]
  246. lut = SmoothBivariateSpline(x,y,z,kx=1,ky=1)
  247. assert_array_almost_equal(lut.get_knots(),([1,1,3,3],[1,1,3,3]))
  248. assert_array_almost_equal(lut.get_coeffs(),[3,3,3,3])
  249. assert_almost_equal(lut.get_residual(),0.0)
  250. assert_array_almost_equal(lut([1,1.5,2],[1,1.5]),[[3,3],[3,3],[3,3]])
  251. def test_linear_1d(self):
  252. x = [1,1,1,2,2,2,3,3,3]
  253. y = [1,2,3,1,2,3,1,2,3]
  254. z = [0,0,0,2,2,2,4,4,4]
  255. lut = SmoothBivariateSpline(x,y,z,kx=1,ky=1)
  256. assert_array_almost_equal(lut.get_knots(),([1,1,3,3],[1,1,3,3]))
  257. assert_array_almost_equal(lut.get_coeffs(),[0,0,4,4])
  258. assert_almost_equal(lut.get_residual(),0.0)
  259. assert_array_almost_equal(lut([1,1.5,2],[1,1.5]),[[0,0],[1,1],[2,2]])
  260. def test_integral(self):
  261. x = [1,1,1,2,2,2,4,4,4]
  262. y = [1,2,3,1,2,3,1,2,3]
  263. z = array([0,7,8,3,4,7,1,3,4])
  264. with suppress_warnings() as sup:
  265. # This seems to fail (ier=1, see ticket 1642).
  266. sup.filter(UserWarning, "\nThe required storage space")
  267. lut = SmoothBivariateSpline(x, y, z, kx=1, ky=1, s=0)
  268. tx = [1,2,4]
  269. ty = [1,2,3]
  270. tz = lut(tx, ty)
  271. trpz = .25*(diff(tx)[:,None]*diff(ty)[None,:]
  272. * (tz[:-1,:-1]+tz[1:,:-1]+tz[:-1,1:]+tz[1:,1:])).sum()
  273. assert_almost_equal(lut.integral(tx[0], tx[-1], ty[0], ty[-1]), trpz)
  274. lut2 = SmoothBivariateSpline(x, y, z, kx=2, ky=2, s=0)
  275. assert_almost_equal(lut2.integral(tx[0], tx[-1], ty[0], ty[-1]), trpz,
  276. decimal=0) # the quadratures give 23.75 and 23.85
  277. tz = lut(tx[:-1], ty[:-1])
  278. trpz = .25*(diff(tx[:-1])[:,None]*diff(ty[:-1])[None,:]
  279. * (tz[:-1,:-1]+tz[1:,:-1]+tz[:-1,1:]+tz[1:,1:])).sum()
  280. assert_almost_equal(lut.integral(tx[0], tx[-2], ty[0], ty[-2]), trpz)
  281. def test_rerun_lwrk2_too_small(self):
  282. # in this setting, lwrk2 is too small in the default run. Here we
  283. # check for equality with the bisplrep/bisplev output because there,
  284. # an automatic re-run of the spline representation is done if ier>10.
  285. x = np.linspace(-2, 2, 80)
  286. y = np.linspace(-2, 2, 80)
  287. z = x + y
  288. xi = np.linspace(-1, 1, 100)
  289. yi = np.linspace(-2, 2, 100)
  290. tck = bisplrep(x, y, z)
  291. res1 = bisplev(xi, yi, tck)
  292. interp_ = SmoothBivariateSpline(x, y, z)
  293. res2 = interp_(xi, yi)
  294. assert_almost_equal(res1, res2)
  295. class TestLSQSphereBivariateSpline(object):
  296. def setup_method(self):
  297. # define the input data and coordinates
  298. ntheta, nphi = 70, 90
  299. theta = linspace(0.5/(ntheta - 1), 1 - 0.5/(ntheta - 1), ntheta) * pi
  300. phi = linspace(0.5/(nphi - 1), 1 - 0.5/(nphi - 1), nphi) * 2. * pi
  301. data = ones((theta.shape[0], phi.shape[0]))
  302. # define knots and extract data values at the knots
  303. knotst = theta[::5]
  304. knotsp = phi[::5]
  305. knotdata = data[::5, ::5]
  306. # calculate spline coefficients
  307. lats, lons = meshgrid(theta, phi)
  308. lut_lsq = LSQSphereBivariateSpline(lats.ravel(), lons.ravel(),
  309. data.T.ravel(), knotst, knotsp)
  310. self.lut_lsq = lut_lsq
  311. self.data = knotdata
  312. self.new_lons, self.new_lats = knotsp, knotst
  313. def test_linear_constant(self):
  314. assert_almost_equal(self.lut_lsq.get_residual(), 0.0)
  315. assert_array_almost_equal(self.lut_lsq(self.new_lats, self.new_lons),
  316. self.data)
  317. def test_empty_input(self):
  318. assert_array_almost_equal(self.lut_lsq([], []), np.zeros((0,0)))
  319. assert_array_almost_equal(self.lut_lsq([], [], grid=False), np.zeros((0,)))
  320. class TestSmoothSphereBivariateSpline(object):
  321. def setup_method(self):
  322. theta = array([.25*pi, .25*pi, .25*pi, .5*pi, .5*pi, .5*pi, .75*pi,
  323. .75*pi, .75*pi])
  324. phi = array([.5 * pi, pi, 1.5 * pi, .5 * pi, pi, 1.5 * pi, .5 * pi, pi,
  325. 1.5 * pi])
  326. r = array([3, 3, 3, 3, 3, 3, 3, 3, 3])
  327. self.lut = SmoothSphereBivariateSpline(theta, phi, r, s=1E10)
  328. def test_linear_constant(self):
  329. assert_almost_equal(self.lut.get_residual(), 0.)
  330. assert_array_almost_equal(self.lut([1, 1.5, 2],[1, 1.5]),
  331. [[3, 3], [3, 3], [3, 3]])
  332. def test_empty_input(self):
  333. assert_array_almost_equal(self.lut([], []), np.zeros((0,0)))
  334. assert_array_almost_equal(self.lut([], [], grid=False), np.zeros((0,)))
  335. class TestRectBivariateSpline(object):
  336. def test_defaults(self):
  337. x = array([1,2,3,4,5])
  338. y = array([1,2,3,4,5])
  339. z = array([[1,2,1,2,1],[1,2,1,2,1],[1,2,3,2,1],[1,2,2,2,1],[1,2,1,2,1]])
  340. lut = RectBivariateSpline(x,y,z)
  341. assert_array_almost_equal(lut(x,y),z)
  342. def test_evaluate(self):
  343. x = array([1,2,3,4,5])
  344. y = array([1,2,3,4,5])
  345. z = array([[1,2,1,2,1],[1,2,1,2,1],[1,2,3,2,1],[1,2,2,2,1],[1,2,1,2,1]])
  346. lut = RectBivariateSpline(x,y,z)
  347. xi = [1, 2.3, 5.3, 0.5, 3.3, 1.2, 3]
  348. yi = [1, 3.3, 1.2, 4.0, 5.0, 1.0, 3]
  349. zi = lut.ev(xi, yi)
  350. zi2 = array([lut(xp, yp)[0,0] for xp, yp in zip(xi, yi)])
  351. assert_almost_equal(zi, zi2)
  352. def test_derivatives_grid(self):
  353. x = array([1,2,3,4,5])
  354. y = array([1,2,3,4,5])
  355. z = array([[1,2,1,2,1],[1,2,1,2,1],[1,2,3,2,1],[1,2,2,2,1],[1,2,1,2,1]])
  356. dx = array([[0,0,-20,0,0],[0,0,13,0,0],[0,0,4,0,0],
  357. [0,0,-11,0,0],[0,0,4,0,0]])/6.
  358. dy = array([[4,-1,0,1,-4],[4,-1,0,1,-4],[0,1.5,0,-1.5,0],
  359. [2,.25,0,-.25,-2],[4,-1,0,1,-4]])
  360. dxdy = array([[40,-25,0,25,-40],[-26,16.25,0,-16.25,26],
  361. [-8,5,0,-5,8],[22,-13.75,0,13.75,-22],[-8,5,0,-5,8]])/6.
  362. lut = RectBivariateSpline(x,y,z)
  363. assert_array_almost_equal(lut(x,y,dx=1),dx)
  364. assert_array_almost_equal(lut(x,y,dy=1),dy)
  365. assert_array_almost_equal(lut(x,y,dx=1,dy=1),dxdy)
  366. def test_derivatives(self):
  367. x = array([1,2,3,4,5])
  368. y = array([1,2,3,4,5])
  369. z = array([[1,2,1,2,1],[1,2,1,2,1],[1,2,3,2,1],[1,2,2,2,1],[1,2,1,2,1]])
  370. dx = array([0,0,2./3,0,0])
  371. dy = array([4,-1,0,-.25,-4])
  372. dxdy = array([160,65,0,55,32])/24.
  373. lut = RectBivariateSpline(x,y,z)
  374. assert_array_almost_equal(lut(x,y,dx=1,grid=False),dx)
  375. assert_array_almost_equal(lut(x,y,dy=1,grid=False),dy)
  376. assert_array_almost_equal(lut(x,y,dx=1,dy=1,grid=False),dxdy)
  377. def test_broadcast(self):
  378. x = array([1,2,3,4,5])
  379. y = array([1,2,3,4,5])
  380. z = array([[1,2,1,2,1],[1,2,1,2,1],[1,2,3,2,1],[1,2,2,2,1],[1,2,1,2,1]])
  381. lut = RectBivariateSpline(x,y,z)
  382. assert_allclose(lut(x, y), lut(x[:,None], y[None,:], grid=False))
  383. class TestRectSphereBivariateSpline(object):
  384. def test_defaults(self):
  385. y = linspace(0.01, 2*pi-0.01, 7)
  386. x = linspace(0.01, pi-0.01, 7)
  387. z = array([[1,2,1,2,1,2,1],[1,2,1,2,1,2,1],[1,2,3,2,1,2,1],
  388. [1,2,2,2,1,2,1],[1,2,1,2,1,2,1],[1,2,2,2,1,2,1],
  389. [1,2,1,2,1,2,1]])
  390. lut = RectSphereBivariateSpline(x,y,z)
  391. assert_array_almost_equal(lut(x,y),z)
  392. def test_evaluate(self):
  393. y = linspace(0.01, 2*pi-0.01, 7)
  394. x = linspace(0.01, pi-0.01, 7)
  395. z = array([[1,2,1,2,1,2,1],[1,2,1,2,1,2,1],[1,2,3,2,1,2,1],
  396. [1,2,2,2,1,2,1],[1,2,1,2,1,2,1],[1,2,2,2,1,2,1],
  397. [1,2,1,2,1,2,1]])
  398. lut = RectSphereBivariateSpline(x,y,z)
  399. yi = [0.2, 1, 2.3, 2.35, 3.0, 3.99, 5.25]
  400. xi = [1.5, 0.4, 1.1, 0.45, 0.2345, 1., 0.0001]
  401. zi = lut.ev(xi, yi)
  402. zi2 = array([lut(xp, yp)[0,0] for xp, yp in zip(xi, yi)])
  403. assert_almost_equal(zi, zi2)
  404. def test_derivatives_grid(self):
  405. y = linspace(0.01, 2*pi-0.01, 7)
  406. x = linspace(0.01, pi-0.01, 7)
  407. z = array([[1,2,1,2,1,2,1],[1,2,1,2,1,2,1],[1,2,3,2,1,2,1],
  408. [1,2,2,2,1,2,1],[1,2,1,2,1,2,1],[1,2,2,2,1,2,1],
  409. [1,2,1,2,1,2,1]])
  410. lut = RectSphereBivariateSpline(x,y,z)
  411. y = linspace(0.02, 2*pi-0.02, 7)
  412. x = linspace(0.02, pi-0.02, 7)
  413. assert_allclose(lut(x, y, dtheta=1), _numdiff_2d(lut, x, y, dx=1),
  414. rtol=1e-4, atol=1e-4)
  415. assert_allclose(lut(x, y, dphi=1), _numdiff_2d(lut, x, y, dy=1),
  416. rtol=1e-4, atol=1e-4)
  417. assert_allclose(lut(x, y, dtheta=1, dphi=1), _numdiff_2d(lut, x, y, dx=1, dy=1, eps=1e-6),
  418. rtol=1e-3, atol=1e-3)
  419. def test_derivatives(self):
  420. y = linspace(0.01, 2*pi-0.01, 7)
  421. x = linspace(0.01, pi-0.01, 7)
  422. z = array([[1,2,1,2,1,2,1],[1,2,1,2,1,2,1],[1,2,3,2,1,2,1],
  423. [1,2,2,2,1,2,1],[1,2,1,2,1,2,1],[1,2,2,2,1,2,1],
  424. [1,2,1,2,1,2,1]])
  425. lut = RectSphereBivariateSpline(x,y,z)
  426. y = linspace(0.02, 2*pi-0.02, 7)
  427. x = linspace(0.02, pi-0.02, 7)
  428. assert_equal(lut(x, y, dtheta=1, grid=False).shape, x.shape)
  429. assert_allclose(lut(x, y, dtheta=1, grid=False),
  430. _numdiff_2d(lambda x,y: lut(x,y,grid=False), x, y, dx=1),
  431. rtol=1e-4, atol=1e-4)
  432. assert_allclose(lut(x, y, dphi=1, grid=False),
  433. _numdiff_2d(lambda x,y: lut(x,y,grid=False), x, y, dy=1),
  434. rtol=1e-4, atol=1e-4)
  435. assert_allclose(lut(x, y, dtheta=1, dphi=1, grid=False),
  436. _numdiff_2d(lambda x,y: lut(x,y,grid=False), x, y, dx=1, dy=1, eps=1e-6),
  437. rtol=1e-3, atol=1e-3)
  438. def _numdiff_2d(func, x, y, dx=0, dy=0, eps=1e-8):
  439. if dx == 0 and dy == 0:
  440. return func(x, y)
  441. elif dx == 1 and dy == 0:
  442. return (func(x + eps, y) - func(x - eps, y)) / (2*eps)
  443. elif dx == 0 and dy == 1:
  444. return (func(x, y + eps) - func(x, y - eps)) / (2*eps)
  445. elif dx == 1 and dy == 1:
  446. return (func(x + eps, y + eps) - func(x - eps, y + eps)
  447. - func(x + eps, y - eps) + func(x - eps, y - eps)) / (2*eps)**2
  448. else:
  449. raise ValueError("invalid derivative order")