Skip to content

Commit

Permalink
MAINT: interpolate: refactor PchipInterpolator to be a *Poly subclass
Browse files Browse the repository at this point in the history
  • Loading branch information
ev-br authored and andreas-h committed Apr 28, 2015
1 parent 30448ac commit c7ec61b
Showing 1 changed file with 5 additions and 56 deletions.
61 changes: 5 additions & 56 deletions scipy/interpolate/_monotone.py
Expand Up @@ -10,7 +10,7 @@
"Akima1DInterpolator"]


class PchipInterpolator(object):
class PchipInterpolator(BPoly):
"""PCHIP 1-d monotonic cubic interpolation
x and y are arrays of values used to approximate some function f,
Expand Down Expand Up @@ -72,75 +72,24 @@ def __init__(self, x, y, axis=0, extrapolate=None):
y = y.astype(float)

axis = axis % y.ndim

xp = x.reshape((x.shape[0],) + (1,)*(y.ndim-1))
yp = np.rollaxis(y, axis)

dk = self._find_derivatives(xp, yp)
data = np.hstack((yp[:, None, ...], dk[:, None, ...]))

self._bpoly = BPoly.from_derivatives(x, data, orders=None,
_b = BPoly.from_derivatives(x, data, orders=None)
super(PchipInterpolator, self).__init__(_b.c, _b.x,
extrapolate=extrapolate)
self.axis = axis

def __call__(self, x, der=0, extrapolate=None):
"""
Evaluate the PCHIP interpolant or its derivative.
Parameters
----------
x : array_like
Points to evaluate the interpolant at.
der : int, optional
Order of derivative to evaluate. Must be non-negative.
extrapolate : bool, optional
Whether to extrapolate to ouf-of-bounds points based on first
and last intervals, or to return NaNs.
Returns
-------
y : ndarray
Interpolated values. Shape is determined by replacing
the interpolation axis in the original array with the shape of x.
"""
out = self._bpoly(x, der, extrapolate)
return self._reshaper(x, out)

def derivative(self, der=1):
"""
Construct a piecewise polynomial representing the derivative.
Parameters
----------
der : int, optional
Order of derivative to evaluate. (Default: 1)
If negative, the antiderivative is returned.
Returns
-------
Piecewise polynomial of order k2 = k - der representing the derivative
of this polynomial.
"""
t = object.__new__(self.__class__)
t.axis = self.axis
t._bpoly = self._bpoly.derivative(der)
return t

def roots(self):
"""
Return the roots of the interpolated function.
"""
return (PPoly.from_bernstein_basis(self._bpoly)).roots()

def _reshaper(self, x, out):
x = np.asarray(x)
l = x.ndim
transp = (tuple(range(l, l+self.axis)) + tuple(range(l)) +
tuple(range(l+self.axis, out.ndim)))
return out.transpose(transp)

@staticmethod
def _edge_case(m0, d1, out):
m0 = np.atleast_1d(m0)
Expand Down Expand Up @@ -334,7 +283,7 @@ def extend(self):
"yet implemented")

# These are inherited from PPoly, but they do not produce an Akima
# interpolor. Hence stub them out.
# interpolator. Hence stub them out.
@classmethod
def from_spline(cls, tck, extrapolate=None):
raise NotImplementedError("This method does not make sense for "
Expand Down

0 comments on commit c7ec61b

Please sign in to comment.