矩形网格上的Python 4D线性插值

时间:2013-01-02 09:51:41

标签: python numpy scipy interpolation

我需要在4个维度(纬度,经度,高度和时间)内线性插值温度数据 点数相当高(360x720x50x8),我需要一种快速计算数据范围内空间和时间任意点的温度的方法。

我尝试使用scipy.interpolate.LinearNDInterpolator,但使用Qhull进行三角测量在矩形网格上效率低下,需要数小时才能完成。

通过阅读此SciPy ticket,解决方案似乎是使用标准interp1d实现新的nd插值器来计算更多数据点,然后使用“最近邻居”方法新数据集。

然而,这需要很长时间(分钟)。

是否有一种快速的方法可以在4维的矩形网格上插入数据,而无需花费数分钟才能完成?

我想过使用interp1d 4次而不用计算更高密度的点数,但留给用户用坐标调用,但我无法理解怎么做。

否则会根据我的需要编写我自己的4D内插器作为选项吗?

以下是我用来测试此代码的代码:

使用scipy.interpolate.LinearNDInterpolator

import numpy as np
from scipy.interpolate import LinearNDInterpolator

lats = np.arange(-90,90.5,0.5)
lons = np.arange(-180,180,0.5)
alts = np.arange(1,1000,21.717)
time = np.arange(8)
data = np.random.rand(len(lats)*len(lons)*len(alts)*len(time)).reshape((len(lats),len(lons),len(alts),len(time)))

coords = np.zeros((len(lats),len(lons),len(alts),len(time),4))
coords[...,0] = lats.reshape((len(lats),1,1,1))
coords[...,1] = lons.reshape((1,len(lons),1,1))
coords[...,2] = alts.reshape((1,1,len(alts),1))
coords[...,3] = time.reshape((1,1,1,len(time)))
coords = coords.reshape((data.size,4))

interpolatedData = LinearNDInterpolator(coords,data)

使用scipy.interpolate.interp1d

import numpy as np
from scipy.interpolate import LinearNDInterpolator

lats = np.arange(-90,90.5,0.5)
lons = np.arange(-180,180,0.5)
alts = np.arange(1,1000,21.717)
time = np.arange(8)
data = np.random.rand(len(lats)*len(lons)*len(alts)*len(time)).reshape((len(lats),len(lons),len(alts),len(time)))

interpolatedData = np.array([None, None, None, None])
interpolatedData[0] = interp1d(lats,data,axis=0)
interpolatedData[1] = interp1d(lons,data,axis=1)
interpolatedData[2] = interp1d(alts,data,axis=2)
interpolatedData[3] = interp1d(time,data,axis=3)

非常感谢你的帮助!

4 个答案:

答案 0 :(得分:11)

在您链接的同一张票中,有一个他们称之为 tensor product interpolation 的示例实现,显示了将递归调用嵌套到interp1d的正确方法。如果您为kind='linear'选择默认的interp1d参数,这相当于四线性插值。

虽然这可能足够好,但这不是线性插值,并且插值函数中会有更高阶的项,因为来自wikipedia entry on bilinear interpolation的图像显示:

enter image description here

对于你所追求的东西来说,这可能已经足够好了,但是有些应用程序需要三角形,真正的分段线性插值。如果你真的需要这个,那么就可以轻松地解决qhull的缓慢问题。

设置LinearNDInterpolator后,有两个步骤可以为给定点提供插值:

  1. 弄清楚哪个三角形(在你的情况下是4D高四面体),并且
  2. 使用相对于顶点的点的barycentric coordinates进行插值作为权重。
  3. 你可能不想搞乱重心坐标,所以最好留给LinearNDInterpolator。但你确实知道有关三角测量的一些事情。大多数情况下,因为你有一个规则的网格,在每个超立方体内,三角测量将是相同的。因此,为了插入单个值,您可以首先确定您的点在哪个子多维数据集中,使用该多维数据集的16个顶点构建LinearNDInterpolator,并使用它来插值:

    from itertools import product
    
    def interpolator(coords, data, point) :
        dims = len(point)
        indices = []
        sub_coords = []
        for j in xrange(dims) :
            idx = np.digitize([point[j]], coords[j])[0]
            indices += [[idx - 1, idx]]
            sub_coords += [coords[j][indices[-1]]]
        indices = np.array([j for j in product(*indices)])
        sub_coords = np.array([j for j in product(*sub_coords)])
        sub_data = data[list(np.swapaxes(indices, 0, 1))]
        li = LinearNDInterpolator(sub_coords, sub_data)
        return li([point])[0]
    
    >>> point = np.array([12.3,-4.2, 500.5, 2.5])
    >>> interpolator((lats, lons, alts, time), data, point)
    0.386082399091
    

    这对矢量化数据不起作用,因为这需要为每个可能的子立方体存储LinearNDInterpolator,即使它可能比对整个事物进行三角测量更快,但它仍然会非常慢。

答案 1 :(得分:4)

scipy.ndimage.map_coordinates 是一个很好的快速插补器,用于统一网格(所有相同大小的盒子)。 请参阅SO上的multivariate-spline-interpolation-in-python-scipy 为了清楚的描述。

对于非均匀矩形网格,一个简单的包装 Intergrid映射/缩放非均匀网格, 然后map_coordinates。 在像你这样的4d测试用例上,每个查询大约需要1微秒:

Intergrid: 1000000 points in a (361, 720, 47, 8) grid took 652 msec

答案 2 :(得分:2)

对于非常类似的事情,我使用Scientific.Functions.Interpolation.InterpolatingFunction

    import numpy as np
    from Scientific.Functions.Interpolation import InterpolatingFunction

    lats = np.arange(-90,90.5,0.5)
    lons = np.arange(-180,180,0.5)
    alts = np.arange(1,1000,21.717)
    time = np.arange(8)
    data = np.random.rand(len(lats)*len(lons)*len(alts)*len(time)).reshape((len(lats),len(lons),len(alts),len(time)))

    axes = (lats, lons, alts, time)
    f = InterpolatingFunction(axes, data)

您现在可以将其留给用户使用坐标调用InterpolatingFunction

>>> f(0,0,10,3)
0.7085675631375401

InterpolatingFunction具有很好的附加功能,例如集成和切片。

但是,我不确定插值是否是线性的。您必须查看模块源才能找到答案。

答案 3 :(得分:0)

我无法打开此地址,并且找不到有关此软件包的足够信息