[Scipy-svn] r3027 - trunk/Lib/interpolate
scipy-svn at scipy.org
scipy-svn at scipy.org
Tue May 22 03:15:39 EDT 2007
Author: oliphant
Date: 2007-05-22 02:15:29 -0500 (Tue, 22 May 2007)
New Revision: 3027
Modified:
trunk/Lib/interpolate/interpolate.py
Log:
Add smoothest option for interpolation --- finds interpolant that minimizes the discontinuity.
Modified: trunk/Lib/interpolate/interpolate.py
===================================================================
--- trunk/Lib/interpolate/interpolate.py 2007-05-22 01:49:39 UTC (rev 3026)
+++ trunk/Lib/interpolate/interpolate.py 2007-05-22 07:15:29 UTC (rev 3027)
@@ -9,6 +9,7 @@
logical_or, atleast_1d, atleast_2d, meshgrid, ravel
import numpy as np
import scipy.linalg as slin
+import math
import fitpack
@@ -352,6 +353,57 @@
res = array([np.dot(V[k,:],pp[:,indxs[k]]) for k in xrange(len(xnew))])
return res
+def _setdiag(a, k, v):
+ assert (a.ndim==2)
+ M,N = a.shape
+ if k > 0:
+ start = k
+ num = N-k
+ else:
+ num = M+k
+ start = abs(k)*N
+ end = start + num*(N+1)-1
+ a.flat[start:end:(N+1)] = v
+
+# Return the spline that minimizes the dis-continuity of the
+# "order-th" derivative; for order >= 2.
+
+def _find_smoothest2(xk, yk):
+ N = len(xk)-1
+ Np1 = N+1
+ # find pseudo-inverse of B directly.
+ Bd = np.empty((Np1,N))
+ for k in range(-N,N):
+ if (k<0):
+ l = np.arange(-k,Np1)
+ v = (l+k+1)
+ if ((k+1) % 2):
+ v = -v
+ else:
+ l = np.arange(k,N)
+ v = N-l
+ if ((k % 2)):
+ v = -v
+ _setdiag(Bd,k,v)
+ Bd /= (Np1)
+ V2 = np.ones((Np1,))
+ V2[1::2] = -1
+ V2 /= math.sqrt(Np1)
+ dk = np.diff(xk)
+ b = 2*np.diff(yk)/dk
+ J = np.zeros((N-1,N+1))
+ idk = 1.0/dk
+ _setdiag(J,0,idk[:-1])
+ _setdiag(J,1,-idk[1:]-idk[:-1])
+ _setdiag(J,2,idk[1:])
+ A = np.dot(J.T,J)
+ val = np.dot(V2,np.dot(A,V2))
+ res1 = np.dot(np.outer(V2,V2)/val,A)
+ mk = np.dot(np.eye(Np1)-res1,np.dot(Bd,b))
+ return mk
+
+
+
def _get_spline2_Bb(xk, yk, kind, conds):
Np1 = len(xk)
dk = xk[1:]-xk[:-1]
@@ -552,6 +604,7 @@
c0 += (yk[:-1]*xk[1:] - yk[1:]*xk[:-1])/dk
return ppform([c3,c2,c1,c0], xk)
+
def splmake(xk,yk,order=3,kind='not-a-knot',conds=None):
"""Return an (mk,xk,yk,order) representation of a spline given
data-points
@@ -562,7 +615,7 @@
kind can be 'natural', 'second', 'first', 'clamped', 'endslope',
'periodic', 'symmetric', 'parabolic', 'not-a-knot',
- 'runout'
+ 'runout', 'smoothest'
for 'second', and 'first' conditions can be given which should
be the desired second and first derivatives at
@@ -577,11 +630,17 @@
if order < 2:
raise ValueError("order cannot be negative")
+ if kind == 'smoothest':
+ func = eval('_find_smoothest%d' % order)
+ mk = func(xk,yk)
+ return mk, xk, yk, order
+
try:
func = eval('_get_spline%d_Bb'%order)
except NameError:
raise ValueError("order %d not available" % order)
+
B,b,exfunc,nlu = func(xk, yk, kind, conds)
if nlu is None:
@@ -597,13 +656,19 @@
return mk, xk, yk, order
def spleval((mk,xk,yk,order),xnew):
+ """Evaluate a spline represented by a tuple at the new x-values.
+ """
func = eval('_sp%deval'%order)
return func((mk,xk,yk),xnew)
def spltopp(mk,xk,yk,order=3):
+ """Return a piece-wise polynomial object from a spline tuple.
+ """
return eval('_sp%dtopp'%order)(mk,xk,yk)
def spline(xk,yk,xnew,order=3,kind='not-a-knot',conds=None):
+ """Interpolate a curve (xk,yk) at points xnew using a spline fit.
+ """
func = eval('_sp%deval'%order)
return func(splmake(xk,yk,order=order,kind=kind,conds=conds)[:-1],xnew)
More information about the Scipy-svn
mailing list