[Scipy-svn] r4563 - branches/Interpolate1D

scipy-svn@scip... scipy-svn@scip...
Fri Jul 25 15:46:46 CDT 2008


Author: fcady
Date: 2008-07-25 15:46:43 -0500 (Fri, 25 Jul 2008)
New Revision: 4563

Modified:
   branches/Interpolate1D/Interpolate1D.py
   branches/Interpolate1D/TODO.txt
   branches/Interpolate1D/fitpack_wrapper.py
   branches/Interpolate1D/interpolate1d.py
   branches/Interpolate1D/interpolate_wrapper.py
Log:
better unit tests, and allow user to input a callable class that has been instantiated but does not yet have x and y

Modified: branches/Interpolate1D/Interpolate1D.py
===================================================================
--- branches/Interpolate1D/Interpolate1D.py	2008-07-25 16:26:25 UTC (rev 4562)
+++ branches/Interpolate1D/Interpolate1D.py	2008-07-25 20:46:43 UTC (rev 4563)
@@ -192,6 +192,7 @@
     """
     # FIXME: more informative descriptions of sample arguments
     # FIXME: examples in doc string
+    # FIXME : Allow copying or not of arrays.  non-copy + remove_bad_data should flash a warning (esp if we interpolate missing values), but work anyway.
     
     def __init__(self, x, y, kind='linear', low=np.NaN, high=np.NaN, \
                         kindkw={}, lowkw={}, highkw={}, \
@@ -212,12 +213,9 @@
         if remove_bad_data:
             x, y = self._remove_bad_data(x, y, bad_data)
         
-        # select proper dataypes and make arrays
-        self._xdtype = {np.float32 : np.float32}.setdefault(type(x[0]), np.float64) # unless data is float32,  cast to float64
-        self._ydtype = {np.float32 : np.float32}.setdefault(type(y[0]), np.float64)
-        self._x = make_array_safe(x, self._xdtype).copy()
-        self._y = make_array_safe(y, self._ydtype).copy()
-
+        # FIXME : may be good to let x and y be initialized later, or changed after-the-fact
+        self._init_xy(x, y)
+        
         # store interpolation functions for each range
         self.kind = self._init_interp_method(self._x, self._y, kind, kindkw)
         self.low = self._init_interp_method(self._x, self._y, low, lowkw)
@@ -236,8 +234,14 @@
         x = x[mask]
         y = y[mask]
         return x, y
-  
     
+    def _init_xy(self, x, y):
+        # select proper dataypes and make arrays
+        self._xdtype = {np.float32 : np.float32}.setdefault(type(x[0]), np.float64) # unless data is float32,  cast to float64
+        self._ydtype = {np.float32 : np.float32}.setdefault(type(y[0]), np.float64)
+        self._x = make_array_safe(x, self._xdtype).copy()
+        self._y = make_array_safe(y, self._ydtype).copy()
+        
     def _init_interp_method(self, x, y, interp_arg, kw):
         """
             User provides interp_arg and dictionary kw.  _init_interp_method
@@ -251,28 +255,55 @@
         
         from inspect import isclass, isfunction
         
+        # primary usage : user passes a string indicating a known function
         if interp_arg in ['linear', 'logarithmic', 'block', 'block_average_above']:
             # string used to indicate interpolation method,  Select appropriate function
             func = {'linear':linear, 'logarithmic':logarithmic, 'block':block, \
                         'block_average_above':block_average_above}[interp_arg]
             result = lambda new_x : func(self._x, self._y, new_x, **kw)
         elif interp_arg in ['Spline', Spline, 'spline']:
-            # spline is a special case of above
+            # use the Spline class from fitpack_wrapper
             result = Spline(self._x, self._y, **kw)
         elif interp_arg in ['cubic', 'Cubic', 'Quadratic', \
-                                'quadratic', 'Quad', 'quad']:
-            # specify certain kinds of splines
+                                'quadratic', 'Quad', 'quad', 'Quintic', 'quintic']:
+            # specify specific kinds of splines
             if interp_arg in ['cubic', 'Cubic']:
                 result = Spline(self._x, self._y, k=3)
             elif interp_arg in ['Quadratic', 'quadratic', 'Quad', 'quad']:
                 result = Spline(self._x, self._y, k=2)
+            elif interp_arg in ['Quintic', 'quintic']:
+                result = Spline(self._x, self._y, k=4)
+                
+        # secondary usage : user passes a callable class
+        elif isclass(interp_arg) and hasattr(interp_arg, '__call__'):
+            if hasattr(interp_arg, 'init_xy'):
+                result = interp_arg(**kw)
+                result.init_xy(self._x, self._y)
+            elif hasattr(interp_arg, 'set_xy'):
+                result = interp_arg(**kw)
+                result.set_xy(self._x, self._y)
+            else:
+                result = interp_arg(x, y, **kw)
+                
+        # user passes an instance of a callable class which has yet
+        # to have its x and y initialized.
+        elif hasattr(interp_arg, 'init_xy') and hasattr(interp_arg, '__call__'):
+            result = interp_arg
+            result.init_xy(self._x, self._y)
+        elif hasattr(interp_arg, 'set_xy') and hasattr(interp_arg, '__call__'):
+            result = interp_arg
+            result.set_xy(self._x, self._y)
+                
+        # user passes a function to be called
+        elif isfunction(interp_arg) and interp.func_code.argcount == 3:
+            result = lambda new_x : interp_arg(self._x, self._y, new_x, **kw)
         elif isfunction(interp_arg):
-            # assume user has passed a function
             result = lambda new_x : interp_arg(new_x, **kw)
-        elif isclass(interp_arg):
-            result = interp_arg(x, y, **kw)
+        
+        # default : user has passed a default value to always be returned
         else:
             result = np.vectorize(lambda new_x : interp_arg)
+            
         return result
 
     def __call__(self, x):
@@ -315,7 +346,7 @@
     def assertAllclose(self, x, y):
         self.assert_(np.allclose(make_array_safe(x), make_array_safe(y)))
         
-    def test__interpolate_wrapper(self):
+    def test_interpolate_wrapper(self):
         """ run unit test contained in interpolate_wrapper.py
         """
         print "\n\nTESTING _interpolate_wrapper MODULE"
@@ -323,7 +354,7 @@
         T = Test()
         T.runTest()
         
-    def test__fitpack_wrapper(self):
+    def test_fitpack_wrapper(self):
         """ run unit test contained in fitpack_wrapper.py
         """
         print "\n\nTESTING _fitpack_wrapper MODULE"
@@ -331,6 +362,56 @@
         T = Test()
         T.runTest()
         
+    def test_instantiationFormat(self):
+        """ make sure : all allowed instantiation formats are supported
+        """
+        
+        # make sure : an instance of a callable class in which
+        # x and y haven't been initiated works
+        print 'hello'
+        N = 7 #must be > 5
+        x = np.arange(N)
+        y = np.arange(N)
+        interp_func = Interpolate1d(x, y, kind=Spline(k=2), low=Spline(k=2), high=Spline(k=2))
+        new_x = np.arange(N+1)-0.5
+        new_y = interp_func(new_x)
+        self.assertAllclose(new_x, new_y)
+        
+    def test_callFormat(self):
+        """ make sure : all allowed calling formats are supported
+        """
+        # make sure : having no out-of-range elements in new_x is fine
+        # There was a bug with this earlier.        
+        N = 5
+        x = arange(N)
+        y = arange(N)
+        new_x = arange(1,N-1)+.2
+        interp_func = Interpolate1d(x, y, kind='linear', low='linear', high=np.NaN)
+        new_y = interp_func(new_x)
+        self.assertAllclose(new_x, new_y)
+        
+    def test_removeBad(self):
+        """make sure : interp1d works with bad data
+        """
+        N = 7.0 # must be >=5
+        x = arange(N); x[2] = np.NaN
+        y = arange(N); y[4] = None; y[0]=np.NaN
+        new_x = arange(N+1)-0.5
+        new_y = interp1d(x, y, new_x, kind='linear', low='linear', high='linear', \
+                                    remove_bad_data = True, bad_data = [None])
+        self.assertAllclose(new_x, new_y)
+        
+    def test_intper1d(self):
+        """
+            make sure : interp1d works, at least in the linear case
+        """
+        N = 7
+        x = arange(N)
+        y = arange(N)
+        new_x = arange(N+1)-0.5
+        new_y = interp1d(x, y, new_x, kind='linear', low='linear', high='linear')        
+        self.assertAllclose(new_x, new_y)
+        
     def test_spline1_defaultExt(self):
         """
             make sure : spline order 1 (linear) interpolation works correctly
@@ -401,40 +482,11 @@
         
         self.assertAllclose(new_x, new_y)
         
-    def test_noLow(self):
-        """
-            make sure : having no out-of-range elements in new_x is fine
-            There was a bug with this earlier.
-        """
-        N = 5
-        x = arange(N)
-        y = arange(N)
-        new_x = arange(1,N-1)+.2
-        interp_func = Interpolate1d(x, y, kind='linear', low='linear', high=np.NaN)
-        new_y = interp_func(new_x)
-        self.assertAllclose(new_x, new_y)
+    
         
-    def test_intper1d(self):
-        """
-            make sure : interp1d works, at least in the linear case
-        """
-        N = 7
-        x = arange(N)
-        y = arange(N)
-        new_x = arange(N+1)-0.5
-        new_y = interp1d(x, y, new_x, kind='linear', low='linear', high='linear')        
-        self.assertAllclose(new_x, new_y)
+    
         
-    def test_removeBad(self):
-        """make sure : interp1d works with bad data
-        """
-        N = 7.0 # must be >=5
-        x = arange(N); x[2] = np.NaN
-        y = arange(N); y[4] = None; y[0]=np.NaN
-        new_x = arange(N+1)-0.5
-        new_y = interp1d(x, y, new_x, kind='linear', low='linear', high='linear', \
-                                    remove_bad_data = True, bad_data = [None])
-        self.assertAllclose(new_x, new_y)
+    
         
 if __name__ == '__main__':
     unittest.main()                 
\ No newline at end of file

Modified: branches/Interpolate1D/TODO.txt
===================================================================
--- branches/Interpolate1D/TODO.txt	2008-07-25 16:26:25 UTC (rev 4562)
+++ branches/Interpolate1D/TODO.txt	2008-07-25 20:46:43 UTC (rev 4563)
@@ -5,25 +5,33 @@
 at appropriate places in the code.
 
 
+**include license for FITPACK
+    take it from scipy.interpolate.
+
+
 **handle smoothing in fitpack_wrapper
     The default smoothing parameter (s) means we aren't actually
     doing interpolation.  Also, small but non-zero s makes the
     algorithm very slow.  Figure out how to handle this, prob by
     not letting the user see s and setting it to 0.
 
-    This may be best handled by modifying fitpack_wrapper.py.
+    Then again, users very often want to smooth data at the same
+    time.  FITPACK suffers from VERY slow performance when s
+    is very small but not 0.  This is a problem.
 
 
 **pick best spline
     Under-the-hood machinery currently comes from _interpolate.cpp
     (used in enthought.interpolate) and FITPACK (Fortran, used in 
     scipy.interpolate).  This isn't necessarily the best (for example,
-    speed of FITPACK is highly sensitive to parameter s).  Other code
+    speed of FITPACK is highly sensitive to smoothing parameter s).  Other code
     is used in scipy.ndimage and scipy.signal.  There is surely other
     code out there too.  Figure out what is best and incorporate it.
 
-    Signal code is slower than FITPACK, and NDImage really only does
-    filtering.  I'm inclined to stay with FITPACK.
+    Signal code is slower than FITPACK, and NDImage requires a
+    regular grid.  I'm inclined to stay with FITPACK, except for the
+    slow performance when x is small (we could add a hack to not
+    let s be tiny > 0).
 
 
 **clean up fitpack_wrapper.py
@@ -36,7 +44,8 @@
 
 **comment interpolate1d
     There's comments there already, but they should be
-    made better.
+    made better.  Plus, features are changing, which requires
+    updating the documentation.
 
 
 **doc strings for interpolate1d and its members
@@ -51,8 +60,8 @@
     updates of documentation easier.
 
 
-**figure out NumPy version stuff with vectorize.
-    In function interpolate1d._format_array.
+**figure out NumPy stuff with vectorize.
+    In function interpolate1d.__call__
     It would be nice to remove the hack I used.
     I believe vectorize is supposed to handle arrays of
     length 0, but it's not working on my computer.
@@ -96,45 +105,25 @@
     shouldn't be done until interpolate1d is more settled.
     
     There is an interesting problem here.  Most of the extensions
-    I have assume a regular grid.  First off, this is often unrealistic.
-    Secondly, if I DO use a rectangular grid, how do I deal with bad
+    I have assume a regular grid.  First off, this is often not general.
+    Secondly, if I DO use a regular grid, how do I deal with bad
     data?  The best way is probably a pre-processing where you
     interpolate values for the bad points (linear would be a nice simple
     way to do it at first, just to get it working)
 
 
-**more convenient way to enter kw arguments
-    currently users have to pass in dictionaries of additional
-    keyword arguments for specific interpolation types.
-    This is kind of awkward, and it would be nice to let
-    them pass in a single argument.  But this is low priority.
-
-
-**allow y to be 2-dimensional
-    That way the interpolated function is from R1 -> Rn, and
-    not just R1 -> R1.  This requires some thinking about axes.
-
-    The interpolation should, I think, be along columns, so each
-    row of y is one complete observation.  This is because 1) rows
-    are separated more from each other when an array is displayed,
-    and 2) the user may want to enter the data as y=array([obs1, obs2, ...]).
-
-    There are two big problem.  First, interpolate_wrapper interpolates
-    along rows, because each row is contiguous.  Second,
-    FITPACK doesn't support 2D y arrays.
-
-    The solution is to have the user indicate which axis to interpolate
-    along, and take the transpose if need be (also copy, so that
-    the columns become contiguous).  Then when the user enters newx,
-    all under-the-hood interpolation is performed on contiguous
-    arrays.
-
-    Whatever is done must be very well commented.
-    
-    Also, there's a problem with removing bad data and still
-    retaining a rectangular array.  I would have to store a list
-    of (x,y) pairs, which suggests I should do this with a wrapper
-    function anyway.  Not memory efficient, but oh well.  In the
-    future, however, when x is a ND array, I should work around this;
-    I should have it be Rn -> Rm and fill in missing values to the best
-    of my ability.
+**allow y to be 2-dimensional?
+    It is not decided whether this feature should be supported, but
+    I don't think it should; I think there should be another class with
+    that functionality which wraps Interpolate1d.  The main reasons
+    are:
+    1) interpolation should probably be along columns, so the user
+    can enter data as enter the data as y=array([obs1, obs2, ...]).  But
+    the interpolate_wrapper and fitpack_wrapper interpolate along
+    rows; this means there would be messy transposes in the code.
+    2) FITPACK doesn't support 2D y arrays, which means we would
+    have to store the y columns separately
+    3) If we remove bad data, bearing in mind (2), we would also
+    have to store copies of x, since the bad data in the y cols aren't
+    at the same locations, meaning that different data points should be
+    deleted for each column.

Modified: branches/Interpolate1D/fitpack_wrapper.py
===================================================================
--- branches/Interpolate1D/fitpack_wrapper.py	2008-07-25 16:26:25 UTC (rev 4562)
+++ branches/Interpolate1D/fitpack_wrapper.py	2008-07-25 20:46:43 UTC (rev 4563)
@@ -14,7 +14,7 @@
 
 import numpy as np
 
-import dfitpack # lower-level wrapper around FITPACK
+import dfitpack # extension module containing FITPACK subroutines
 
 
 class Spline(object):
@@ -30,7 +30,7 @@
     BivariateSpline - a similar class for bivariate spline interpolation
     """
 
-    def __init__(self, x, y, w=None, bbox = [None]*2, k=3, s=0.0):
+    def __init__(self, x=None, y=None, w=None, bbox = [None]*2, k=3, s=0.0):
         """
         Input:
           x,y   - 1-d sequences of data points (x must be
@@ -49,9 +49,23 @@
                        if 1/w[i] is an estimate of the standard
                        deviation of y[i].
         """
+        
+        self._k = k
+        self._s = s
+        self._bbox = bbox
+        self._w = w
+        
+        if x is not None and y is not None:
+            self.init_xy(x, y)
+            self._is_initialized = True
+        else:
+            self._is_initialized = False
+        
+    def init_xy(self, x, y):
+        
         #_data == x,y,w,xb,xe,k,s,n,t,c,fp,fpint,nrdata,ier
-        data = dfitpack.fpcurf0(x, y, k, w=w,
-                                xb=bbox[0], xe=bbox[1], s=s)
+        data = dfitpack.fpcurf0(x, y, self._k, w=self._w,
+                                xb=self._bbox[0], xe=self._bbox[1], s=self._s)
         if data[-1]==1:
             # nest too small, setting to maximum bound
             data = self._reset_nest(data)
@@ -59,6 +73,8 @@
         # the relevant part of self._reset_class()
         n,t,c,k,ier = data[7],data[8],data[9],data[5],data[-1]
         self._eval_args = t[:n],c[:n],k
+        
+        self._is_initialized = True
 
     def _reset_nest(self, data, nest=None):
         n = data[10]
@@ -101,11 +117,13 @@
         if x is (partially) ordered.
         
         """
-        
-        if len(x) == 0: return np.array([]) #hack to cope with shape (0,)
-        if nu is None:
-            return dfitpack.splev(*(self._eval_args+(x,)))
-        return dfitpack.splder(nu=nu,*(self._eval_args+(x,)))
+        if self._is_initialized:
+            if len(x) == 0: return np.array([]) #hack to cope with shape (0,)
+            if nu is None:
+                return dfitpack.splev(*(self._eval_args+(x,)))
+            return dfitpack.splder(nu=nu,*(self._eval_args+(x,)))
+        else:
+            raise TypeError, "x and y must be set before interpolation is possible"
 
     def get_knots(self):
         """ Return the positions of (boundary and interior)
@@ -165,23 +183,58 @@
     def assertAllclose(self, x, y):
         self.assert_(np.allclose(x, y))
         
-    def test_linearSpl(self):
+    def test_linearInterp(self):
+        """ make sure : linear interpolation (spline with order = 1, s = 0)works
+        """
         N = 3000.
         x = np.arange(N)
         y = np.arange(N)
-        T1 = time.clock()
+        #T1 = time.clock()
         interp_func = Spline(x, y, k=1)
-        T2 = time.clock()
-        print "time to create order 1 spline interpolation function with N = %i:" % N, T2 - T1
+        #T2 = time.clock()
+        #print "time to create order 1 spline interpolation function with N = %i:" % N, T2 - T1
         new_x = np.arange(N)+0.5
-        t1 = time.clock()
+        #t1 = time.clock()
         new_y = interp_func(new_x)
-        t2 = time.clock()
-        print "time for order 1 spline interpolation with N = %i:" % N, t2 - t1
+        #t2 = time.clock()
+        #print "time for order 1 spline interpolation with N = %i:" % N, t2 - t1
         self.assertAllclose(new_y[:5], [0.5, 1.5, 2.5, 3.5, 4.5])
+        
+    def test_quadInterp(self):
+        """ make sure : quadratic interpolation (spline with order = 2, s = 0)works
+        """
+        N = 3000.
+        x = np.arange(N)
+        y = x**2
+        interp_func = Spline(x, y, k=2)
+        #print "time to create order 1 spline interpolation function with N = %i:" % N, T2 - T1
+        new_x = np.arange(N)+0.5
+        #t1 = time.clock()
+        new_y = interp_func(x)
+        #t2 = time.clock()
+        #print "time for order 1 spline interpolation with N = %i:" % N, t2 - t1
+        self.assertAllclose(new_y, y)
+        
+        
+    def test_inputFormat(self):
+        """ make sure : it's possible to instantiate Spline without x and y
+        """
+        #print "testing input format"
+        N = 3000.
+        x = np.arange(N)
+        y = np.arange(N)
+        interp_func = Spline(k=1)
+        interp_func.init_xy(x, y)
+        new_x = np.arange(N)+0.5
+        new_y = interp_func(new_x)
+        self.assertAllclose(new_y[:5], [0.5, 1.5, 2.5, 3.5, 4.5])
     
     def runTest(self):
-        self.test_linearSpl()
+        test_list = [name for name in dir(self) if name.find('test_')==0]
+        for test_name in test_list:
+            exec("self.%s()" % test_name)
+           
+        
                              
 if __name__ == '__main__':
     unittest.main()

Modified: branches/Interpolate1D/interpolate1d.py
===================================================================
--- branches/Interpolate1D/interpolate1d.py	2008-07-25 16:26:25 UTC (rev 4562)
+++ branches/Interpolate1D/interpolate1d.py	2008-07-25 20:46:43 UTC (rev 4563)
@@ -192,6 +192,7 @@
     """
     # FIXME: more informative descriptions of sample arguments
     # FIXME: examples in doc string
+    # FIXME : Allow copying or not of arrays.  non-copy + remove_bad_data should flash a warning (esp if we interpolate missing values), but work anyway.
     
     def __init__(self, x, y, kind='linear', low=np.NaN, high=np.NaN, \
                         kindkw={}, lowkw={}, highkw={}, \
@@ -212,12 +213,9 @@
         if remove_bad_data:
             x, y = self._remove_bad_data(x, y, bad_data)
         
-        # select proper dataypes and make arrays
-        self._xdtype = {np.float32 : np.float32}.setdefault(type(x[0]), np.float64) # unless data is float32,  cast to float64
-        self._ydtype = {np.float32 : np.float32}.setdefault(type(y[0]), np.float64)
-        self._x = make_array_safe(x, self._xdtype).copy()
-        self._y = make_array_safe(y, self._ydtype).copy()
-
+        # FIXME : may be good to let x and y be initialized later, or changed after-the-fact
+        self._init_xy(x, y)
+        
         # store interpolation functions for each range
         self.kind = self._init_interp_method(self._x, self._y, kind, kindkw)
         self.low = self._init_interp_method(self._x, self._y, low, lowkw)
@@ -236,8 +234,14 @@
         x = x[mask]
         y = y[mask]
         return x, y
-  
     
+    def _init_xy(self, x, y):
+        # select proper dataypes and make arrays
+        self._xdtype = {np.float32 : np.float32}.setdefault(type(x[0]), np.float64) # unless data is float32,  cast to float64
+        self._ydtype = {np.float32 : np.float32}.setdefault(type(y[0]), np.float64)
+        self._x = make_array_safe(x, self._xdtype).copy()
+        self._y = make_array_safe(y, self._ydtype).copy()
+        
     def _init_interp_method(self, x, y, interp_arg, kw):
         """
             User provides interp_arg and dictionary kw.  _init_interp_method
@@ -251,28 +255,55 @@
         
         from inspect import isclass, isfunction
         
+        # primary usage : user passes a string indicating a known function
         if interp_arg in ['linear', 'logarithmic', 'block', 'block_average_above']:
             # string used to indicate interpolation method,  Select appropriate function
             func = {'linear':linear, 'logarithmic':logarithmic, 'block':block, \
                         'block_average_above':block_average_above}[interp_arg]
             result = lambda new_x : func(self._x, self._y, new_x, **kw)
         elif interp_arg in ['Spline', Spline, 'spline']:
-            # spline is a special case of above
+            # use the Spline class from fitpack_wrapper
             result = Spline(self._x, self._y, **kw)
         elif interp_arg in ['cubic', 'Cubic', 'Quadratic', \
-                                'quadratic', 'Quad', 'quad']:
-            # specify certain kinds of splines
+                                'quadratic', 'Quad', 'quad', 'Quintic', 'quintic']:
+            # specify specific kinds of splines
             if interp_arg in ['cubic', 'Cubic']:
                 result = Spline(self._x, self._y, k=3)
             elif interp_arg in ['Quadratic', 'quadratic', 'Quad', 'quad']:
                 result = Spline(self._x, self._y, k=2)
+            elif interp_arg in ['Quintic', 'quintic']:
+                result = Spline(self._x, self._y, k=4)
+                
+        # secondary usage : user passes a callable class
+        elif isclass(interp_arg) and hasattr(interp_arg, '__call__'):
+            if hasattr(interp_arg, 'init_xy'):
+                result = interp_arg(**kw)
+                result.init_xy(self._x, self._y)
+            elif hasattr(interp_arg, 'set_xy'):
+                result = interp_arg(**kw)
+                result.set_xy(self._x, self._y)
+            else:
+                result = interp_arg(x, y, **kw)
+                
+        # user passes an instance of a callable class which has yet
+        # to have its x and y initialized.
+        elif hasattr(interp_arg, 'init_xy') and hasattr(interp_arg, '__call__'):
+            result = interp_arg
+            result.init_xy(self._x, self._y)
+        elif hasattr(interp_arg, 'set_xy') and hasattr(interp_arg, '__call__'):
+            result = interp_arg
+            result.set_xy(self._x, self._y)
+                
+        # user passes a function to be called
+        elif isfunction(interp_arg) and interp.func_code.argcount == 3:
+            result = lambda new_x : interp_arg(self._x, self._y, new_x, **kw)
         elif isfunction(interp_arg):
-            # assume user has passed a function
             result = lambda new_x : interp_arg(new_x, **kw)
-        elif isclass(interp_arg):
-            result = interp_arg(x, y, **kw)
+        
+        # default : user has passed a default value to always be returned
         else:
             result = np.vectorize(lambda new_x : interp_arg)
+            
         return result
 
     def __call__(self, x):
@@ -315,7 +346,7 @@
     def assertAllclose(self, x, y):
         self.assert_(np.allclose(make_array_safe(x), make_array_safe(y)))
         
-    def test__interpolate_wrapper(self):
+    def test_interpolate_wrapper(self):
         """ run unit test contained in interpolate_wrapper.py
         """
         print "\n\nTESTING _interpolate_wrapper MODULE"
@@ -323,7 +354,7 @@
         T = Test()
         T.runTest()
         
-    def test__fitpack_wrapper(self):
+    def test_fitpack_wrapper(self):
         """ run unit test contained in fitpack_wrapper.py
         """
         print "\n\nTESTING _fitpack_wrapper MODULE"
@@ -331,6 +362,56 @@
         T = Test()
         T.runTest()
         
+    def test_instantiationFormat(self):
+        """ make sure : all allowed instantiation formats are supported
+        """
+        
+        # make sure : an instance of a callable class in which
+        # x and y haven't been initiated works
+        print 'hello'
+        N = 7 #must be > 5
+        x = np.arange(N)
+        y = np.arange(N)
+        interp_func = Interpolate1d(x, y, kind=Spline(k=2), low=Spline(k=2), high=Spline(k=2))
+        new_x = np.arange(N+1)-0.5
+        new_y = interp_func(new_x)
+        self.assertAllclose(new_x, new_y)
+        
+    def test_callFormat(self):
+        """ make sure : all allowed calling formats are supported
+        """
+        # make sure : having no out-of-range elements in new_x is fine
+        # There was a bug with this earlier.        
+        N = 5
+        x = arange(N)
+        y = arange(N)
+        new_x = arange(1,N-1)+.2
+        interp_func = Interpolate1d(x, y, kind='linear', low='linear', high=np.NaN)
+        new_y = interp_func(new_x)
+        self.assertAllclose(new_x, new_y)
+        
+    def test_removeBad(self):
+        """make sure : interp1d works with bad data
+        """
+        N = 7.0 # must be >=5
+        x = arange(N); x[2] = np.NaN
+        y = arange(N); y[4] = None; y[0]=np.NaN
+        new_x = arange(N+1)-0.5
+        new_y = interp1d(x, y, new_x, kind='linear', low='linear', high='linear', \
+                                    remove_bad_data = True, bad_data = [None])
+        self.assertAllclose(new_x, new_y)
+        
+    def test_intper1d(self):
+        """
+            make sure : interp1d works, at least in the linear case
+        """
+        N = 7
+        x = arange(N)
+        y = arange(N)
+        new_x = arange(N+1)-0.5
+        new_y = interp1d(x, y, new_x, kind='linear', low='linear', high='linear')        
+        self.assertAllclose(new_x, new_y)
+        
     def test_spline1_defaultExt(self):
         """
             make sure : spline order 1 (linear) interpolation works correctly
@@ -401,40 +482,11 @@
         
         self.assertAllclose(new_x, new_y)
         
-    def test_noLow(self):
-        """
-            make sure : having no out-of-range elements in new_x is fine
-            There was a bug with this earlier.
-        """
-        N = 5
-        x = arange(N)
-        y = arange(N)
-        new_x = arange(1,N-1)+.2
-        interp_func = Interpolate1d(x, y, kind='linear', low='linear', high=np.NaN)
-        new_y = interp_func(new_x)
-        self.assertAllclose(new_x, new_y)
+    
         
-    def test_intper1d(self):
-        """
-            make sure : interp1d works, at least in the linear case
-        """
-        N = 7
-        x = arange(N)
-        y = arange(N)
-        new_x = arange(N+1)-0.5
-        new_y = interp1d(x, y, new_x, kind='linear', low='linear', high='linear')        
-        self.assertAllclose(new_x, new_y)
+    
         
-    def test_removeBad(self):
-        """make sure : interp1d works with bad data
-        """
-        N = 7.0 # must be >=5
-        x = arange(N); x[2] = np.NaN
-        y = arange(N); y[4] = None; y[0]=np.NaN
-        new_x = arange(N+1)-0.5
-        new_y = interp1d(x, y, new_x, kind='linear', low='linear', high='linear', \
-                                    remove_bad_data = True, bad_data = [None])
-        self.assertAllclose(new_x, new_y)
+    
         
 if __name__ == '__main__':
     unittest.main()                 
\ No newline at end of file

Modified: branches/Interpolate1D/interpolate_wrapper.py
===================================================================
--- branches/Interpolate1D/interpolate_wrapper.py	2008-07-25 16:26:25 UTC (rev 4562)
+++ branches/Interpolate1D/interpolate_wrapper.py	2008-07-25 20:46:43 UTC (rev 4563)
@@ -155,7 +155,7 @@
         t1 = time.clock()
         new_y = linear(x, y, new_x)
         t2 = time.clock()
-        print "time for linear interpolation with N = %i:" % N, t2 - t1
+        #print "time for linear interpolation with N = %i:" % N, t2 - t1
         
         self.assertAllclose(new_y[:5], [0.5, 1.5, 2.5, 3.5, 4.5])
         
@@ -168,7 +168,7 @@
         t1 = time.clock()
         new_y = block_average_above(x, y, new_x)
         t2 = time.clock()
-        print "time for block_avg_above interpolation with N = %i:" % N, t2 - t1
+        #print "time for block_avg_above interpolation with N = %i:" % N, t2 - t1
         self.assertAllclose(new_y[:5], [0.0, 0.5, 2.5, 4.5, 6.5])
 
     def test_linear2(self):
@@ -179,7 +179,7 @@
         t1 = time.clock()
         new_y = linear(x, y, new_x)
         t2 = time.clock()
-        print "time for 2D linear interpolation with N = %i:" % N, t2 - t1
+        #print "time for 2D linear interpolation with N = %i:" % N, t2 - t1
         self.assertAllclose(new_y[:5,:5],
                             [[ 0.5, 1.5, 2.5, 3.5, 4.5],
                              [ 0.5, 1.5, 2.5, 3.5, 4.5],
@@ -188,22 +188,21 @@
                              [ 0.5, 1.5, 2.5, 3.5, 4.5]])
                              
     def test_logarithmic(self):
-        N = 3000.
+        N = 4000.
         x = arange(N)
         y = arange(N)
         new_x = arange(N)+0.5
         t1 = time.clock()
         new_y = logarithmic(x, y, new_x)
         t2 = time.clock()
-        print "time for logarithmic interpolation with N = %i:" % N, t2 - t1
+        #print "time for logarithmic interpolation with N = %i:" % N, t2 - t1
         correct_y = [np.NaN, 1.41421356, 2.44948974, 3.46410162, 4.47213595]
         self.assertAllclose(new_y[:5], correct_y)
         
     def runTest(self):
-        self.test_linear()
-        self.test_block_average_above()
-        self.test_linear2()
-        self.test_logarithmic()
+        test_list = [name for name in dir(self) if name.find('test_')==0]
+        for test_name in test_list:
+            exec("self.%s()" % test_name)
     
 if __name__ == '__main__':
     unittest.main()



More information about the Scipy-svn mailing list