Python 使用numpy/scipy从三维阵列计算等值面

Python 使用numpy/scipy从三维阵列计算等值面,python,numpy,scipy,Python,Numpy,Scipy,我有一个3D numpy数组,其中包含给定函数的值。我想计算一个二维iso曲面,或一组表示此函数某些值的iso曲面 在这种特殊情况下,3D阵列的每个1D列(column=myarray[i,j,:])都可以单独处理。所以我想知道的是函数等于某个值的最后一个索引位置(2D数组),比如说myvalue 一些(缓慢的)代码举例说明: # myarray = 3D ndarray import numpy as np from scipy import interpolate result = np.

我有一个3D numpy数组,其中包含给定函数的值。我想计算一个二维iso曲面,或一组表示此函数某些值的iso曲面

在这种特殊情况下,3D阵列的每个1D列(
column=myarray[i,j,:]
)都可以单独处理。所以我想知道的是函数等于某个值的最后一个索引位置(2D数组),比如说
myvalue

一些(缓慢的)代码举例说明:

# myarray = 3D ndarray
import numpy as np
from scipy import interpolate

result = np.zeros(nx, ny)
z_values = np.arange(nz)

for i in range(nx):
    for j in range(ny):
        f = interpolate.interp1d(my_array[i, j], z_values)
        result[i, j] = f(myvalue)

我知道使用
np.ndenumerate
和其他技巧可以加快速度,但我想知道是否已经有一种更简单的方法来实现这种iso曲面。我在
nImage
或其他库中找不到任何内容。我知道mayavi2和vtk有很多工具来处理iso曲面,但我这里的目标不是可视化——我想对这些iso曲面值执行计算,而不是显示它们。另外,vtk的许多iso曲面方法似乎涉及多边形等,我需要的只是每个iso曲面值的一个2D位置数组。

仅使用
numpy
就可以使用
argsort
sort
take
和正确的数组操作得到一个很好的解决方案。下面的函数使用加权平均值计算iso曲面:

def calc_iso_surface(my_array, my_value, zs, interp_order=6, power_parameter=0.5):
    if interp_order < 1: interp_order = 1
    from numpy import argsort, take, clip, zeros
    dist = (my_array - my_value)**2
    arg = argsort(dist,axis=2)
    dist.sort(axis=2)
    w_total = 0.
    z = zeros(my_array.shape[:2], dtype=float)
    for i in xrange(int(interp_order)):
        zi = take(zs, arg[:,:,i])
        valuei = dist[:,:,i]
        wi = 1/valuei
        clip(wi, 0, 1.e6, out=wi) # avoiding overflows
        w_total += wi**power_parameter
        z += zi*wi**power_parameter
    z /= w_total
    return z
您还可以使用不同的插值函数。请参见下面的一个示例,该示例取两个最近的
zs
的平均值:

def calc_iso_surface_2(my_array, my_value, zs):
    '''Takes the average of the two closest zs
    '''
    from numpy import argsort, take
    dist = (my_array - my_value)**2
    arg = argsort(dist,axis=2)
    z0 = take(zs, arg[:,:,0])
    z1 = take(zs, arg[:,:,1])
    z = (z0+z1)/2
    return z

感谢您优雅的解决方案!这就是我要找的。
def calc_iso_surface_2(my_array, my_value, zs):
    '''Takes the average of the two closest zs
    '''
    from numpy import argsort, take
    dist = (my_array - my_value)**2
    arg = argsort(dist,axis=2)
    z0 = take(zs, arg[:,:,0])
    z1 = take(zs, arg[:,:,1])
    z = (z0+z1)/2
    return z