[Scipy-svn] r4570 - branches/Interpolate1D
scipy-svn@scip...
scipy-svn@scip...
Mon Jul 28 19:06:54 CDT 2008
Author: fcady
Date: 2008-07-28 19:06:51 -0500 (Mon, 28 Jul 2008)
New Revision: 4570
Added:
branches/Interpolate1D/info.py
Modified:
branches/Interpolate1D/__init__.py
branches/Interpolate1D/example_script.py
branches/Interpolate1D/fitpack_wrapper.py
branches/Interpolate1D/interpolate1d.py
branches/Interpolate1D/regression_test.py
Log:
more updates, esp. to documentation
Modified: branches/Interpolate1D/__init__.py
===================================================================
--- branches/Interpolate1D/__init__.py 2008-07-28 21:36:48 UTC (rev 4569)
+++ branches/Interpolate1D/__init__.py 2008-07-29 00:06:51 UTC (rev 4570)
@@ -5,7 +5,7 @@
# basic interpolation routines
from interpolate_wrapper import linear, logarithmic, block, block_average_above
-#support for spline interpolation
+# support for spline interpolation
from fitpack_wrapper import Spline
# wrapping for all supported interpolation types.
Modified: branches/Interpolate1D/example_script.py
===================================================================
--- branches/Interpolate1D/example_script.py 2008-07-28 21:36:48 UTC (rev 4569)
+++ branches/Interpolate1D/example_script.py 2008-07-29 00:06:51 UTC (rev 4570)
@@ -1,8 +1,15 @@
""" sample operation script
+
+ Creates a sample dataset, performs several
+ basic interpolations on it, and plots results
+ for comparison. Pauses, then does the same
+ thing using different user-input options.
+
Note that in the plot, quadratic, cubic and
quintic lines blur together. You can comment
two out to see one clearly.
"""
+
import numpy as np
import interpolate1d as I
import matplotlib.pyplot as P
@@ -11,6 +18,7 @@
import time
+
## Interpolating in-range data. Basic operation
if True:
@@ -37,8 +45,8 @@
y_cubic = interp(newx)
# 4th order spline
- interp = I.Interpolate1d(x, y, 'quintic')
- y_quintic = interp(newx)
+ interp = I.Interpolate1d(x, y, 'quartic')
+ y_quartic = interp(newx)
# plot result
print "plotting results"
@@ -47,13 +55,14 @@
P.plot(newx, y_linear, 'b')
P.plot(newx, y_quad, 'r')
P.plot(newx, y_cubic, 'm')
- P.plot(newx, y_quintic, 'y')
+ P.plot(newx, y_quartic, 'y')
P.title( "interpolating in-range data with Interpolate1d class" )
P.show()
print "plotted results"
- time.sleep(3)
+ time.sleep(5)
+
## demoing some of the other interfac features
if True:
N = 10.0
@@ -78,7 +87,11 @@
y_cubic2 = interp(newx)
# 4th order spline
- interp = I.Interpolate1d(x, y, 'quintic')
+ interp = I.Interpolate1d(x, y, 'Quartic')
+ y_quartic2 = interp(newx)
+
+ # 5th order spline
+ interp = I.Interpolate1d(x, y, 'Quintic')
y_quintic2 = interp(newx)
# plot result
@@ -88,10 +101,34 @@
P.plot(newx, y_linear2, 'b')
P.plot(newx, y_quad2, 'r')
P.plot(newx, y_cubic2, 'm')
+ P.plot(newx, y_quartic2, 'y')
P.plot(newx, y_quintic2, 'y')
P.title( "same data through different interface" )
P.show()
print "plotted results"
+
+
+# demoing block_average_above and logarithmic
+if False:
+ N = 10.0
+ x = np.arange(N)
+ x[1] = 1.2 # make it grid non-regular
+ y = np.sin(x)
+ newx = np.arange(.05, N, .05)
+
+ # block interpolation
+ # FIXME : I'm not really familiar with logarithmic
+ # interpolation and thus can't comment on what these
+ # data should look like, but this looks weird.
+ interp = I.Interpolate1d(x, y, 'logarithmic')
+ y_logarithmic = interp(newx)
+
+ # linear interpolation
+ interp = I.Interpolate1d(x, y, 'block_average_above')
+ y_blockavgabove = interp(newx)
- #time.sleep(20)
-
+ # plotting the results
+ P.hold(true)
+ P.plot(newx, y_logarithmic, 'g')
+ P.plot(newx, y_blockavgabove, 'r')
+ P.show()
\ No newline at end of file
Modified: branches/Interpolate1D/fitpack_wrapper.py
===================================================================
--- branches/Interpolate1D/fitpack_wrapper.py 2008-07-28 21:36:48 UTC (rev 4569)
+++ branches/Interpolate1D/fitpack_wrapper.py 2008-07-29 00:06:51 UTC (rev 4570)
@@ -10,11 +10,12 @@
under the hood.
"""
-# FIXME : clean up this file! scipy.interpolate contained a lot of
+# FIXME : CLEAN UP THIS FILE! scipy.interpolate contained a lot of
# nice functionality that is only partially in this file.
# The question is whether to copy over the full functionality
-# to the point where we may as well include fitting.py form
-# scipy.interpolate, or whether we should strip is down some.
+# to the point where we may as well include fitting.py from
+# scipy.interpolate, or whether we should strip this down some.
+# Until that's decided, cleaning is premature.
import numpy as np
Added: branches/Interpolate1D/info.py
===================================================================
--- branches/Interpolate1D/info.py 2008-07-28 21:36:48 UTC (rev 4569)
+++ branches/Interpolate1D/info.py 2008-07-29 00:06:51 UTC (rev 4570)
@@ -0,0 +1,45 @@
+# FIXME : better docstring. This needs updating as features change,
+# and it also discusses technical points as well as user-interface.
+
+__doc__ = \
+"""
+ Interpolation of 1D data
+
+ This module provides several functions and classes for interpolation
+ and extrapolation of 1D (in both input and output) real-valued. The
+ primary function provided is:
+
+ interp1d(x, y, new_x) : from data points (x[i], y[i]), interpolates
+ values for points in new_x and
+ returns them as an array. x and new_x
+ must both be in sorted order.
+
+ Classes provided include:
+
+ Interpolate1d : an object for interpolation of
+ various kinds. interp1d is a wrapper
+ around this class.
+
+ Spline : an object for spline interpolation. Interpolate1d
+ wraps this class if spline interpolation
+ is used. However, not all functionality
+ of Spline is available through Interpolate1d.
+
+ Functions provided include:
+
+ linear : linear interpolation
+ logarithmic : logarithmic interpolation
+ block : block interpolation
+ block_average_above : block average above interpolation
+
+ The dependency/interface architecture is as follows:
+ interpolate1d.py is viewed by the user (through interp1d and Interpolate1d)
+ It depends on fitpack_wrapper.py and interpolate_wrapper.py
+ fitpack_wrapper is viewed by the user (through Spline)
+ It depends on dfitpack.pyd, a Fortran extension module
+ interpolate_wrapper is viewed by he user (through functions linear, etc)
+ It depends on _interpolate.pyd, a C extension module.
+
+"""
+
+postpone_import = 1
\ No newline at end of file
Modified: branches/Interpolate1D/interpolate1d.py
===================================================================
--- branches/Interpolate1D/interpolate1d.py 2008-07-28 21:36:48 UTC (rev 4569)
+++ branches/Interpolate1D/interpolate1d.py 2008-07-29 00:06:51 UTC (rev 4570)
@@ -1,31 +1,4 @@
-"""
- Interpolation of 1D data
- This module provides several functions and classes for interpolation
- and extrapolation of 1D data (1D in both input and output). The
- primary function provided is:
-
- interp1d(x, y, new_x) : from data points x and y, interpolates
- values for points in new_x and
- returns them as an array.
-
- Classes provided include:
-
- Interpolate1d : an object for interpolation of
- various kinds. interp1d is a wrapper
- around this class.
-
- Spline : an object for spline interpolation
-
- Functions provided include:
-
- linear : linear interpolation
- logarithmic : logarithmic interpolation
- block : block interpolation
- block_average_above : block average above interpolation
-
-"""
-
# FIXME: information strings giving mathematical descriptions of the actions
# of the functions.
@@ -119,44 +92,77 @@
"""
return Interpolate1d(x, y, kind=kind, low=low, high=high, \
kindkw=kindkw, lowkw=lowkw, highkw=highkw, \
- remove_bad_data = remove_bad_data, bad_data=bad_data)(new_x)
+ remove_bad_data = remove_bad_data, bad_data=bad_data\
+ )(new_x)
class Interpolate1d(object):
- """ A class for interpolation of 1D data.
+ """ A callable class for interpolation of 1D, real-valued data.
Parameters
-----------
- x -- list or NumPy array
+ x -- list or 1D NumPy array
x includes the x-values for the data set to
interpolate from. It must be sorted in
ascending order.
- y -- list or NumPy array
+ y -- list or 1D NumPy array
y includes the y-values for the data set to
- interpolate from. Note that y must be
- one-dimensional.
+ interpolate from. Note that 2-dimensional
+ y is not supported.
Optional Arguments
-------------------
- kind -- Usu. function or string. But can be any type.
- Specifies the type of extrapolation to use for values within
- the range of x. If a string is passed, it will look for an object
- or function with that name and call it when evaluating. If
- a function or object is passed, it will be called when interpolating.
- A constant signifies a function which returns that constant
- (e.g. val and lambda x : val are equivalent). Defaults to linear
- interpolation.
+ kind -- Usu. string or function. But can be any type.
+ Specifies the type of interpolation to use for values within
+ the range of x.
+ If a string is passed, it will look for an object
+ or function with that name and call it when evaluating.
+ This is the primary mode of operation. See below for list
+ of acceptable strings.
+
+ By default, linear interpolation is used.
+
+ Other options are also available:
+
+ If a callable class is passed, it is assumed to have format
+ instance = Class(x, y, **kw).
+ It is instantiated and used for interpolation when the instance
+ of Interpolate1d is called.
+
+ If a callable object with method "init_xy" or "set_xy" is
+ passed, that method will be used to set x and y, and the
+ object will be called during interpolation.
+
+ If a function is passed, it will be called when interpolating.
+ It is assumed to have the form
+ newy = kind(x, y, newx),
+ where x, y, newx, and newy are all numpy arrays.
+
+ A primitive type which is not a string signifies a function
+ which is identically that value (e.g. val and
+ lambda x, y, newx : val are equivalent).
+
+ low -- same as for kind
+ How to extrapolate values for inputs below the range of x.
+ Same options as for 'kind'. Defaults to returning numpy.NaN ('not
+ a number') for all values below the range of x.
+
+ high -- same as for kind
+ How to extrapolate values for inputs above the range of x.
+ Same options as for 'kind'. Defaults to returning numpy.NaN ('not
+ a number') for all values above the range of x.
+
kindkw -- dictionary
If kind is a class, function or string, additional keyword arguments
- may be needed (example: if you want a 2nd order spline, kind = 'spline'
- and kindkw = {'k' : 2}.
+ may be needed (example: if you want a 2nd order spline, you could
+ set kind = 'spline' and kindkw = {'k' : 2}.)
- low (high) -- same as for kind
- Same options as for 'kind'. Defaults to returning numpy.NaN ('not
- a number') for all values outside the range of x.
+ lowkw -- like kindkw, but for low extrapolation
+
+ highkw -- like kindkw, except for high extrapolation
remove_bad_data -- bool
indicates whether to remove bad data points from x and y.
@@ -177,7 +183,10 @@
"block_average_above' -- block average above
"Spline" -- spline interpolation. keyword k (defaults to 3)
indicates order of spline
- numpy.NaN -- return numpy.NaN
+ "quad", "quadratic" -- spline interpolation order 2
+ "cubic" -- spline interpolation order 3
+ "quartic" -- spline interpolation order 4
+ "quintic" -- spline interpolation order 5
Examples
---------
@@ -201,6 +210,11 @@
# FIXME: don't allow copying multiple times.
# FIXME : allow no copying, in case user has huge dataset
+ self._remove_bad_data = remove_bad_data
+ # remove bad data, is there is any
+ if self._remove_bad_data:
+ x, y = self._remove_bad_data(x, y, bad_data)
+
# check acceptable size and dimensions
x = np.array(x)
y = np.array(y)
@@ -209,11 +223,7 @@
assert y.ndim == 1 , "y must be one-dimensional"
assert len(x) == len(y) , "x and y must be of the same length"
- # remove bad data, is there is any
- if remove_bad_data:
- x, y = self._remove_bad_data(x, y, bad_data)
-
- # store data
+ # store data, and remove bad data points is applicable
# FIXME : may be good to let x and y be initialized later, or changed after-the-fact
self._init_xy(x, y)
@@ -222,6 +232,14 @@
self.low = self._init_interp_method(low, lowkw)
self.high = self._init_interp_method(high, highkw)
+ 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 _remove_bad_data(self, x, y, bad_data = [None, np.NaN]):
""" removes data points whose x or y coordinate is
either in bad_data or is a NaN.
@@ -235,18 +253,11 @@
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, interp_arg, kw):
"""
User provides interp_arg and dictionary kw. _init_interp_method
- returns the interpolating function from x and y specified by interp_arg,
+ returns the interpolating function specified by interp_arg,
possibly with extra keyword arguments given in kw.
"""
@@ -264,17 +275,24 @@
result = lambda new_x : func(self._x, self._y, new_x, **kw)
elif interp_arg in ['Spline', Spline, 'spline']:
# use the Spline class from fitpack_wrapper
+ # k = 3 unless otherwise specified
result = Spline(self._x, self._y, **kw)
- elif interp_arg in ['cubic', 'Cubic', 'Quadratic', \
- 'quadratic', 'Quad', 'quad', 'Quintic', 'quintic']:
+ elif interp_arg in ['Quadratic', 'quadratic', 'Quad', 'quad', \
+ 'Cubic', 'cubic', \
+ 'Quartic', 'quartic', 'Quar', 'quar',\
+ 'Quintic', 'quintic', 'Quin', 'quin']:
# specify specific kinds of splines
if interp_arg in ['Quadratic', 'quadratic', 'Quad', 'quad']:
result = Spline(self._x, self._y, k=2)
- elif interp_arg in ['cubic', 'Cubic']:
+ elif interp_arg in ['Cubic', 'cubic']:
result = Spline(self._x, self._y, k=3)
- elif interp_arg in ['Quintic', 'quintic']:
+ elif interp_arg in ['Quartic', 'quartic', 'Quar', 'quar']:
result = Spline(self._x, self._y, k=4)
-
+ elif interp_arg in ['Quintic', 'quintic', 'Quin', 'quin']:
+ result = Spline(self._x, self._y, k=5)
+ elif isinstance(interp_arg, str):
+ raise TypeError, "input string %s not valid" % interp_arg
+
# secondary usage : user passes a callable class
elif isclass(interp_arg) and hasattr(interp_arg, '__call__'):
if hasattr(interp_arg, 'init_xy'):
@@ -310,7 +328,8 @@
def __call__(self, newx):
"""
- Input x must be in sorted order.
+ Input x must be a list or NumPy array in sorted order.
+
Breaks x into pieces in-range, below-range, and above range.
Performs appropriate operation on each and concatenates results.
"""
Modified: branches/Interpolate1D/regression_test.py
===================================================================
--- branches/Interpolate1D/regression_test.py 2008-07-28 21:36:48 UTC (rev 4569)
+++ branches/Interpolate1D/regression_test.py 2008-07-29 00:06:51 UTC (rev 4570)
@@ -1,4 +1,5 @@
-""" regression test:
+"""
+ regression test:
This script runs a simple regression test on the functionality of
the interpolation module. Currently, when run, it times each
@@ -15,7 +16,7 @@
filename = 'regression_test.dbm'
log_total = shelve.open(filename)
-current_time = str(time.localtime()[0:5]) # specified up to minute
+current_time = str(time.localtime()[0:5]) # specified up to the minute
# run all tests in interpolate1d's test class
test_list = [name for name in dir(Test) if name.find('test_') == 0]
More information about the Scipy-svn
mailing list