Python による ParaView の操作

2011年3月2日

はじめに

ParaView で Python を使ってみる。

バージョン

ParaView 3.8.1 Windows 版/3.8.0 Linux 版

ファイル

例として以下のファイルを使用する。

contour.vtk.zip

展開して使ってください。

Python Shell の起動

ParaView に Python が組み込まれているなら、メニューの [Tools]-[Python Shell] で Python Shell が立ち上がる。自動的に ParaView 操作用のモジュールがインポートされる。

VTK ファイルの読み込み

Windows 版の場合、作業フォルダに ParaView のアイコンをコピーし、右クリック、[プロパティ] の [ショートカット] タブの作業フォルダのパスを削除すれば、ParaView を起動したとき、作業フォルダがカレントになる。そうして起動したとして、作業フォルダにある VTK ファイルを次のように読み込む。

>>> reader = LegacyVTKReader(FileNames="contour.vtk")

Pipeline Browser に項目が追加されるはずである。これを可視にする。

>>> Show(reader)

そして描画させる。

>>> Render()

ちなみに、次のようにすれば不可視になる。

>>> Hide(reader)

フィルタの使用

フィルタの使用例として、Delaunay2D を使う。以下のようにする。

>>> d = Delaunay2D(reader)
>>> Show(d)
>>> Hide(reader)
>>> Render()

図形が一部欠けるので、Offset の設定を変えたい。さて、どうやってやるものか、dir() 関数でちょっと調べてみる。

>>> dir(d)
['Alpha', 'BoundingTriangulation', 'CellData', 'FileNameChanged', 'GetCellDataInformation',
'GetDataInformation', 'GetPointDataInformation', 'GetProperty', 'GetPropertyValue', 'Initialize',
'InitializeFromProxy', 'Input', 'ListProperties', 'Observed', 'ObserverTag', 'Offset', 'PointData',
...

文字がいっぱい出てきて、その中に 'Offset' の文字を発見。これかしら…とりあえず見てみる。

>>> d.Offset
1.0

たぶんこれだろうということで、値を入れてみる。

>>> d.Offset = 1.5

設定が変わる。Render() で描画させると、欠けがなくなる。

実は、dir() の代わりに ListProperties() を使えば、プロパティのリストを得ることができる。

>>> d.ListProperties()
['Alpha', 'BoundingTriangulation', 'Input', 'Offset', 'ProjectionPlaneMode', 'Tolerance']

また、help() で詳しい情報を得ることもできる。

>>> help(d)

表示スタイルの変更

"Outline" や "Surface" などといった表示スタイルは、以下のように変更する。

>>> dp = GetDisplayProperties(d)
>>> dp.Representation = 'Outline'
>>> dp.Representation = 'Surface'
>>> dp.Representation = 'Surface With Edges'

データの確認

スカラー値などのデータをコンター表示させたいが、その前に、どういうデータがあるのかを確認する。

>>> reader.CellData[:]
[]
>>> reader.PointData[:]
[Array: point_scalars]

"point_scalars" という名前の点データがあるのがわかる。以下のようにすると、データの範囲を取得できる。

>>> reader.PointData['point_scalars'].GetRange()
(-0.21710202097892761, 1.0)

もしデータがベクトルであれば、"GetRange(component = 0)" などと component に値 0, 1, 2 を指定して各成分の範囲を得ることができる。

次のようにすると、データの幾何学的な範囲を得ることができる。

>>> reader.GetDataInformation().GetBounds()
(-12.0, 12.0, -12.0, 12.0, 0.0, 0.0)

コンターの表示

点データのコンターを表示させる。以下のようにする。

>>> dp.ColorAttributeType = 'POINT_DATA'
>>> dp.ColorArrayName = 'point_scalars'
>>> r = reader.PointData['point_scalars'].GetRange()
>>> dp.LookupTable = MakeBlueToRedLT(r[0], r[1])
>>> Render()

LookupTable というのは、色のテーブルのことで、ここでは色の最大値・最小値とデータの最大値・最小値を一致させている。色の設定は、次のように確認できる。

>>> dp.LookupTable.RGBPoints
[-0.21710202097892761, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0]

値はスカラーの値, R, G, B, ... と並んでいる。上はスカラー値の最小値に青、最大値に赤が設定されていることを意味している。色が気に入らなければ、色を直接指定してテーブルを作ることもできる。

>>> dp.LookupTable = GetLookupTableForArray('Point Scalars', 1,
... RGBPoints = [r[0], 0.23, 0.3, 0.754,
... r[1], 0.706, 0.016, 0.15],
... ColorSpace = 'Diverging')
>>> Render()

カラーバーの表示

カラーバーの表示は以下のようにする。

>>> l = servermanager.rendering.ScalarBarWidgetRepresentation()
>>> l.LookupTable = dp.LookupTable
>>> l.Title = 'point_scalars'
>>> l.TitleFontSize = 12
>>> l.LabelFontSize = 10
>>> l.AutomaticLabelFormat = 0
>>> l.LabelFormat = '%10.3e'
>>> view = GetActiveView()
>>> view.Representations.append(l)

表示・非表示を切り替えるには、次のようにする。

>>> l.Visibility = 0
>>> Render()
>>> l.Visibility = 1
>>> Render()

カメラの操作

カメラを操作してみる。その前に、ペッタンコのものを見ても面白くないので、WarpByScalar を使う。

>>> Hide(d)
>>> w = WarpByScalar(d)
>>> Show(w)
>>> w.ScaleFactor = 3
>>> dp = GetDisplayProperties(w)
>>> dp.ColorAttributeType = 'POINT_DATA'
>>> dp.ColorArrayName = 'point_scalars'
>>> dp.LookupTable = MakeBlueToRedLT(r[0], r[1])
>>> Render()

カメラを取得する。

>>> camera = GetActiveCamera()

ズーム。

>>> camera.Zoom(2)
>>> Render()
>>> camera.Zoom(0.5)
>>> Render()

回転。

>>> camera.Roll(45)
>>> Render()
>>> camera.Elevation(-45)
>>> Render()
>>> camera.Azimuth(45)
>>> Render()

首振り。

>>> camera.Pitch(4)
>>> Render()
>>> camera.Yaw(4)
>>> Render()

カメラの位置と焦点の位置の設定。

>>> p = camera.GetPosition()
>>> camera.SetPosition((p[0]+4, p[1], p[2]))
>>> fp = camera.GetFocalPoint()
>>> camera.SetFocalPoint((fp[0]+4, fp[1], fp[2]))
>>> Render()

透視射影と正射影を切り替えることもできる。

>>> camera.ParallelProjectionOn()
>>> Render()
>>> camera.ParallelProjectionOff()
>>> Render()

全体を表示させるには、カメラをリセットする。

>>> ResetCamera()

画像の出力

画像を出力させるには、次のようにする。

>>> WriteImage('contour.png')

画像のフォーマットは拡張子で判断される。

スクリプト

Python Shell の Run Script を使えば、スクリプトを読み込んで実行させることができる。以下は、スクリプトの例である。

reader = LegacyVTKReader(FileNames='contour.vtk')
Show(reader)
Hide(reader)

d = Delaunay2D(reader)
d.Offset = 1.5
Show(d)
Hide(d)

w = WarpByScalar(d)
w.ScaleFactor = 3
Show(w)

dp = GetDisplayProperties(w)
dp.ColorAttributeType = 'POINT_DATA'
dp.ColorArrayName = 'point_scalars'
r = reader.PointData['point_scalars'].GetRange()
dp.LookupTable = MakeBlueToRedLT(r[0], r[1])

l = servermanager.rendering.ScalarBarWidgetRepresentation()
l.LookupTable = dp.LookupTable
l.Title = 'point_scalars'
l.TitleFontSize = 12
l.LabelFontSize = 10
l.AutomaticLabelFormat = 0
l.LabelFormat = '%10.3e'
view = GetActiveView()
view.Representations.append(l)

camera = GetActiveCamera()
camera.Elevation(-60)

Render()

WriteImage('contour.png')

これをファイル contour.py として保存し、Run Script で実行すると、次のような絵ができる。

ParaView 起動直後に Python スクリプトを実行させたい場合は、コマンドラインで次のように指定する。

$ paraview --script=contour.py

ParaView の終了

スクリプト指定で ParaView を実行して、そのまま終了させたいときは、つぎのコマンドを使う。

quit()

時刻の指定

時系列データの場合は、次のようにして時刻を指定できる。

view = GetActiveView()
view.ViewTime = 0.5

reader.TimestepValues で時刻のリストが得られるので、最終時刻を指定するには次のようにすればよい。

latestTime = max(reader.TimestepValues)
view = GetActiveView()
view.ViewTime = latestTime

Proxy Manager を使う

上で見た LegacyVTKReader() や WarpByScalar() の結果は、実行後すぐに ParaView の Pipeline Browser に表示される。代わりに Pipeline Browser への登録まで含めた下位の操作も可能である。

たとえば、ソースとして Sphere (球) を追加して表示する処理は次のように書ける。

s = Sphere()
Show(s)
Render()

これは次のように書き直すことができる。

pm = servermanager.ProxyManager()
s = servermanager.sources.Sphere()
pm.RegisterProxy("sources", "Sphere1", s)
Show(s)
Render()

Sphere() の代わりに servermanager.sources.Sphere() を使っている。この場合は、ProxManager のオブジェクトに RegisterProxy() で登録した時点で Sphere オブジェクトが Pipeline Browser に表示される。

"Sphere()" → "servermanager.sources.Sphere()" だったので、フィルタの場合は "servermanager.filters" を使えばよい。たとえばクリップを使う場合は次のようにする。

c = servermanager.filters.Clip(Input = s)
pm.RegisterProxy("sources", "Clip1", c)
Show(c)
Hide(s)
Render()