ParaView Python によるポスト処理

2011年12月7日

はじめに

ParaView で Python を使ってポスト処理を行う方法。

バージョン

OpenFOAM 2.0.1, ParaView 3.10.1 (Python を有効にしてコンパイルしたもの)。

データの用意

icoFoam のチュートリアルデータ cavity を用意する。

$ cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity
$ cd cavity
$ blockMesh
$ icoFoam

スクリプトの実行

下記のスクリプトは、Python Shell で打ち込んでもよいし、次のようにスクリプトのファイルを作って ParaView 起動時に実行させてもよい。

$ paraview --script=contour.py

データの読み込み

reader = OpenFOAMReader(FileName='case.foam')
Show(reader)
Render()

ケースディレクトリ内で実行する。'case.foam' がなくてもデータは読み込まれる。

特徴線表示

reader = OpenFOAMReader(FileName='case.foam')
Show(reader)
Hide(reader)

es = ExtractSurface(reader)
Show(es)
Hide(es)

fe = FeatureEdges(es)
Show(fe)

Render()

コンター表示

reader = OpenFOAMReader(FileName='case.foam')
Show(reader)

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

Render()

dp = GetDisplayProperties(reader)
dp.ColorAttributeType = 'POINT_DATA'
dp.ColorArrayName = 'U'
r = reader.PointData['U'].GetRange()
dp.LookupTable = GetLookupTableForArray('U', 1,
		RGBPoints = [r[0], 0.23, 0.3, 0.754,
			r[1], 0.706, 0.016, 0.15],
		ColorSpace = 'Diverging')
dp.LookupTable.VectorMode = 'Magnitude'

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

Render()

まず、表示する時間を設定するために view.ViewTime に時間を設定し、一度 Render() を呼び出している。GetLookupTableForArray() の RGBPoints で値の範囲を r[0] から r[1] に設定している。ここでは U の Magnitude を表示しているが、成分を表示する場合は dp.LookupTable.VectorMode の部分を次のように書き換える。

dp.LookupTable.VectorMode = 'Component'
dp.LookupTable.VectorComponent = 0

VectorComponent の値は 0, 1, 2 でそれぞれ X, Y, Z 成分を表す。

view.ViewTime でデータの最終時間を指定している。つまり最後の結果が表示されることになる。

カラーバーの位置を調整するときは l.Position, サイズを調整するときは l.Position2 を設定する。

l.Position = [0.87, 0.25]
l.Position2 = [0.13, 0.5]

スライス

reader = OpenFOAMReader(FileName='case.foam')
Show(reader)
Hide(reader)

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

bounds = reader.GetDataInformation().GetBounds()
cx = (bounds[0] + bounds[1])/2.
cy = (bounds[2] + bounds[3])/2.
cz = (bounds[4] + bounds[5])/2.

s = Slice(reader)
s.SliceType.Origin = [cx, cy, cz]
s.SliceType.Normal = [0., 0., 1.]
Show(s)

dp = GetDisplayProperties(s)
dp.ColorAttributeType = 'POINT_DATA'
dp.ColorArrayName = 'U'
r = reader.PointData['U'].GetRange()
dp.LookupTable = GetLookupTableForArray('U', 1,
		RGBPoints = [r[0], 0.23, 0.3, 0.754,
			r[1], 0.706, 0.016, 0.15],
		ColorSpace = 'Diverging')
dp.LookupTable.VectorMode = 'Magnitude'

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

Render()

これでスライスは表示されるが、"Show Plane" をオフにする方法がわからなかった。そこで、つぎのように書き換えた。

pm = servermanager.ProxyManager()

reader = servermanager.sources.OpenFOAMReader(FileName='case.foam')
pm.RegisterProxy('sources', 'case.foam', reader)
Show(reader)
Hide(reader)

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

bounds = reader.GetDataInformation().GetBounds()
cx = (bounds[0] + bounds[1])/2.
cy = (bounds[2] + bounds[3])/2.
cz = (bounds[4] + bounds[5])/2.

s = servermanager.filters.Slice(Input=reader)
s.SliceType.Origin = [cx, cy, cz]
s.SliceType.Normal = [0., 0., 1.]
pm.RegisterProxy('sources', 'Slice1', s)
Show(s)

dp = GetDisplayProperties(s)
dp.ColorAttributeType = 'POINT_DATA'
dp.ColorArrayName = 'U'
r = reader.PointData['U'].GetRange()
dp.LookupTable = GetLookupTableForArray('U', 1,
		RGBPoints = [r[0], 0.23, 0.3, 0.754,
			r[1], 0.706, 0.016, 0.15],
		ColorSpace = 'Diverging')
dp.LookupTable.VectorMode = 'Magnitude'

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

Render()

スライスの部分で servermanager を使うようにした。GUI の操作を行わない限りスライスの平面は描画されない。

ベクトル

pm = servermanager.ProxyManager()

reader = servermanager.sources.OpenFOAMReader(FileName='case.foam')
pm.RegisterProxy('sources', 'case.foam', reader)
Show(reader)
Hide(reader)

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

bounds = reader.GetDataInformation().GetBounds()
cx = (bounds[0] + bounds[1])/2.
cy = (bounds[2] + bounds[3])/2.
cz = (bounds[4] + bounds[5])/2.

es = ExtractSurface(reader)
Show(es)
Hide(es)

fe = FeatureEdges(es)
Show(fe)

s = servermanager.filters.Slice(Input=reader)
s.SliceType.Origin = [cx, cy, cz]
s.SliceType.Normal = [0., 0., 1.]
pm.RegisterProxy('sources', 'Slice1', s)
Show(s)
Hide(s)

g = Glyph(Input=s, GlyphType='2D Glyph')
g.SetScaleFactor = 0.005
Show(g)

dp = GetDisplayProperties(g)
dp.ColorAttributeType = 'POINT_DATA'
dp.ColorArrayName = 'GlyphVector'
r = reader.PointData['U'].GetRange()
dp.LookupTable = GetLookupTableForArray('U', 1,
		RGBPoints = [r[0], 0.23, 0.3, 0.754,
			r[1], 0.706, 0.016, 0.15],
		ColorSpace = 'Diverging')
dp.LookupTable.VectorMode = 'Magnitude'

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

Render()

テキスト

t = Text()
t.Text = 'Test'
Show(t)

Render()

テキストの位置の設定は、つぎのようにする。

tp = GetDisplayProperties(t)
tp.Position = [0.05, 0.9]

Render()

tp.Position でテキストの位置を指定する。[0, 0] が左下隅である。また、つぎのような指定の仕方もある。

tp.WindowLocation = 'LowerLeftCorner'

'LowerLeftCorner' や 'UpperRightCorner', 'LowerCenter' などで位置を指定できる。

時刻の表示には AnnotateTime を使う。

at = AnnotateTime()
Show(at)

Render()

at.Format で表示のフォーマットを指定できる。

at.Format = 'Time: %.0f s'

Render()

画像ファイルの出力

画像ファイルを書き出すには次のようにする。

WriteImage('U.png')

画像サイズを変更するにはビューのサイズを変更する。

view = GetActiveView()
size0 = view.ViewSize
view.ViewSize = [1024, 768]
WriteImage('U.png')
view.ViewSize = size0

次のような関数を定義しておくと便利だろう。

def writeImage(filename, size):
	view = GetActiveView()
	size0 = view.ViewSize
	view.ViewSize = size
	WriteImage(filename)
	view.ViewSize = size0

次のように使う。

writeImage('U.png')

ポスト処理の自動化

たとえば、あるディレクトリにケースディレクトリがいくつか入っているとする。それぞれのケースに対して同じ出力を行いたい。ここでは最終結果の速度分布と圧力分布を出力するとしよう。すべて同じ Python スクリプトで出力できるものとする。まず、スクリプト post.py を用意する。

post.py

def writeImage(filename, size):
	view = GetActiveView()
	size0 = view.ViewSize
	view.ViewSize = size
	WriteImage(filename)
	view.ViewSize = size0


reader = OpenFOAMReader(FileName='case.foam')
Show(reader)

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

Render()


dp = GetDisplayProperties(reader)
dp.ColorAttributeType = 'POINT_DATA'
dp.ColorArrayName = 'U'
r = reader.PointData['U'].GetRange()
dp.LookupTable = GetLookupTableForArray('U', 1,
		RGBPoints = [r[0], 0.23, 0.3, 0.754,
			r[1], 0.706, 0.016, 0.15],
		ColorSpace = 'Diverging')
dp.LookupTable.VectorMode = 'Magnitude'

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

Render()

writeImage('U.png', [1024, 768])


dp.ColorArrayName = 'p'
r = reader.PointData['p'].GetRange()
dp.LookupTable = GetLookupTableForArray('p', 1,
		RGBPoints = [r[0], 0.23, 0.3, 0.754,
			r[1], 0.706, 0.016, 0.15],
		ColorSpace = 'Diverging')

l.LookupTable = dp.LookupTable
l.Title = 'p'
l.TitleFontSize = 12
l.LabelFontSize = 10
l.AutomaticLabelFormat = 0
l.LabelFormat = '%10.3e'
view.Representations.append(l)

Render()

writeImage('p.png', [1024, 768])

exit()

これをディレクトリのトップに置いておく。そして次のようなシェルスクリプトを用意する。

run-post

#!/bin/sh

for CASE in * ; do
	if [ -d $CASE ] ; then
		echo $CASE
		cd $CASE
		cp ../post.py .
		paraview --script=post.py
		cd ..
	fi
done

これはディレクトリ内にあるディレクトリすべてをケースディレクトリとみなして巡回し、それぞれのケースで post.py をコピーして ParaView を実行している。実行は次のようにする。

$ chmod +x run-post
$ ./run-post

すべてのケースディレクトリにそれぞれの U.png と p.png が出力される。