简体   繁体   English

二维非结构化网格数据的插值

[英]Interpolation over 2d unstructured grid data

I have some data (x,y,z) lying on an unstructured grid and I would like to interpolate the data for visualization purposes. 我有一些数据 (x,y,z)放在一个非结构化的网格上,我想对这些数据进行插值以用于可视化目的。

I have already tried scipy.interpolate.griddata , the interpolation assumes everywhere the same value. 我已经尝试过scipy.interpolate.griddata ,插值在所有地方都假定为相同的值。 After that I tried scipy.interpolate.Rbf , but this gets me a memory error (see code below). 之后,我尝试了scipy.interpolate.Rbf ,但是这使我遇到了内存错误(请参见下面的代码)。

Is there another method or other options which improve the result? 是否有其他方法或其他选项可以改善结果?

Result--> 结果->

结果

My code 我的密码

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata, Rbf

x, y, z = np.loadtxt('stackoverflow_example-data')
# griddata
points = np.reshape(np.array([x, y]),(z.size, 2))
grid_x, grid_y = np.mgrid[x.min():x.max():1000j,y.min():y.max():1000j]
counts_I_grid_1 = griddata(points, z, (grid_x, grid_y), method='nearest')
counts_I_grid_2 = griddata(points, z, (grid_x, grid_y), method='linear', fill_value=0)
counts_I_grid_3 = griddata(points, z, (grid_x, grid_y), method='cubic', fill_value=0) 

# Rbf -- fails due to memory error
#rbf = Rbf(x,y,z)
#counts_I_Rbf = rbf(grid_x,grid_y)

Traceback (most recent call last): File "/path/code.py", line 14, in rbf = Rbf(x,y,z) File "/[...]/python3.4/site-packages/scipy/interpolate/rbf.py", line 198, in init r = self._call_norm(self.xi, self.xi) File "/[...]/python3.4/site-packages/scipy/interpolate/rbf.py", line 222, in _call_norm return self.norm(x1, x2) File "/[...]/python3.4/site-packages/scipy/interpolate/rbf.py", line 114, in _euclidean_norm return sqrt(((x1 - x2)**2).sum(axis=0)) MemoryError 追溯(最近一次通话最近):文件“ /path/code.py”,第14行,在rbf = Rbf(x,y,z)中文件“ /[...]/python3.4/site-packages/scipy /initpolate/rbf.py”,第198行, init r = self._call_norm(self.xi,self.xi)文件“ /[...]/python3.4/site-packages/scipy/interpolate/rbf。 py”,第222行,_call_norm中返回self.norm(x1,x2)文件“ /[...]/python3.4/site-packages/scipy/interpolate/rbf.py”,第114行,_euclidean_norm中返回sqrt ((((x1-x2)** 2).sum(axis = 0))MemoryError

# plot the result
fig = plt.figure()

ax1 = plt.subplot(2,2,1)
plt.title('Data')
plt.gca().set_aspect((x.max() - x.min()) / (y.max() - y.min()))
plt.scatter(x, y, c=z, s=2, edgecolor='', marker=',')
plt.colorbar(ax=ax1)
plt.xlim(x.min(), x.max())
plt.ylim(y.min(), y.max())
plt.xticks([20.7,20.9,21.1,21.3])
plt.ticklabel_format(useOffset=False)

ax2 = plt.subplot(2,2,2)
plt.title('nearest')
plt.imshow(counts_I_grid_1.T, origin='lower',
           extent=(x.min(), x.max(), y.min(), y.max()),
           aspect=(x.max() - x.min()) / (y.max() - y.min()),
           vmin=0,vmax=36)
plt.colorbar(ax=ax2)
plt.xticks([20.7,20.9,21.1,21.3])
plt.ticklabel_format(useOffset=False)

ax2 = plt.subplot(2,2,3)
plt.title('linear')
plt.imshow(counts_I_grid_2.T, origin='lower',
           extent=(x.min(), x.max(), y.min(), y.max()),
           aspect=(x.max() - x.min()) / (y.max() - y.min()),
           vmin=0,vmax=36)
plt.colorbar(ax=ax2)
plt.xticks([20.7,20.9,21.1,21.3])
plt.ticklabel_format(useOffset=False)

ax2 = plt.subplot(2,2,4)
plt.title('cubic')
plt.imshow(counts_I_grid_3.T, origin='lower',
           extent=(x.min(), x.max(), y.min(), y.max()),
           aspect=(x.max() - x.min()) / (y.max() - y.min()),
           vmin=0,vmax=36)
plt.colorbar(ax=ax2)
plt.xticks([20.7,20.9,21.1,21.3])
plt.ticklabel_format(useOffset=False)
plt.tight_layout()
plt.show()

Your problem is due to a subtle mistake that is dangerous enough that I believe it's worth giving a full answer. 您的问题是由于一个微小的错误而引起的,这个错误非常危险,我认为值得给出完整的答案。

Consider this line: 考虑这一行:

points = np.reshape(np.array([x, y]),(z.size, 2))

Since your input arrays are 1d, you're trying to transform [x,y] into shape "(something, 2)". 由于您的输入数组为1d,因此您试图将[x,y]转换为形状“(something,2)”。 Note that it's valid to say 请注意,说出来是正确的

points = np.reshape(np.array([x, y]),(-1, 2))

to let numpy infer the missing dimension for you, and this would still not be what you want. 让numpy为您推断缺少的尺寸,而这仍然不是您想要的。 When you construct the 2d array 当您构建2D数组时

np.array([x, y])

you're defining a matrix row by row , thereby creating an array of shape "(2, something)". 您正在逐行定义矩阵,从而创建形状为“(2,something)”的数组。 When you call reshape on it, it will read the elements row-by-row by default, since numpy stores arrays in row-major order (like C/C++, and unlike fortran and MATLAB). 当您在其上调用reshape时,默认情况下它将逐行读取元素,因为numpy以行优先的顺序存储数组(如C / C ++,并且与fortran和MATLAB不同)。 This means that the resulting two-column array will first contain all the x values, then all the y values, rather than containing pairs of (x,y) in each row. 这意味着生成的两列数组将首先包含所有x值,然后包含所有y值,而不是在每行中包含成对的(x,y)

What you're actually trying to do is to swap the dimensions of your array, without touching its structure. 您实际上想做的是交换阵列的尺寸,而不用改变其结构。 This means that you have to transpose your matrix. 这意味着您必须转置矩阵。 This means that you have to use 这意味着您必须使用

points = np.array([x, y]).T
# or np.transpose([x,y])

instead. 代替。 Note that while this has the same shape as your original, it has the elements in the proper order: 请注意,虽然它的shape与原始shape相同,但其元素的顺序正确:

In [320]: np.reshape(np.array([x,y]),(-1,2))
Out[320]: 
array([[  20.7     ,   20.702   ],
       [  20.704   ,   20.706   ],
       [  20.708   ,   20.71    ],
       ..., 
       [ 852.356964,  852.356964],
       [ 852.356964,  852.356964],
       [ 852.356964,  852.356964]])

In [321]: np.array([x,y]).T
Out[321]: 
array([[  20.7     ,  852.357235],
       [  20.702   ,  852.357235],
       [  20.704   ,  852.357235],
       ..., 
       [  21.296   ,  852.356964],
       [  21.298   ,  852.356964],
       [  21.3     ,  852.356964]])

This will fix the inconsistency between your sample x/y points and z , and will produce the expected results. 这将解决您的样本x/y点与z之间的不一致,并产生预期的结果。 In my experience, reshape -ing is almost never called for. 以我的经验, reshape几乎从未被要求。 Often you need to flatten out an ndarray into a 1d one, but then the ravel() method of the given array is best. 通常,您需要将ndarray展平为1d数组,但是最好使用给定数组的ndarray ravel()方法。

Results as proof: left, your original with cubic interpolation; 结果证明:左,您的原件带有三次插值; right, the version with points fixed: 正确, points固定的版本:

之前 后

Note that as @MaxNoe suggested , I reduced your interpolating mesh size to 200x200. 请注意,正如@MaxNoe建议的那样 ,我将您的插值网格尺寸减小为200x200。 And as they hinted, your memory error with Rbf most probably stemmed from this huge number of interpolating points. 正如他们所暗示的那样, Rbf的内存错误很可能源于大量的插值点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM