2013-11-01 2 views
4

streamplot이 Tom Flannaghan 및 Tony Yu가 최근 matplotlib에 통합했기 때문에 파이썬 및 matplotlib를 사용하여 2D 스트림 플롯을 제작하는 것은 현재 매우 쉽습니다.python 및 mayavi를 사용하여 3D 스트림 플롯 만들기

matplotlib을 사용하여 특정 유형의 3D 플롯을 생성 할 수도 있지만 3D 스트림 플롯은 현재 지원되지 않습니다. 그러나 파이썬 플로팅 프로그램 인 mayavi (vtk 기반 플로팅에 대한 파이썬 인터페이스 제공)는 flow() 함수를 사용하여 3D 스트림 플롯을 처리 할 수 ​​있습니다.

저는 3D 데이터 세트에서 Z 기울기 (모든 dZ = 0)없이 2D 및 3D로 데이터를 streamplot하기 위해 간단한 파이썬 모듈을 생성하여 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') 

차원하기 matplotlib 결과 (주에 띌 연합의 값 가득 DX와 DY 배열 모두에 경사 1 일치의 유선) : 2D matplotlib streamplot 차원 mayavi 결과 (시도 1 여기에 존재하는 단일 유선형의 기울기가 정확하지만 유선의 길이와 숫자가 분명히 2D하기 matplotlib 예를 상당히 다르다는 것을 주) : enter image description here 차원 mayavi 결과 (시도 2; 노트 내 사용을 충분히 높은 해상도를 가진 라인 시드는 더 많은 적절한 기울기의 유선형을 만들었지 만 코드에 지정된 검은 시드 선의 시작 & 끝 x 좌표가 플롯과 일치하지 않음을 유의하십시오. enter image description here 마지막으로 # 3 (혼란스럽게도) 다른 시드/위젯 포인트를 지정 했음에도 불구하고 # 2와 똑같은 플롯을 생성합니다. 질문 : 그렇다면 시드 선의 위치를 ​​대각선으로 제어하려면 어떻게해야합니까? 더 광범위하게 말하면, 좀 더 일반적인 스트림 플롯 3D (비평면) 문제에 대해 시드 포인트의 임의의 배열을 공급할 수 있기를 원하지만, 이전 특정 사례를 해결하면 라인을 시작해야합니다.

  1. 하기 matplotlib의 streamplot 공동 저자 톰 Flannaghan의 blog post 주제
  2. example 사용자 정의를에 : 확실히 내 문제가 해결되지 않은이 문제에서 작업하는 동안

    일부 기타 유용한 리소스 내가 발견 씨앗의 배열은 mayavi Streamline의 서브 클래스와 함께 사용됩니다 (차례 차례로 flow()에 의해 사용됩니다). 불행하게도, 재생산하기에 불충분 한 구현 세부 사항이 있습니다.

  3. mayavi를 사용하여 2D streamplots of magnetic field lines을 생성하는 예제 (주석 처리 된 소스 코드 포함).
  4. 흐름() plot resulting from the example code합니다 (유선 뒤에 표시 구형 씨 위젯)을 mayavi 표준 문서에서 제공 : 내 음모를 꾸미고 문제를 해결하기 위해 여전히
  5. Similar examples with source in 3D
  6. 하지만 충분하지 않습니다.

답변

5

유선 시드 위젯의 clamp_to_bounds 속성의 기본값이 True로 설정되는 것이 문제 인 것 같습니다. 실제로 위젯을 이동하려면이 값을 False로 설정해야합니다.

st.seed.widget.clamp_to_bounds = False 

코드에 이것을 추가 한 후, 최종 결과는 다음과 같습니다

Final result

당신은하지만 너무 설명의 가능성, 앞에서 Mayavi을 탐구하는이 방법을 잘 알고있을 수 있습니다 많이 언급 하겠지만

Mayavi에서 이처럼 모호한 속성을 발견하는 방법은 pylab을 사용하는 IPython 용 스크립트를 시작하는 것입니다. 우분투에서 터미널 명령은 다음과 같습니다, 지금 액세스 할 수있는 플롯이 이루어진 후

%run streamlines.py 

:

ipython --pylab=qt 

IPython를 실행 한 후, 나는 % 실행 마법 명령을 사용하여 스크립트를 실행 Mayavi 창 및 Mayavi 아이콘을 클릭하여 Mayavi 파이프 라인의 내부를 볼 수 있습니다 : 당신이 찾을 수있는 파이프 라인에서

enter image description here

을 Streamline 개체를 클릭하고 Seed를 선택하면 "Clamp to bounds"체크 상자가 나타납니다. 이 실제로 무엇을하는지 확인하려면

enter image description here

을 - (스크린 샷의 색상 나쁜 혼합 죄송 Mayavi 어떤 이유로 ... 최근 어두운 테마를 사용하기 시작했다), 당신은 레코드 버튼을 누르면 수

enter image description here

당신이 clamp_to_bounds 속성을 참조하고 스크립트에 추가 할 수 있습니다 : enter image description here 당신에게 설정을 변경 당신의 코드에 상응를 표시하는 창을 엽니 다 얻을 수 있습니다.

유선형과 행운!