Skip to content

Commit

Permalink
ENH: Add ext parameter to UnivariateSpline call
Browse files Browse the repository at this point in the history
Pass parameter to fitpack.splev to control how to handle out of range
evaluations. Added test to scipy/interpolate/tests/test_fitpack2.py.

See ticket 3557.

closes scipygh-3557
  • Loading branch information
jacobcvt12 authored and ev-br committed Aug 16, 2014
1 parent 276b3bc commit 3c4b944
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 5 deletions.
27 changes: 22 additions & 5 deletions scipy/interpolate/fitpack2.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,28 @@ def set_smoothing_factor(self, s):
self._data = data
self._reset_class()

def __call__(self, x, nu=0):
""" Evaluate spline (or its nu-th derivative) at positions x.
def __call__(self, x, nu=0, ext=0):
"""
Evaluate spline (or its nu-th derivative) at positions x.
Parameters
----------
x : array_like
A 1-D array of points at which to return the value of the smoothed
spline or its derivatives. Note: x can be unordered but the
evaluation is more efficient if x is (partially) ordered.
nu : int
The order of derivative of the spline to compute.
ext : int
Controls the value returned for elements of ``x`` not in the
interval defined by the knot sequence.
* if ext=0, return the extrapolated value.
* if ext=1, return 0
* if ext=2, raise a ValueError
The default value is 0.
Note: x can be unordered but the evaluation is more efficient
if x is (partially) ordered.
"""
x = np.asarray(x)
# empty input yields empty output
Expand All @@ -241,7 +258,7 @@ def __call__(self, x, nu=0):
# if nu is None:
# return dfitpack.splev(*(self._eval_args+(x,)))
# return dfitpack.splder(nu=nu,*(self._eval_args+(x,)))
return fitpack.splev(x, self._eval_args, der=nu)
return fitpack.splev(x, self._eval_args, der=nu, ext=ext)

def get_knots(self):
""" Return positions of (boundary and interior) knots of the spline.
Expand Down
15 changes: 15 additions & 0 deletions scipy/interpolate/tests/test_fitpack2.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ def test_resize_regression(self):
desired = array([0.35100374, 0.51715855, 0.87789547, 0.98719344])
assert_allclose(spl([0.1, 0.5, 0.9, 0.99]), desired, atol=5e-4)

def test_out_of_range_regression(self):
"""Regression test for #3557."""
x_in_range = [-3., -2.33333333, -1.66666667, -1., -0.33333333,
0.33333333, 1., 1.66666667, 2.33333333, 3.]
x_out_of_range = [-3.66666667, -3., -2.33333333, -1.66666667, -1.,
-0.33333333, 0.33333333, 1., 1.66666667, 2.33333333,
3., 3.66666667]
y = [-0.03443365, 0.02969204, 0.16251805, 0.33279394, 1.07995049,
0.88203547, 0.31274008, -0.10215527, -0.0274716, -0.06661292]
desired = array([0., -0.21332128, 0.16590419, 0.41822373, 0.55728419,
0.59673238, 0.55021514, 0.43137928, 0.25387164,
0.03133904, -0.22257169, 0.])
spl = UnivariateSpline(x=x_in_range, y=y)
assert_allclose(spl(x_out_of_range, ext=1), desired, atol=5e-4)

def test_derivative_and_antiderivative(self):
# Thin wrappers to splder/splantider, so light smoke test only.
x = np.linspace(0, 1, 70)**3
Expand Down

0 comments on commit 3c4b944

Please sign in to comment.