Reputation: 11
I have a function of Everett interpolation and I'd like to make it a little bit faster than it is right now. It works very well b
x and y are the parameters: time and values. xi is the time which I want to have interpolated value.
def everett(x,y,xi):
'''
function everett
INPUT:
x list float
y list float
xi float
RETURN:
yi float
'''
n = len(x) #interpolation degree
h = x[1]-x[0] #differences between epochs
D = np.zeros([n,n+1])
D[:,0] = x
D[:,1] = y
for j in range(1,n): #loop to each column
for i in range(0,n-j): #loop to cell within a column
D[i,j+1] = D[i+1,j] - D[i,j]
#Finding the value of u
for i in range(0,n):
u = ( xi - x[i] ) / h
if u == 0:
return y[i]
elif( u > 0 and u < 1.0 ):
break
if i == n-1:
return None
z = i
w = 1 - u
i = 0
yi = 0
m1 = u
m2 = w
for j in range(1,n+1,2):
yi += m1 * D[z+1-i,j] + m2 * D[z-i,j]
i = i + 1
m1 *= (u - i) * (u + i) / ((j+1)*(j+2))
m2 *= (w - i) * (w + i) / ((j+1)*(j+2))
if (z-i)<0 or (z+1-i)>(n-j-1):
break #//checks validity of index in the table
return yi
Thx!
EDIT: some modification using numpy
I change this part of code:
#Finding the value of u
for i in range(0,n):
u = ( xi - x[i] ) / h
if u == 0:
return y[i]
elif( u > 0 and u < 1.0 ):
break
if i == n-1:
return None
by this one:
#Finding the value of u
u = (xi - x) /h
u0 = np.where(u == 0)[0]
if u0.size:
return y[u0[0]]
i = np.where((u > 0) & (u < 1.0))[0]
if not i.size:
return None
z = i[0]
u = u[z]
the biggest problem I have right now is how to modify the last loop and the first loop where variable D
is filled with values.
Any ideas?
Upvotes: 0
Views: 207
Reputation: 428
Include numpy, put the data into numpy.array()s and use numpy operations. You'll simplify your code and get, potentially, orders of magnitude better performance. If you're comfortable with Matlab, you'll find numpy easy to learn.
Loops like
for i in range(0,n):
u = ( xi - x[i] ) / h
become simple one liners:
u = (xi - x) / h
(where x is an array, u will be an array and the -
and /
will do element-wise arithmetic if xi
and h
are numbers)
This even works for whole arrays. For example, a forward difference can be expressed in 1D as
Dx = X[1:] - x[:1]
The X[1:] means the elements of X excluding the first and X[:1] means the elements of X excluding the last.
You can do the same on N-dimensional arrays, eliminating nested loops.
I wrote this article a long time ago, but it's still relevant. You'll see where I use numpy to speed up a finite difference calculation on a mesh (solving the 2D diffusion equation) while also simplifying the code: http://www.timteatro.net/2010/10/29/performance-python-solving-the-2d-diffusion-equation-with-numpy/
If I get a chance, I will come back and help you work on your specific code. But actually, I think this algorithm is a perfect project to introduce yourself to numpy.
And, if you're more interested in the result than you are the method, SciPy (an extension of numpy) has interpolation functions:
http://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html
Upvotes: 1