使用(mayavi)mlab.contour3d绘制存储在文件中的数据?

时间:2014-03-07 04:27:18

标签: numpy mayavi mayavi.mlab

我正在努力使用从文件中读取的数据在mayavi中进行简单的contour3d绘图。数据是

形式的常规3d笛卡尔网格
   x1   y1    z1    val(x1,y1,z1)  
   x1   y1    z2    val(x1,y1,z2)  
    .    .     .       .  
   x1   y1     z_K  val(x1,y1,z_K)  

   x1   y2     z1    val(x1,y2,z1)  
    .    .     .       .  
    .    .     .       .  
   x_L   y_M    z_K    val(x_L,y_M,z_K)  

(这里每行的前3个值给出点的(x,y,z)坐标,而第4个值给出该点的标量值。如果有用,我可以粘贴最小的示例文件)< / p>

可以使用numpy.loadtxt成功读取数据文件,但是如何从那里获取 使用(mayavi)mlab.contour3d 绘制等值面?我认为是默认输出 对于mlab.contour3d,来自loadtxt的数组格式不正确。

我能找到的所有mlab.contour3d的例子都是使用ogrid生成一个网格,然后绘制这个网格的一个简单函数(sin等)。我已经能够成功运行这些示例,但它们没有告诉我如何将文件中的数据读入正确的格式 数组准备好绘图。我相信如果有人能给我一个指针,它会帮助很多新手处于类似的位置;绘制存储在由另一个程序生成的文件中的3d数据肯定是科学家必须做的最常见的绘图任务之一。

2 个答案:

答案 0 :(得分:1)

我发现以下方法可以很好地工作。

x,y,z,d是原始输入文本文件中的一维numpy数组,其中d = f(x,y,z)

# Import relevant modules
import numpy as np
import scipy.interpolate as si
from mayavi import mlab

# Generate the figure
figure = mlab.figure()

# Generate the 3D mesh
xi, yi, zi = np.meshgrid(*([np.linspace(0,1,100)] * 3))

# Interpolate d over the 3D mesh
di = si.griddata((x, y, z), d, (xi, yi, zi))

# Generate the desired figure
min_d = d.min()
max_d = d.max()
grid = mlab.pipeline.scalar_field(di)
mlab.pipeline.volume(grid, vmin=min_d, vmax=min_d + .5*(max_d-min_d))

# Other good options too
## mlab.contour3d(di, vmin=min_d, vmax=min_d + .8*(max_d-min_d))
## pts = mlab.points3d(x, y, z, d)
mlab.axes()
mlab.show()

答案 1 :(得分:0)

对E先生的延迟回复表示道歉,周末我无法访问互联网。 但是,我确实可以访问计算机,我找到了一个问题的答案,虽然有点难看。我确信可以改进以下方法,并且由于上述原因,我知道这是3d绘图软件的一个重要的基本用途,所以如果任何人有任何他们可以提供的改进,他们将不胜感激。以下说明假设您使用的是Linux,但我确信在其他操作系统上执行相同的操作(即保存和运行python文件)非常简单。

首先生成示例数据文件。真正的数据来自Fortran程序,但是对于当前的测试目的,我将使用python生成一个示例数据文件。在“gen-data.py”文件中存储以下代码(复制粘贴到您喜欢的文本编辑器中然后点击“另存为”等。)

#!/usr/bin/python
import numpy as numpy

# run this program with 
#" python  gen-data.py > stream.out  "
# to generate sample data file stream.out  
x_low = -1 ; x_upp = 1 ; NX = 5
y_low = -2 ; y_upp = 2 ; NY = 3
z_low = -3 ; z_upp = 3 ; NZ = 3

x_arr = numpy.linspace(x_low,x_upp,num = NX, endpoint=True)
y_arr = numpy.linspace(y_low,y_upp,num = NY, endpoint=True)
z_arr = numpy.linspace(z_low,z_upp,num = NZ, endpoint=True)

#the following line generates data (for distance from the origin) 
# over  a structured grid
for x in x_arr:
    for y in y_arr:
        for z in z_arr:
            print x , y , z , x**2 + y**2 + z**2

使用运行程序     python gen-data.py&gt;流出来 它将在数据文件“stream.out”中存储上述类型的样本数据文件。您应该有一个包含值的文件:
-1.0 -2.0 -3.0 14.0
-1.0 -2.0 0.0 5.0
-1.0 -2.0 3.0 14.0
-1.0 0.0 -3.0 10.0
-1.0 0.0 0.0 1.0
-1.0 0.0 3.0 10.0
-1.0 2.0 -3.0 14.0
-1.0 2.0 0.0 5.0
-1.0 2.0 3.0 14.0
-0.5 -2.0 -3.0 13.25
。 。 。 。
0.5 2.0 3.0 13.25
1.0 -2.0 -3.0 14.0
1.0 -2.0 0.0 5.0
1.0 -2.0 3.0 14.0
1.0 0.0 -3.0 10.0
1.0 0.0 0.0 1.0
1.0 0.0 3.0 10.0
1.0 2.0 -3.0 14.0
1.0 2.0 0.0 5.0
1.0 2.0 3.0 14.0
数据文件中的每一行都是形式
x y z V(x,y,z)
其中x,y,z描述空间中一个点的x,y,x坐标,V(x,y,z)表示  此时标量的值。

绘制数据
 我们的问题是如何使用mayavi绘制这些数据 - 我特别感兴趣 在绘制等值面时,可以使用contour3d命令实现。 网上的众多例子显示了contour3d绘制生成的数据 使用mgrid命令。 (还有使用ogrid命令的示例,但是  对我来说,mgrid更容易理解)。 策略:如果我们可以操纵我们的数据以获得相同的形状,并且从mgrid命令的输出中我们应该能够绘制它。 分析mgrid的输出,很明显所需的是3个三维的 用于存储x,y和z坐标的numpy数组,以及另一个三维numpy数组 在这些点存储标量值(上面的V)。以下程序 实现这些步骤。我认为该计划肯定可以改进: 我确信,例行程序fill_up_array可以被一个人用一行代替  知道python中的数组切片,并且可能还有其他地方 得到改善。我不禁想到,对于那些知道他们在numpy / mayavi做什么的人来说,整个事情可能会在1或2行中完成,但以下内容 我认为,程序易于理解且有效(你应该看到截断的球形 出现的图中的表面。) 将以下文件保存到“hope.py”并使用
运行   python hope.py

import numpy
from mayavi import mlab

def fill_up_array(output_arr,source_arr,nx,ny,nz,posn):
# takes a slice of results from source_arr and writes to output_arr
# there is probably an easy one liner to do this ?
#TODO: add checks to ensure input is sensible
    for i in range(nx):
        for j in range(ny):
            for k in range(nz):
                output_arr[i][j][k] = source_arr[i][j][k][posn]

# these numbers have to correspond to those used in gen-data.py
NX = 5 ; NY = 3 ; NZ = 3 

NDIM = 4  # number of columns in data file, 4 for current example


#initialise arrays:
# xx will contain x coordinate of data point
# yy will contain y coordinate of data point
# zz will contain z coordinate of data point
# VV will contain sample scalar value at (x,y,z)
xx = numpy.zeros((NX,NY,NZ))
yy = numpy.zeros((NX,NY,NZ))
zz = numpy.zeros((NX,NY,NZ))
VV =  numpy.zeros((NX,NY,NZ))


#now read in values from stream.out file to these arrays
full = numpy.loadtxt("stream.out")
fy = numpy.reshape(full, (NX,NY,NZ,NDIM))


fill_up_array(xx,fy,NX,NY,NZ,0)
fill_up_array(yy,fy,NX,NY,NZ,1)
fill_up_array(zz,fy,NX,NY,NZ,2)
fill_up_array(VV,fy,NX,NY,NZ,3)


#test plot
mlab.contour3d(xx, yy, zz, VV)
mlab.show()