由数据点定义的“平面”下的卷 - python

时间:2012-01-09 17:29:42

标签: python numpy scipy

我有一个大的网格数据点网格,我是从模拟中产生的,并且与xy平面中的每个点相关联的是z值(模拟的结果)。

我将x,y,z值转储到纯文本文件中,我想要做的是测量xy平面(即.z = 0)和由此定义的“平面”之间的体积。数据点。数据点目前不是均匀间隔的,尽管它们应该在模拟运行完毕后才会出现。

我一直在查看scipy文档,我不确定scipy.integrate是否提供了我需要的功能 - 似乎只有能够在2d中执行此操作,而不是我需要的3d。

首先,除非必要,我可以不进行插值,纯粹基于“梯形规则”或类似近似的积分是一个很好的基础。

感谢任何帮助。

感谢

编辑:下面描述的解决方案都运行良好。在我的情况下,事实证明使用样条曲线可以在平面中的尖锐最大值周围引起“涟漪”,因此Delaunay方法效果更好,但我建议人们检查两者。

3 个答案:

答案 0 :(得分:4)

答案 1 :(得分:3)

如果你想严格遵守梯形规则,你可以做类似的事情:

import numpy as np
import scipy.spatial

def main():
    xyz = np.random.random((100, 3))
    area_underneath = trapezoidal_area(xyz)
    print area_underneath

def trapezoidal_area(xyz):
    """Calculate volume under a surface defined by irregularly spaced points
    using delaunay triangulation. "x,y,z" is a <numpoints x 3> shaped ndarray."""
    d = scipy.spatial.Delaunay(xyz[:,:2])
    tri = xyz[d.vertices]

    a = tri[:,0,:2] - tri[:,1,:2]
    b = tri[:,0,:2] - tri[:,2,:2]
    proj_area = np.cross(a, b).sum(axis=-1)
    zavg = tri[:,:,2].sum(axis=1)
    vol = zavg * np.abs(proj_area) / 6.0
    return vol.sum()

main()

样条曲线或线性(梯形)插值是否更适合将在很大程度上取决于您的问题。

答案 2 :(得分:2)

Joe Kington 的回答几乎不错(并且性能很高),但并不完全正确。 这是正确的代码,使用@ 运算符将操作保持在正确的级别,并具有完整的 numpy 性能。

import numpy as np
import scipy.spatial

def main():
    xyz = np.random.random((100, 3))
    area_underneath = trapezoidal_area(xyz)
    print(area_underneath)

def trapezoidal_area(xyz):
    """Calculate volume under a surface defined by irregularly spaced points
    using delaunay triangulation. "x,y,z" is a <numpoints x 3> shaped ndarray."""
    d = scipy.spatial.Delaunay(xyz[:,:2])
    tri = xyz[d.vertices]

    a = tri[:,0,:2] - tri[:,1,:2]
    b = tri[:,0,:2] - tri[:,2,:2]
    vol = np.cross(a, b) @ tri[:,:,2]
    return vol.sum() / 6.0

main()