在不规则网格上进行插值

发布于 2024-09-09 18:01:07 字数 392 浏览 7 评论 0原文

所以,我有三个 numpy 数组,它们在网格上存储纬度、经度和一些属性值——也就是说,我有 LAT(y,x)、LON(y,x) 和温度 T(y,x) ),对于 x 和 y 的某些限制。网格不一定是规则的——事实上,它是三极的。

然后,我想将这些属性(温度)值插入到一堆不同的纬度/经度点(存储为 lat1(t)、lon1(t),大约 10,000 t...),这些点不落在实际的网格点上。我尝试过 matplotlib.mlab.griddata,但这需要太长时间(毕竟它并不是真正为我正在做的事情而设计的)。我也尝试过 scipy.interpolate.interp2d,但出现 MemoryError (我的网格约为 400x400)。

有没有什么巧妙的、最好是快速的方法来做到这一点?我忍不住认为答案是显而易见的......谢谢!

So, I have three numpy arrays which store latitude, longitude, and some property value on a grid -- that is, I have LAT(y,x), LON(y,x), and, say temperature T(y,x), for some limits of x and y. The grid isn't necessarily regular -- in fact, it's tripolar.

I then want to interpolate these property (temperature) values onto a bunch of different lat/lon points (stored as lat1(t), lon1(t), for about 10,000 t...) which do not fall on the actual grid points. I've tried matplotlib.mlab.griddata, but that takes far too long (it's not really designed for what I'm doing, after all). I've also tried scipy.interpolate.interp2d, but I get a MemoryError (my grids are about 400x400).

Is there any sort of slick, preferably fast way of doing this? I can't help but think the answer is something obvious... Thanks!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夜雨飘雪 2024-09-16 18:01:08

我是否正确地认为您的数据网格看起来像这样(红色是旧数据,蓝色是新的插值数据)?

替代文本 http:// www.geekops.co.uk/photos/0000-00-02%20%28Forum%20images%29/DataSeparation.png

这可能是一种有点暴力的方法,但是渲染现有数据怎么样?作为位图(opengl 将通过配置正确的选项为您进行简单的颜色插值,并且您可以将数据渲染为三角形,这应该相当快)。然后,您可以在新点的位置对像素进行采样。

或者,您可以对第一组点进行空间排序,然后找到新点周围最近的旧点,并根据到这些点的距离进行插值。

Am I right in thinking your data grids look something like this (red is the old data, blue is the new interpolated data)?

alt text http://www.geekops.co.uk/photos/0000-00-02%20%28Forum%20images%29/DataSeparation.png

This might be a slightly brute-force-ish approach, but what about rendering your existing data as a bitmap (opengl will do simple interpolation of colours for you with the right options configured and you could render the data as triangles which should be fairly fast). You could then sample pixels at the locations of the new points.

Alternatively, you could sort your first set of points spatially and then find the closest old points surrounding your new point and interpolate based on the distances to those points.

喜你已久 2024-09-16 18:01:08

有一个名为 BIVAR 的 FORTRAN 库,它非常有用适合这个问题。通过一些修改,您可以使用 f2py 使其在 python 中可用。

从描述来看:

BIVAR 是一个 FORTRAN90 库,可对分散的双变量数据进行插值,作者:Hiroshi Akima。

BIVAR 接受一组散布在 2D 中的 (X,Y) 数据点以及相关的 Z 数据值,并且能够构建与给定数据一致的平滑插值函数 Z(X,Y),并且可以在平面上的其他点进行评估。

There is a FORTRAN library called BIVAR, which is very suitable for this problem. With a few modifications you can make it usable in python using f2py.

From the description:

BIVAR is a FORTRAN90 library which interpolates scattered bivariate data, by Hiroshi Akima.

BIVAR accepts a set of (X,Y) data points scattered in 2D, with associated Z data values, and is able to construct a smooth interpolation function Z(X,Y), which agrees with the given data, and can be evaluated at other points in the plane.

第七度阳光i 2024-09-16 18:01:07

尝试结合反距离加权和
scipy.spatial.KDTree
描述于SO
反距离-weighted-idw-interpolation-with-python
Kd 树
在 2d 3d ... 中工作良好,反距离加权平滑且局部,
并且 k= 最近邻居的数量可以改变以权衡速度/准确性。

Try the combination of inverse-distance weighting and
scipy.spatial.KDTree
described in SO
inverse-distance-weighted-idw-interpolation-with-python.
Kd-trees
work nicely in 2d 3d ..., inverse-distance weighting is smooth and local,
and the k= number of nearest neighbours can be varied to tradeoff speed / accuracy.

偷得浮生 2024-09-16 18:01:07

Roger Veciana 有一个 很好的反距离示例我 Rovira 以及一些使用 GDAL 写入 geotiff 的代码(如果您对此感兴趣)。

这对于常规网格来说很粗糙,但假设您首先使用 pyproj 或其他东西将数据投影到像素网格,同时要小心数据使用的投影。

他的算法和示例脚本的副本

from math import pow  
from math import sqrt  
import numpy as np  
import matplotlib.pyplot as plt  
  
def pointValue(x,y,power,smoothing,xv,yv,values):  
    nominator=0  
    denominator=0  
    for i in range(0,len(values)):  
        dist = sqrt((x-xv[i])*(x-xv[i])+(y-yv[i])*(y-yv[i])+smoothing*smoothing);  
        #If the point is really close to one of the data points, return the data point value to avoid singularities  
        if(dist<0.0000000001):  
            return values[i]  
        nominator=nominator+(values[i]/pow(dist,power))  
        denominator=denominator+(1/pow(dist,power))  
    #Return NODATA if the denominator is zero  
    if denominator > 0:  
        value = nominator/denominator  
    else:  
        value = -9999  
    return value  
  
def invDist(xv,yv,values,xsize=100,ysize=100,power=2,smoothing=0):  
    valuesGrid = np.zeros((ysize,xsize))  
    for x in range(0,xsize):  
        for y in range(0,ysize):  
            valuesGrid[y][x] = pointValue(x,y,power,smoothing,xv,yv,values)  
    return valuesGrid  
      
  
if __name__ == "__main__":  
    power=1  
    smoothing=20  
  
    #Creating some data, with each coodinate and the values stored in separated lists  
    xv = [10,60,40,70,10,50,20,70,30,60]  
    yv = [10,20,30,30,40,50,60,70,80,90]  
    values = [1,2,2,3,4,6,7,7,8,10]  
      
    #Creating the output grid (100x100, in the example)  
    ti = np.linspace(0, 100, 100)  
    XI, YI = np.meshgrid(ti, ti)  
  
    #Creating the interpolation function and populating the output matrix value  
    ZI = invDist(xv,yv,values,100,100,power,smoothing)  
  
  
    # Plotting the result  
    n = plt.normalize(0.0, 100.0)  
    plt.subplot(1, 1, 1)  
    plt.pcolor(XI, YI, ZI)  
    plt.scatter(xv, yv, 100, values)  
    plt.title('Inv dist interpolation - power: ' + str(power) + ' smoothing: ' + str(smoothing))  
    plt.xlim(0, 100)  
    plt.ylim(0, 100)  
    plt.colorbar()  
  
    plt.show() 

There is a nice inverse distance example by Roger Veciana i Rovira along with some code using GDAL to write to geotiff if you're into that.

This is of coarse to a regular grid, but assuming you project the data first to a pixel grid with pyproj or something, all the while being careful what projection is used for your data.

A copy of his algorithm and example script:

from math import pow  
from math import sqrt  
import numpy as np  
import matplotlib.pyplot as plt  
  
def pointValue(x,y,power,smoothing,xv,yv,values):  
    nominator=0  
    denominator=0  
    for i in range(0,len(values)):  
        dist = sqrt((x-xv[i])*(x-xv[i])+(y-yv[i])*(y-yv[i])+smoothing*smoothing);  
        #If the point is really close to one of the data points, return the data point value to avoid singularities  
        if(dist<0.0000000001):  
            return values[i]  
        nominator=nominator+(values[i]/pow(dist,power))  
        denominator=denominator+(1/pow(dist,power))  
    #Return NODATA if the denominator is zero  
    if denominator > 0:  
        value = nominator/denominator  
    else:  
        value = -9999  
    return value  
  
def invDist(xv,yv,values,xsize=100,ysize=100,power=2,smoothing=0):  
    valuesGrid = np.zeros((ysize,xsize))  
    for x in range(0,xsize):  
        for y in range(0,ysize):  
            valuesGrid[y][x] = pointValue(x,y,power,smoothing,xv,yv,values)  
    return valuesGrid  
      
  
if __name__ == "__main__":  
    power=1  
    smoothing=20  
  
    #Creating some data, with each coodinate and the values stored in separated lists  
    xv = [10,60,40,70,10,50,20,70,30,60]  
    yv = [10,20,30,30,40,50,60,70,80,90]  
    values = [1,2,2,3,4,6,7,7,8,10]  
      
    #Creating the output grid (100x100, in the example)  
    ti = np.linspace(0, 100, 100)  
    XI, YI = np.meshgrid(ti, ti)  
  
    #Creating the interpolation function and populating the output matrix value  
    ZI = invDist(xv,yv,values,100,100,power,smoothing)  
  
  
    # Plotting the result  
    n = plt.normalize(0.0, 100.0)  
    plt.subplot(1, 1, 1)  
    plt.pcolor(XI, YI, ZI)  
    plt.scatter(xv, yv, 100, values)  
    plt.title('Inv dist interpolation - power: ' + str(power) + ' smoothing: ' + str(smoothing))  
    plt.xlim(0, 100)  
    plt.ylim(0, 100)  
    plt.colorbar()  
  
    plt.show() 
魔法唧唧 2024-09-16 18:01:07

这里有很多选项,哪一个最好取决于您的数据......
但是我不知道适合您的现成解决方案

您说您的输入数据来自三极数据。对于如何构建这些数据,存在三种主要情况。

  1. 从三极空间中的 3d 网格采样,投影回 2d LAT、LON 数据。
  2. 从三极空间中的二维网格采样,投影为二维 LAT LON 数据。
  3. 三极空间中的非结构化数据投影到 2d LAT LON 数据

其中最简单的是 2。不是在 LAT LON 空间中插值,而是“只是”将您的点转换回源空间并在那里插值。

适用于 1 和 2 的另一个选项是搜索从三极空间映射的单元以覆盖您的样本点。 (您可以使用 BSP 或网格类型结构来加速此搜索)选择一个单元格,然后在其中进行插值。

最后还有一堆非结构化插值选项..但它们往往很慢。
我个人最喜欢的是使用最近 N 个点的线性插值,找到这 N 个点可以再次通过网格或 BSP 来完成。另一个不错的选择是对非结构化点进行 Delauney 三角剖分,并在生成的三角网格上进行插值。

就我个人而言,如果我的网格是情况 1,我会使用非结构化策略,因为我担心必须处理具有重叠投影的单元格搜索。选择“正确”的细胞会很困难。

There's a bunch of options here, which one is best will depend on your data...
However I don't know of an out-of-the-box solution for you

You say your input data is from tripolar data. There are three main cases for how this data could be structured.

  1. Sampled from a 3d grid in tripolar space, projected back to 2d LAT, LON data.
  2. Sampled from a 2d grid in tripolar space, projected into 2d LAT LON data.
  3. Unstructured data in tripolar space projected into 2d LAT LON data

The easiest of these is 2. Instead of interpolating in LAT LON space, "just" transform your point back into the source space and interpolate there.

Another option that works for 1 and 2 is to search for the cells that maps from tripolar space to cover your sample point. (You can use a BSP or grid type structure to speed up this search) Pick one of the cells, and interpolate inside it.

Finally there's a heap of unstructured interpolation options .. but they tend to be slow.
A personal favourite of mine is to use a linear interpolation of the nearest N points, finding those N points can again be done with gridding or a BSP. Another good option is to Delauney triangulate the unstructured points and interpolate on the resulting triangular mesh.

Personally if my mesh was case 1, I'd use an unstructured strategy as I'd be worried about having to handle searching through cells with overlapping projections. Choosing the "right" cell would be difficult.

无法言说的痛 2024-09-16 18:01:07

我建议您看一下 GRASS(开源 GIS 软件包)插值功能 (http://grass.ibiblio.org/gdp/html_grass62/v.surf.bspline.html)。它不是用 python 编写的,但您可以重新实现它或与 C 代码交互。

I suggest you taking a look at GRASS (an open source GIS package) interpolation features (http://grass.ibiblio.org/gdp/html_grass62/v.surf.bspline.html). It's not in python but you can reimplement it or interface with C code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文