[Scipy-svn] r5156 - trunk/scipy/interpolate

scipy-svn at scipy.org scipy-svn at scipy.org
Fri Nov 21 16:08:09 EST 2008


Author: ptvirtan
Date: 2008-11-21 15:07:57 -0600 (Fri, 21 Nov 2008)
New Revision: 5156

Modified:
   trunk/scipy/interpolate/interpolate.py
Log:
Implement kind='nearest' interpolation, code adapted from #305

Modified: trunk/scipy/interpolate/interpolate.py
===================================================================
--- trunk/scipy/interpolate/interpolate.py	2008-11-21 10:24:29 UTC (rev 5155)
+++ trunk/scipy/interpolate/interpolate.py	2008-11-21 21:07:57 UTC (rev 5156)
@@ -8,7 +8,7 @@
 
 from numpy import shape, sometrue, rank, array, transpose, searchsorted, \
                   ones, logical_or, atleast_1d, atleast_2d, meshgrid, ravel, \
-                  dot, poly1d, asarray
+                  dot, poly1d, asarray, intp
 import numpy as np
 import scipy.special as spec
 import math
@@ -198,14 +198,14 @@
         self.bounds_error = bounds_error
         self.fill_value = fill_value
 
-        if kind in ['zero', 'slinear', 'quadratic', 'cubic', 'nearest']:
+        if kind in ['zero', 'slinear', 'quadratic', 'cubic']:
             order = {'nearest':0, 'zero':0,'slinear':1,
                      'quadratic':2, 'cubic':3}[kind]
             kind = 'spline'
         elif isinstance(kind, int):
             order = kind
             kind = 'spline'
-        elif kind != 'linear':
+        elif kind not in ('linear', 'nearest'):
             raise NotImplementedError("%s is unsupported: Use fitpack "\
                                       "routines for other types." % kind)
         x = array(x, copy=self.copy)
@@ -220,7 +220,7 @@
         self.axis = axis % len(y.shape)
         self._kind = kind
 
-        if kind == 'linear':
+        if kind in ('linear', 'nearest'):
             # Make a "view" of the y array that is rotated to the interpolation
             # axis.
             axes = range(y.ndim)
@@ -229,7 +229,11 @@
             oriented_y = y.transpose(axes)
             minval = 2
             len_y = oriented_y.shape[-1]
-            self._call = self._call_linear
+            if kind == 'linear':
+                self._call = self._call_linear
+            elif kind == 'nearest':
+                self.x_bds = (x[1:] + x[:-1]) / 2.0
+                self._call = self._call_nearest
         else:
             axes = range(y.ndim)
             del axes[self.axis]
@@ -242,10 +246,10 @@
 
         len_x = len(x)
         if len_x != len_y:
-            raise ValueError("x and y arrays must be equal in length along"
-            "interpolation axis.")
+            raise ValueError("x and y arrays must be equal in length along "
+                             "interpolation axis.")
         if len_x < minval:
-            raise ValueError("x and y arrays must have at " \
+            raise ValueError("x and y arrays must have at "
                              "least %d entries" % minval)
         self.x = x
         self.y = oriented_y
@@ -280,6 +284,23 @@
 
         return y_new
 
+    def _call_nearest(self, x_new):
+        """ Find nearest neighbour interpolated y_new = f(x_new)."""
+
+        # 2. Find where in the averaged data the values to interpolate
+        #    would be inserted.
+        #    Note: use side='left' (right) to searchsorted() to define the
+        #    halfway point to be nearest to the left (right) neighbour
+        x_new_indices = searchsorted(self.x_bds, x_new, side='left')
+
+        # 3. Clip x_new_indices so that they are within the range of x indices.
+        x_new_indices = x_new_indices.clip(0,  len(self.x)-1).astype(intp)
+
+        # 4. Calculate the actual value for each entry in x_new.
+        y_new = self.y[..., x_new_indices]
+
+        return y_new
+
     def _call_spline(self, x_new):
         x_new =np.asarray(x_new)
         result = spleval(self._spline,x_new.ravel())
@@ -327,7 +348,7 @@
                 else:
                     y_new[...] = self.fill_value
             return asarray(y_new)
-        elif self._kind == 'linear':
+        elif self._kind in ('linear', 'nearest'):
             y_new[..., out_of_bounds] = self.fill_value
             axes = range(ny - nx)
             axes[self.axis:self.axis] = range(ny - nx, ny)




More information about the Scipy-svn mailing list