[英]Python Scipy for 2D extrapolated spline function?
我想為2D矩陣編寫外推樣條函數。 我現在擁有的是一維數組的外推樣條函數,如下所示。 使用scipy.interpolate.InterpolatedUnivariateSpline() 。
import numpy as np
import scipy as sp
def extrapolated_spline_1D(x0,y0):
x0 = np.array(x0)
y0 = np.array(y0)
assert x0.shape == y.shape
spline = sp.interpolate.InterpolatedUnivariateSpline(x0,y0)
def f(x, spline=spline):
return np.select(
[(x<x0[0]), (x>x0[-1]), np.ones_like(x,dtype='bool')],
[np.zeros_like(x)+y0[0], np.zeros_like(x)+y0[-1], spline(x)])
return f
它取x0(定義函數的位置)和y0(相應的值)。 當x <x0 [0]時,y = y0 [0]; 當x> x0 [-1]時,y = y0 [-1]。 在此,假設x0為升序。
我想有一個類似的推斷樣條函數使用二維矩陣處理np.select()在extrapolated_spline_1D。 我認為scipy.interpolate.RectBivariateSpline()可能會有所幫助,但我不確定該怎么做。
作為參考,我當前的extrapolated_spline_2D版本非常慢 。 基本思想是:
(1)首先,給定一維數組x0,y0和2D數組z2d0作為輸入,使nx0 extrapolated_spline_1D函數y0_spls,每個函數代表在y0上定義的z2d0層;
(2)其次,對於不在網格上的點(x,y),計算nx0個值,每個值等於y0_spls [i](y);
(3)第三,擬合(X0,y0_spls [I](Y))與extrapolated_spline_1D到x_spl和(x)作為最終結果返回x_spl。
def extrapolated_spline_2D(x0,y0,z2d0):
'''
x0,y0 : array_like, 1-D arrays of coordinates in strictly monotonic order.
z2d0 : array_like, 2-D array of data with shape (x.size,y.size).
'''
nx0 = x0.shape[0]
ny0 = y0.shape[0]
assert z2d0.shape == (nx0,ny0)
# make nx0 splines, each of which stands for a layer of z2d0 on y0
y0_spls = [extrapolated_spline_1D(y0,z2d0[i,:]) for i in range(nx0)]
def f(x, y):
'''
f takes 2 arguments at the same time --> x, y have the same dimention
Return: a numpy ndarray object with the same shape of x and y
'''
x = np.array(x,dtype='f4')
y = np.array(y,dtype='f4')
assert x.shape == y.shape
ndim = x.ndim
if ndim == 0:
'''
Given a point on the xy-plane.
Make ny = 1 splines, each of which stands for a layer of new_xs on x0
'''
new_xs = np.array([y0_spls[i](y) for i in range(nx0)])
x_spl = extrapolated_spline_1D(x0,new_xs)
result = x_spl(x)
elif ndim == 1:
'''
Given a 1-D array of points on the xy-plane.
'''
ny = len(y)
new_xs = np.array([y0_spls[i](y) for i in range(nx0)]) # new_xs.shape = (nx0,ny)
x_spls = [extrapolated_spline_1D(x0,new_xs[:,i]) for i in range(ny)]
result = np.array([x_spls[i](x[i]) for i in range(ny)])
else:
'''
Given a multiple dimensional array of points on the xy-plane.
'''
x_flatten = x.flatten()
y_flatten = y.flatten()
ny = len(y_flatten)
new_xs = np.array([y0_spls[i](y_flatten) for i in range(nx0)])
x_spls = [extrapolated_spline_1D(x0,new_xs[:,i]) for i in range(ny)]
result = np.array([x_spls[i](x_flatten[i]) for i in range(ny)]).reshape(y.shape)
return result
return f
我想我自己想出了一個答案,該答案利用了scipy.interpolate.RectBivariateSpline() ,比我的舊答案快10倍以上。
這是函數extrapolated_spline_2D_new 。
def extrapolated_spline_2D_new(x0,y0,z2d0):
'''
x0,y0 : array_like,1-D arrays of coordinates in strictly ascending order.
z2d0 : array_like,2-D array of data with shape (x.size,y.size).
'''
assert z2d0.shape == (x0.shape[0],y0.shape[0])
spline = scipy.interpolate.RectBivariateSpline(x0,y0,z2d0,kx=3,ky=3)
'''
scipy.interpolate.RectBivariateSpline
x,y : array_like, 1-D arrays of coordinates in strictly ascending order.
z : array_like, 2-D array of data with shape (x.size,y.size).
'''
def f(x,y,spline=spline):
'''
x and y have the same shape with the output.
'''
x = np.array(x,dtype='f4')
y = np.array(y,dtype='f4')
assert x.shape == y.shape
ndim = x.ndim
# We want the output to have the same dimension as the input,
# and when ndim == 0 or 1, spline(x,y) is always 2D.
if ndim == 0: result = spline(x,y)[0][0]
elif ndim == 1:
result = np.array([spline(x[i],y[i])[0][0] for i in range(len(x))])
else:
result = np.array([spline(x.flatten()[i],y.flatten()[i])[0][0] for i in range(len(x.flatten()))]).reshape(x.shape)
return result
return f
注意:在上述版本中,我是一個接一個地計算值,而不是使用下面的代碼。
def f(x,y,spline=spline):
'''
x and y have the same shape with the output.
'''
x = np.array(x,dtype='f4')
y = np.array(y,dtype='f4')
assert x.shape == y.shape
ndim = x.ndim
if ndim == 0: result = spline(x,y)[0][0]
elif ndim == 1:
result = spline(x,y).diagonal()
else:
result = spline(x.flatten(),y.flatten()).diagonal().reshape(x.shape)
return result
因為當我嘗試使用下面的代碼進行計算時,有時會顯示錯誤消息:
<ipython-input-65-33285fd2319d> in f(x, y, spline)
29 if ndim == 0: result = spline(x,y)[0][0]
30 elif ndim == 1:
---> 31 result = spline(x,y).diagonal()
32 else:
33 result = spline(x.flatten(),y.flatten()).diagonal().reshape(x.shape)
/usr/local/lib/python2.7/site-packages/scipy/interpolate/fitpack2.pyc in __call__(self, x, y, mth, dx, dy, grid)
826 z,ier = dfitpack.bispev(tx,ty,c,kx,ky,x,y)
827 if not ier == 0:
--> 828 raise ValueError("Error code returned by bispev: %s" % ier)
829 else:
830 # standard Numpy broadcasting
ValueError: Error code returned by bispev: 10
我不知道這是什么意思
我做了一個名為GlobalSpline2D類似的工作在這里 ,並在任一襯,三次,五次或花鍵完美的作品。
基本上,它繼承了interp2d ,並通過InterpolatedUnivariateSpline將用法推廣到2D外推。 它們都是內部的功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.