Multivariate (3D) Interpolation Using Vandermonde Matrix in Python - python

I can't seem to figure out how to implement the Vandermonde Matrix into Multivariate Interpolation. I am able to get the actual matrix, but I don't understand how to get the values (array) c00,c01,c02... . I know that c = V/z, but I feel like I am missing something (perhaps, not division?). I also know that I need to somehow set up a system of equations (the columns of V are each cij).
How do you do this in python?
Here is what I have so far:
import numpy as np
x = [1, 1, 1, 2, 2, 2, 3, 3, 3]
y = [1, 2, 3, 1, 2, 3, 1, 2, 3]
z = [3.2, 4.4, 6.5, 2.5, 4.7, 5.8, 5.1, 3.6, 2.9]
numpy.polynomial.polynomial.polyvander2d(x, y, [2,2])
>>>array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 2., 4., 1., 2., 4., 1., 2., 4.],
[ 1., 3., 9., 1., 3., 9., 1., 3., 9.],
[ 1., 1., 1., 2., 2., 2., 4., 4., 4.],
[ 1., 2., 4., 2., 4., 8., 4., 8., 16.],
[ 1., 3., 9., 2., 6., 18., 4., 12., 36.],
[ 1., 1., 1., 3., 3., 3., 9., 9., 9.],
[ 1., 2., 4., 3., 6., 12., 9., 18., 36.],
[ 1., 3., 9., 3., 9., 27., 9., 27., 81.]])
np.dot(V, c.flat)and numpy.polynomial.polynomial.polyval2d(x, y, c) I think have to be incorporated into this somehow, but I don't know what to do. Please help!
I am supposed to output:
c = V \ z
c =
0.97500
-5.27500
5.95000
-3.92500
19.82500
-21.55000
3.40000
-14.70000
18.50000
Here is the site where I got this example (They used MatLab):
https://ece.uwaterloo.ca/~dwharder/NumericalAnalysis/05Interpolation/multi/
Hope this helps!

Given positions x and y:
x = [1, 1, 1, 2, 2, 2, 3, 3, 3]
y = [1, 2, 3, 1, 2, 3, 1, 2, 3]
and function values z:
z = [3.2, 4.4, 6.5, 2.5, 4.7, 5.8, 5.1, 3.6, 2.9]
V will be the Vandermonde matrix:
V = numpy.polynomial.polynomial.polyvander2d(x, y, [2,2])
V = array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 2., 4., 1., 2., 4., 1., 2., 4.],
[ 1., 3., 9., 1., 3., 9., 1., 3., 9.],
[ 1., 1., 1., 2., 2., 2., 4., 4., 4.],
[ 1., 2., 4., 2., 4., 8., 4., 8., 16.],
[ 1., 3., 9., 2., 6., 18., 4., 12., 36.],
[ 1., 1., 1., 3., 3., 3., 9., 9., 9.],
[ 1., 2., 4., 3., 6., 12., 9., 18., 36.],
[ 1., 3., 9., 3., 9., 27., 9., 27., 81.]])
Each row:
a = x[i]
b = y[i]
V[i,:] = [ 1, b, b², a, a*b, a*b², a², a²b, a²b²]
A linear interpolation aims to solve:
$$z = V \cdot c$$
therefore we need to solve:
$$c = V^{-1} z$$
c = np.linalg.solve(V, z)
c now holds the coefficients in the same orders as the Vandermonde matrix does.
You can evaluate it manually:
def poly_eval(x, y, z):
return z[0] + z[1]*y + z[2]*np.power(y,2) + z[3]*x + z[4]*x*y + z[5]*x*np.power(y,2) + z[6]*np.power(x,2) + z[7]*np.power(x,2)*y + z[8]*np.power(x,2)*np.power(y,2)
or use
np.polynomial.polynomial.polyval2d([1,2], [3,4], c)
Out[22]: array([-65.5, -88.4])

Related

find the median frequency of the resultant fft magnitude

I am having my head confused around computing the median frequency from the fft I computed over my data, using the following function:
import numpy as np
from scipy.fft import fft, fftfreq
def fft_transfrom(data):
# data has a 4D shape
fourier = fft(data, axis=2)
mag = np.round(np.abs(fourier), 0)
fs = 5 # sample size
freq = fftfreq(fs, d=1/fs)
return mag, freq
And this sample data:
A = np.array([
[[[0, 1, 2, 3],
[3, 0, 1, 2],
[2, 3, 0, 1],
[1, 3, 2, 1],
[1, 2, 3, 0]]],
[[[9, 8, 7, 6],
[5, 4, 3, 2],
[0, 9, 8, 3],
[1, 9, 2, 3],
[1, 0, -1, 2]]],
[[[0, 7, 1, 2],
[1, 2, 1, 0],
[0, 2, 0, 7],
[-1, 3, 0, 1],
[1, 0, 1, 0]]]
])
So I get the magnitude and frequencies like so:
magnitude, frequency = fft_transfrom(A)
magnitude
array([[[[ 7., 9., 8., 7.],
[ 3., 4., 3., 3.],
[ 2., 2., 1., 2.],
[ 2., 2., 1., 2.],
[ 3., 4., 3., 3.]]],
[[[16., 30., 19., 16.],
[11., 7., 7., 2.],
[ 6., 11., 9., 5.],
[ 6., 11., 9., 5.],
[11., 7., 7., 2.]]],
[[[ 1., 14., 3., 10.],
[ 2., 4., 2., 6.],
[ 2., 7., 1., 7.],
[ 2., 7., 1., 7.],
[ 2., 4., 2., 6.]]]])
And sorted like so:
sorted_magnitude = np.sort(magnitude, axis=2)
sorted_magnitude
array([[[[ 2., 2., 1., 2.],
[ 2., 2., 1., 2.],
[ 3., 4., 3., 3.],
[ 3., 4., 3., 3.],
[ 7., 9., 8., 7.]]],
[[[ 6., 7., 7., 2.],
[ 6., 7., 7., 2.],
[11., 11., 9., 5.],
[11., 11., 9., 5.],
[16., 30., 19., 16.]]],
[[[ 1., 4., 1., 6.],
[ 2., 4., 1., 6.],
[ 2., 7., 2., 7.],
[ 2., 7., 2., 7.],
[ 2., 14., 3., 10.]]]])
Now that each array column (instance column) are sorted.
But I have problem finding the frequency that corresponds to the middle of the sorted power spectrum
median_frequency = frequency[np.where(magnitude ==
sorted_magnitude[int(len(magnitude)/2)])]
IndexError: too many indices for array: array is 1-dimensional, but 4 were indexed
How do I get the frequencies of the middle magnitude in each array.
I can directly get the median of each array in magnitude using:
np.median(magnitude, axis=2)
array([[[ 3., 4., 3., 3.]],
[[11., 11., 9., 5.]],
[[ 2., 7., 2., 7.]]])
How then do I get the frequency corresponding to the median power spectrum?

multiplication of all the combination of elements in certain dimension

I'm trying to do multiplication of all the combination of elements in a certain dimension.
For example,
using for loops it would be
for a,i in enumerate(A):
for b,j in enumerate(B):
c[i][j] = a[1]*b[0]
not using for loop would be
A[:,None,1]*B[:,0]
this worked fine for 2-dimensions(A.shape=(4,2),B.shape=(4,2)).
However, When I am expanding above procedures to 3-dimensions(A.shape=(2,4,2),B.shape=(2,4,2)).
I tried with
A[:,:,1]*B[:,:,None,0]
but gives me an error.
How can I do this without using for loops???
For 2-dimensional tensors this is what I get
a = torch.FloatTensor([[0,1],[0,2],[0,3],[0,4]])
b = torch.FloatTensor([[1,0],[2,0],[3,0],[4,0]])
c = a[:,None,0] * b[:,1]
print(c)
tensor([[ 1., 2., 3., 4.],
[ 2., 4., 6., 8.],
[ 3., 6., 9., 12.],
[ 4., 8., 12., 16.]])
but in the case of
A = torch.cat([a.unsqueeze(0),a.unsqueeze(0)],dim=0)
B = torch.cat([b.unsqueeze(0),b.unsqueeze(0)],dim=0)
C = A[:,:,None,0] * B[:,:,1] << RuntimeError
RuntimeError: The size of tensor a (4) must match the size of tensor b (2) at non-singleton dimension 1
what I want is
tensor([[[ 1., 2., 3., 4.],
[ 2., 4., 6., 8.],
[ 3., 6., 9., 12.],
[ 4., 8., 12., 16.]],
[[ 1., 2., 3., 4.],
[ 2., 4., 6., 8.],
[ 3., 6., 9., 12.],
[ 4., 8., 12., 16.]]])
I cannot think of a way to do this without using for loop in dimension 0.

Combine two numpy array together

I have two numpy array like this,
this is the first one, called "pred_test"
array([2., 2., 2., 2., 2., 1., 2., 2., 2., 3., 2., 2., 3., 2., 2., 2., 2.,
2., 3., 3.], dtype=float32)
and this is the second one, called "pred_train"
array([13., 11., 9., 5., 5., 3., 2., 1., 1., 1., 4., 5., 11.,
9., 9., 4., 4., 3., 2., 1., 1., 1., 2., 1., 11., 12.,
8., 3., 3., 4., 4., 2., 2., 1., 2., 2., 4., 3., 2.,
1., 1., 1., 1., 1., 2., 1., 1., 2., 3., 2., 3., 2.,
2., 2., 2., 2., 2., 1., 2., 2., 10., 2., 2., 2., 2.,
2., 2., 3., 3., 2., 2., 3., 4., 2., 3., 3.],
dtype=float32)
How can i combine the two array to look like pred_train + pred test, something like this..
[2., 2., 2., 2., 2., 1., 2., 2., 2., 3., 2., 2., 3., 2., 2., 2., 2., 2., 3., 3.,
13., 11., 9., 5., 5., 3., 2., 1., 1., 1., 4., 5., 11.,
9., 9., 4., 4., 3., 2., 1., 1., 1., 2., 1., 11., 12.,
8., 3., 3., 4., 4., 2., 2., 1., 2., 2., 4., 3., 2.,
1., 1., 1., 1., 1., 2., 1., 1., 2., 3., 2., 3., 2.,
2., 2., 2., 2., 2., 1., 2., 2., 10., 2., 2., 2., 2.,
2., 2., 3., 3., 2., 2., 3., 4., 2., 3., 3.]
Can someone help me? Thank you..
Use numpy.concatenate((pred_test, pred_train))
You can go with:
np.append(pred_test, pred_train)

python - numpy - summation of numpy arrays of different dimension

Suppose we create an numpy array like this:
x = np.linspace(1,5,5).reshape(-1,1)
which results in this:
array([[ 1.],
[ 2.],
[ 3.],
[ 4.],
[ 5.]])
now we add the transpose of this array to it:
x + x.T
which results in this:
array([[ 2., 3., 4., 5., 6.],
[ 3., 4., 5., 6., 7.],
[ 4., 5., 6., 7., 8.],
[ 5., 6., 7., 8., 9.],
[ 6., 7., 8., 9., 10.]])
I don't understand this because the two arrays have different dimensions (5x1 and 1x5) and I learned in linear algebra that we can only sum up matrices when they have the same dimension.
Edit: OK thanks, got it
Here, we have
x = array([[ 1.],[ 2.],[ 3.],[ 4.],[ 5.]])
x.T = array([[ 1., 2., 3., 4., 5.]])
Now you are trying to add two matrices of different dimensions (1 X 5) and (5 X 1).
The way numpy handles this is by copying elements in each row of 1st matrix across its columns to match a number of columns of 2nd matrix and copying elements in each column of 2nd matrix across its rows to match no. of rows of 1st matrix. This gives you 2 5 X 5 matrix which can be added together.
The element wise addition is done as
array([[ 1., 1., 1., 1., 1.],[ 2., 2., 2., 2., 2.,],[ 3., 3., 3., 3., 3.,],[4., 4., 4., 4., 4.],[ 5., 5., 5., 5., 5.,]]) + 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.]])
which produces the result
array([[ 2., 3., 4., 5., 6.],
[ 3., 4., 5., 6., 7.],
[ 4., 5., 6., 7., 8.],
[ 5., 6., 7., 8., 9.],
[ 6., 7., 8., 9., 10.]])

Python - Find values whose coordinates are known in several times

I would like to get several values whose i have the coordinates.
My coordinates are given by "Coord" (shape : (3, 3, 2, 3) : X and Y during 3 times and with 2 because of 2 coordinates) and my values are given by "Values" (shape : (3, 3, 3) for 3 times)
In other words, i would like to concatenate values in time with "slices" for each positions...
I dont know how to undertake that...Here there is a little part of the arrays.
import numpy as np
Coord = np.array([[[[ 4., 6., 10.],
[ 1., 3., 7.]],
[[ 3., 5., 9.],
[ 1., 3., 7.]],
[[ 2., 4., 8.],
[ 1., 3., 7.]]],
[[[ 4., 6., 10.],
[ 2., 4., 8.]],
[[ 3., 5., 9.],
[ 2., 4., 8.]],
[[ 2., 4., 8.],
[ 2., 4., 8.]]],
[[[ 4., 6., 10.],
[ 3., 5., 9.]],
[[ 3., 5., 9.],
[ 3., 5., 9.]],
[[ 2., 4., 8.],
[ 3., 5., 9.]]]])
Values = np.array([[[-4.24045246, 0.97551048, -5.78904502],
[-3.24218504, 0.9771782 , -4.79103141],
[-2.24390519, 0.97882129, -3.79298771]],
[[-4.24087775, 1.97719843, -5.79065966],
[-3.24261128, 1.97886271, -4.7926441 ],
[-2.24433235, 1.98050192, -3.79459845]],
[[-4.24129055, 2.97886284, -5.79224713],
[-3.24302502, 2.98052345, -4.79422942],
[-2.24474697, 2.98215901, -3.79618161]]])
EDIT LATER
I try in case of a simplified problem (without time first). I have used a "for loop" but
somes errors seems subsist...do you think it s the best way to treat this problem? because my arrays are important... 400x300x100
Coord3 = np.array([[[ 2, 2.],
[ 0., 1.],
[ 0., 2.]],
[[ 1., 0.],
[ 2., 1.],
[ 1., 2.]],
[[ 2., 0.],
[ 1., 1.],
[ 0., 0.]]])
Coord3 = Coord3.astype(int)
Values2 = np.array([[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.]])
b = np.zeros((3,3))
for i in range(Values2.shape[0]):
for j in range(Values2.shape[1]):
b[Coord3[i,j,0], Coord3[i,j,1]] = Values2[i,j]
b
Your second example is relatively easy to do with fancy indexing:
b = np.zeros((3,3), values2.dtype)
b[coord3[..., 0], coord3[..., 1]] = values2
The origial problem is a bit harder to do, but I think this takes care of it:
coord = coord.astype(int)
x_size = coord[..., 0, :].max() + 1
y_size = coord[..., 1, :].max() + 1
# x_size, y_size = coord.max(axis=(0, 1, 3)) + 1
nt = coord.shape[3]
b = np.zeros((x_size, y_size, nt), values.dtype)
b[coord[..., 0, :], coord[..., 1, :], np.arange(nt)] = values

Categories