Python 使用numpy/scipy从三维阵列计算等值面
我有一个3D numpy数组,其中包含给定函数的值。我想计算一个二维iso曲面,或一组表示此函数某些值的iso曲面 在这种特殊情况下,3D阵列的每个1D列(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.
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