Scipy interpolate 2D with one value - python

I would like to interpolate X, Y, Z in Python and return the interpolated results X, Y with z. For example
from scipy.interpolate import interp2d
x = [1, 2, 3, 4, 5]
y = [1, 2, 3, 4, 5]
z = [1, 2, 3, 4, 5]
i = interp2d(x, y, z)
i(1, 2)
Out: array([ 1.5])
So, here, the interp2d object takes X and Y to get Z. I would like to give Z to get X and Y. I think I might need a spline function.

Related

Evaluate a RegularGridInterpolator on an another regular grid

I'm having trouble understanding how to shape data to evaluate an interpolated view of an nD-array, using scipy.interpolate.RegularGridInterpolator
Considering A a (n1,n2,n3)-shaped numpy array, indexed along the following coordinates :
x = np.linspace(0, 10, 5) # n1 = 5
y = np.linspace(-1, 1, 10) # n2 = 10
z = np.linspace(0, 500, 1000) # n3 = 1000
For this example, you can generate A = ex_array with this bit of code from the documentation :
def f(x,y,z):
return 2 * x**3 + 3 * y**2 - z
ex_array = f(*np.meshgrid(x, y, z, indexing='ij', sparse=True))
Let's imagine I want to interpolate the entire array along each axis.
This is done with :
from scipy.interpolate import RegularGridInterpolator
interpolated = RegularGridInterpolator((x,y,z), ex_array)
Now, the part where my brain starts to hurt hard :
In order to evaluate this interpolator object at any given coordinates, you have to __call__ it on said point like so :
evaluated_pts = interpolated((0,1,0)) # evaluate at (x,y,z) = (5,0.5,300)
print(evaluated_pts)
In order to evaluate it on several points, you can iterate like this :
pts = ((5,0.5,_z) for _z in np.linspace(100,200,50))
evaluated_pts = interpolated(pts)
Now, what if I want to use the same logic as above, and evaluate on an entire new grid, such as :
new_x = np.linspace(2, 3, 128)
new_y = np.linspace(-0.1, 0.1, 100)
new_z = np.linspace(350, 400, 256)
As you can see now, it's not as straightforward as interpolated(new_x, new_y, new_z), and I tried to use np.meshgrid but could not figure it out.
Ideally, I'd want to output a new (128, 100, 256) array in this example.
RegularGridInterpolator input values are located on a grid. The grid points are defined using a tuple of "ticks" along each axis, for instance ((x0, x1, ..., xn), (y0, y1, ..., xm), (z0, z1, ..., zk) ) in 3D. The values are given as an nd-array of shape (n, m, k) in this case.
To evaluate the interpolated function, the assumption that the points are on a grid is no more required. Then, the asked points are defined as a list of points (actually an array of coordinates): ((x1, y1, z1), (x2, y2, z2), ... (xP, yP, zP)) i.e. a nd-array of shape (Number of points, Number of dimension).
To evaluate the interpolation on a new grid, it must be constructed using meshgrid.
reshape and transpose are used to transform arrays from one shape to another (see this question).
For example:
x = [0, 1, 2]
y = [3, 4]
z = [5, 6, 7, 8]
xyz_grid = np.meshgrid(x, y, z, indexing='ij')
xyz_list = np.reshape(xyz_grid, (3, -1), order='C').T
xyz_list
̀xyz_list could be used to call the interpolation function and it looks like that:
array([[0, 3, 5],
[0, 3, 6],
[0, 3, 7],
[0, 3, 8],
[0, 4, 5],
[0, 4, 6],
[0, 4, 7],
[0, 4, 8],
[1, 3, 5],
[1, 3, 6],
[1, 3, 7],
[1, 3, 8],
[1, 4, 5],
[1, 4, 6],
[1, 4, 7],
[1, 4, 8],
[2, 3, 5],
[2, 3, 6],
[2, 3, 7],
[2, 3, 8],
[2, 4, 5],
[2, 4, 6],
[2, 4, 7],
[2, 4, 8]])

Summing array entries along a particular line, python

I have a 2D array, and would like to sum its entries along a particular line. It should basically be like numpy.sum(), not along a column or row but rather along a line (given by an equation).
I don't really know where to start from. There is this answer which uses a Radon transfer (though I haven't managed to porperly install the skimage package).
Is there any built-in function I can start from?
Here's what I've come up with:
array = [[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
def points_on_line(x0,y0, x1,y1):
dx = x1 - x0
dy = y1 - y0
D = 2*dy - dx
y = y0
for x in range(x0, x1):
yield (x,y)
if D > 0:
y = y + 1
D = D - 2*dx
D = D + 2*dy
print(sum([array[y][x] for x, y in points_on_line(0,0, 5, 4)]))
This uses Bresenheim's Line Algorithm to find the points lying on the line between two points. It's not perfect though, and won't return all the points that it touches. This should be a good jumping off point, though!

Splitting columns of a numpy array easily

How can I split an array's columns into three arrays x, y, z without manually writing each of the [:,0],[:,1],[:,2] separately?
Example
# Create example np array
import numpy as np
data = np.array([[1,2,3],[4,5,6],[7,8,9]])
Now data is
[[1 2 3]
[4 5 6]
[7 8 9]]
What I want to do:
x, y, z = data[:,0], data[:,1], data[:,2] ## Help me here!
print(x)
Wanted output:
array([1, 4, 7])
Transpose, then unpack:
>>> x, y, z = data.T
>>> x
array([1, 4, 7])
You don't need to slice it.
>>> import numpy as np
>>> data = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> x, y, z = data.T
>>> x
array([1, 4, 7])
>>> y
array([2, 5, 8])
>>> z
array([3, 6, 9])

Interpolation with the most recent value

Say I have a set of (x,y) points in two arrays, x and y of the same length.
I would like to interpolate the values of y for new values of x_new. However, this interpolation should use the last (as "previously seen") value of y in the array.
In other words, the interpolation of
x = [0, 10, 15]
y = [1, 3, 6]
on
x_new = [1, 2, 9, 14, 16]
should return:
y_new = [1, 1, 1, 3, 6]
How can I do that in numpy? Is looping and manually checking the previous value my only alternative?
Explanation
The first element of y_new is 1, this is because its associated x_new value is 1, and the greatest, smaller than 1, x value is 0, and its y is 1.
Perhaps the best way to look at this is to consider x as temporal values, and I hoping to fill in y_new with the most recent y value.
Assume x is in increasing order. Here's how you could use np.searchsorted to do your interpolation:
In [194]: x
Out[194]: array([ 0, 10, 15])
In [195]: y
Out[195]: array([1, 3, 6])
In [196]: x_new
Out[196]: array([ 1, 2, 9, 14, 15, 16])
In [197]: i = np.searchsorted(x, x_new, side='right') - 1
In [198]: y_new = y[i]
In [199]: y_new
Out[199]: array([1, 1, 1, 3, 6, 6])
(x_new does not have to be sorted.)
This will give an incorrect result if any value in x_new is less then x[0], but that shouldn't be problem, because the process isn't defined in that case.

How do i compute with (numpy) -arrays eloquently in python

How can i express this construct in a more efficient way?
x = [2, 4, 6, 8, 10]
for p in x:
x = x/2
print x
there has to be a good way to do this.
If you are trying to divide every element of x by 2, then the following will do it:
x = np.array([2, 4, 6, 8, 10])
x /= 2
The resulting value of x is array([1, 2, 3, 4, 5]).
Note that the above uses integer (truncating) division. If you want floating-point division, either make x into a floating-point array:
x = np.array([2, 4, 6, 8, 10], dtype='float64')
or change the division to:
x = x / 2.0
If it is a numpy array You can do it all at once:
In [4]: from numpy import array
In [5]: x = array([2, 4, 6, 8, 10])
In [6]: print x/2
[1 2 3 4 5]

Categories