2013-11-01 186 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屬性,就可以將其添加到您的腳本。

    與流線祝你好運!