2013-11-01 184 views
4

目前很容易用python和matplotlib生成2D流图,因为streamplot最近由Tom Flannaghan和Tony Yu合并到matplotlib中。使用python和mayavi创建3D流图

尽管可以使用matplotlib生成某些类型的3D图,但3D流图当前不受支持。然而,Python绘图程序mayavi(它提供了基于vtk的绘图的python界面)能够使用其flow()函数进行3D流图。

我已经创建了一个简单的python模块来绘制3D数据集中没有Z-slope(全部为dZ = 0)的2D和3D流图数据,以演示我面临的与mayavi和matplotlib的绘图挑战有效地匹配xy平面中的数据。注释的代码和所得曲线如下所示:

import numpy, matplotlib, mayavi, matplotlib.pyplot, mayavi.mlab 
#for now, let's produce artificial streamline data sets for 2D & 3D cases where x and y change by +1 at each point, while Z changes by 0 at each point: 

#2D data first: 
x = numpy.ones((10,10)) 
y = numpy.ones((10,10)) 
#and a corresponding meshgrid: 
Y,X = numpy.mgrid[-10:10:10j,-10:10:10j] 

#now 3D data with Z = 0 (i.e., I want to be able to produce a matching streamplot plane in mayavi, which is normally used for 3D): 
xx = numpy.ones((10,10,10)) 
yy = numpy.ones((10,10,10)) 
zz = numpy.zeros((10,10,10)) 
#and a corresponding meshgrid: 
ZZ,YY,XX = numpy.mgrid[-10:10:10j,-10:10:10j,-10:10:10j] 

#plot the 2D streamplot data with matplotlib: 
fig = matplotlib.pyplot.figure() 
ax = fig.add_subplot(111,aspect='equal') 
speed = numpy.sqrt(x*x + y*y) 
ax.streamplot(X, Y, x, y, color=x, linewidth=2, cmap=matplotlib.pyplot.cm.autumn,arrowsize=3) 
fig.savefig('test_streamplot_2D.png',dpi=300) 

#there's no streamplot 3D available in matplotlib, so try to see how mayavi behaves with a similar 3D data set: 
fig = mayavi.mlab.figure(bgcolor=(1.0,1.0,1.0),size=(800,800),fgcolor=(0, 0, 0)) 
st = mayavi.mlab.flow(XX,YY,ZZ,xx,yy,zz,line_width=4,seedtype='sphere',integration_direction='forward') #sphere is the default seed type 
mayavi.mlab.axes(extent = [-10.0,10.0,-10.0,10.0,-1.0,1.0]) #set plot bounds 
fig.scene.z_plus_view() #adjust the view for a perspective along z (xy plane flat) 
mayavi.mlab.savefig('test_streamplot_3D_attempt_1.png') 

#now start to modify the mayavi code to see if I can 'seed in' more streamlines (default only produces a single short streamline, albeit of the correct slope) 
#attempt 2 uses a line seed/widget over the specified bounds (points 1 and 2): 
fig = mayavi.mlab.figure(bgcolor=(1.0,1.0,1.0),size=(800,800),fgcolor=(0, 0, 0)) 
st = mayavi.mlab.flow(XX,YY,ZZ,xx,yy,zz,line_width=4,seedtype='line',integration_direction='forward') #line instead of sphere 
st.seed.widget.point1 = [0,-10,0] 
st.seed.widget.point2 = [0,10,0] #so seed line should go up along y axis 
st.seed.widget.resolution = 25 #seems to be the number of seeds points along the seed line 
mayavi.mlab.axes(extent = [-10.0,10.0,-10.0,10.0,-1.0,1.0]) #set plot bounds 
fig.scene.z_plus_view() #adjust the view for a perspective along z (xy plane flat) 
mayavi.mlab.savefig('test_streamplot_3D_attempt_2.png') 

#attempt 3 will try to seed a diagonal line across the plot to produce streamlines that cover the full plot: 
#would need to use 'both' for integration_direction if I could get the diagonal seed line to work 
fig = mayavi.mlab.figure(bgcolor=(1.0,1.0,1.0),size=(800,800),fgcolor=(0, 0, 0)) 
st = mayavi.mlab.flow(XX,YY,ZZ,xx,yy,zz,line_width=4,seedtype='line',integration_direction='forward') 
st.seed.widget.point1 = [-10,10,0] #start seed line at top left corner of plot 
st.seed.widget.point2 = [10,-10,0] #end seed line at bottom right corner of plot 
#this fails to produce a diagonal seed line though 
st.seed.widget.resolution = 25 #seems to be the number of seeds points along the seed line 
mayavi.mlab.axes(extent = [-10.0,10.0,-10.0,10.0,-1.0,1.0]) #set plot bounds 
fig.scene.z_plus_view() #adjust the view for a perspective along z (xy plane flat) 
mayavi.mlab.savefig('test_streamplot_3D_attempt_3.png') 

2D matplotlib结果(音符斜率1匹配的流线明显地与填充有统一的值dx和dy阵列全部): 2D matplotlib streamplot 3D编写Mayavi结果(尝试1; 注意,本这里的单流线的斜率是正确的,但流线的长度和数量显然是从2D matplotlib示例相当不同): enter image description here 3D Mayavi的结果(尝试2; 音符那我使用一个具有足够高分辨率的在线种子产生了许多更合适斜率的流线,但也要注意,代码中指定的黑色种子线的末端x坐标与图)不匹配 enter image description here 最后尝试尽管指定了不同的种子/小部件点,#3(令人困惑地)产生了与#2完全相同的图。 所以,问题是:我怎样才能更好地控制我的种子线的位置,使其成为对角线?更广泛地说,我希望能够提供任意数量的种子点,用于更一般的流图3D(非平面)问题,但是解决前面的具体情况应该让我开始。

其他一些有用的资源,我发现这个问题,这并没有完全解决我的问题,工作时:在话题

  • example其中一个自定义

    1. matplotlib streamplot合着者汤姆Flannaghan的blog post种子数组与mayavi Streamline的子类一起使用(它依次由flow()使用),但不幸的是,实现细节不足以重现。
    2. 使用mayavi生成2D streamplots of magnetic field lines的示例(包括注释源代码)。
    3. Similar examples with source in 3D,但仍不足以解决我的问题策划:
    4. 流量()Mayavi的标准文档中提供plot resulting from the example code(球形种子插件的流线后面可见)。
  • 回答

    5

    看来问题在于流线种子控件的clamp_to_bounds属性的默认值设置为True。您必须将其设置为False才能移动小部件。

    st.seed.widget.clamp_to_bounds = False 
    

    添加此的代码后,最后的结果是这样的:

    Final result

    你可能很熟悉,从之前探索Mayavi的这种方法,但解释过的可能性不管怎么说,我会提到这个:

    我发现这个选项的方式,以及我通常在Mayavi中如何找到这样晦涩的属性,是通过启用启用pylab的IPython脚本。在Ubuntu上,终端命令如下:

    ipython --pylab=qt 
    

    启动的IPython后,我使用%跑法宝命令运行脚本:

    %run streamlines.py 
    

    情节作出后,我现在有机会到Mayavi的窗口,可以通过点击图标Mayavi的看到Mayavi的管道的内部:

    enter image description here

    在管道工程中,你会发现Streamline对象,如果你点击它然后选择Seed,你会发现“Clamp to bounds”复选框。 (很抱歉的截图颜色不好混 - Mayavi的已经因某种原因开始最近使用的是深色的主题...)

    enter image description here

    要查看这实际上呢,你可以按下录音键enter image description here得到打开一个窗口,显示你的代码相当于您在更改设置:

    enter image description here

    在那里你看到clamp_to_bounds属性,就可以将其添加到您的脚本。

    与流线祝你好运!