PyQt5とvtkを使ってOpenFOAMの結果を可視化してみた

#はじめに
pyqt5上でOpenFOAMの計算結果をvtkで表示する方法を簡単にまとめます。
ほぼ、私向けの備忘録となってます。 
#環境
OS: windows7
OpenFOAM v4.0
python 3.6.4
pyqt5-5.9.2
vtk-8.0.0
numpy

#ファイル構成
case/
　├ pyvtk.py　(本プログラム)
　└ pitzDaily
　　　　├ 0 (中身はp,Uなど)
　　　　├ constant
　　　　├ system
　　　　├ 100 (以下フォルダ0と同様)
　　　　├ 200
　　　　├ 300
　　　　├ 400
　　　　└ 406
↓github
https://github.com/matsubaraDaisuke/my_qiita/tree/master/pyvtk

#簡単な説明
 vtkライブラリには「vtkOpenFOAMReader」クラスが標準で実装されており、簡単にOpenFOAMの結果を読み込むことができる。
VTKの使い方の流れは、以下の様な流れで使用する。
Reader→Filter→Mapper→Actor→Renderer→Window
詳しくはVTK勉強会資料が役につ(↓pdfの表示)
http://www.simulation-studies.org/wp-content/uploads/2014/01/vtk_semi_comp.pdf

##vtkを使ったOpenFOAMの結果の読み込み

```py3
#!/usr/bin/env python

# -*- coding: utf-8 -*-
import os
import vtk as vtk
import numpy as np
from vtk.util.numpy_support import vtk_to_numpy

rootDir = "pitzDaily"
fileName = rootDir + "/system/controlDict"

# reader
reader = vtk.vtkOpenFOAMReader()
reader.SetFileName(fileName)
reader.CreateCellToPointOn()
reader.DecomposePolyhedraOn()
reader.EnableAllCellArrays()
reader.Update()

tArray =vtk_to_numpy(reader.GetTimeValues())    #出力ファイルの時間を格納
print(tArray)                                   #output-> [   0.  100.  200.  300.  400.  406.]
reader.UpdateTimeStep(tArray[-1])               #最新の時間406を出力設定
reader.Update()

filter = vtk.vtkGeometryFilter()
filter.SetInputConnection(reader.GetOutputPort()) #filterにreaderを設定


# mapper
mapper = vtk.vtkCompositePolyDataMapper2()
mapper.SetInputConnection(filter.GetOutputPort()) #mapperにfilterを設定
##スカラー値の設定
mapper.SetScalarModeToUseCellFieldData() #scalarデータ用に設定
mapper.SelectColorArray("p")             #圧力を表示する
mapper.SetScalarRange(-10,50)            #圧力を[-10,50]の範囲で表示

# actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)             #actorにmapperを設定

# renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)            #rendererにactorを設定

##背景色の設定
renderer.GradientBackgroundOn()      #グラデーション背景を設定
renderer.SetBackground2(0.2,0.4,0.6) #上面の色
renderer.SetBackground(1,1,1)        #下面の色

#Window
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(renderer)         #Windowにrendererを設定

iren = vtk.vtkRenderWindowInteractor();
iren.SetRenderWindow(renWin);

renWin.SetSize(850, 850)
renWin.Render()
iren.Start();

```
##結果
拡大や回転もできる。
![result.png](https://qiita-image-store.s3.amazonaws.com/0/132299/b54cb58c-b005-8eb5-dd33-055f69bd8710.png)


##pyqt5とvtkを使ったOpenFOAMの結果の読み込み

```py3
#!/usr/bin/env python

# -*- coding: utf-8 -*-
import sys
import os
import vtk as vtk
import numpy as np
from vtk.util.numpy_support import vtk_to_numpy

from PyQt5 import QtCore, QtGui
from PyQt5 import Qt
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

class MainWindow(Qt.QMainWindow):
    
    def __init__(self, parent = None):
        Qt.QMainWindow.__init__(self, parent)
        
        #Qtの枠の設定
        #########追加
        self.setWindowTitle('QtSample')
        
        self.frame = Qt.QFrame()
        self.vl = Qt.QVBoxLayout()
        self.iren = QVTKRenderWindowInteractor(self.frame)
        self.vl.addWidget(self.iren)
        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)
    
        #########window以外は一緒
        self.rootDir = "pitzDaily"
        self.fileName = self.rootDir + "/system/controlDict"

        # reader
        self.reader = vtk.vtkOpenFOAMReader()
        self.reader.SetFileName(self.fileName)
        self.reader.CreateCellToPointOn()
        self.reader.DecomposePolyhedraOn()
        self.reader.EnableAllCellArrays()
        self.reader.Update()

        tArray =vtk_to_numpy(self.reader.GetTimeValues())    #出力ファイルの時間を格納
        print(tArray)                                   #output-> [   0.  100.  200.  300.  400.  406.]
        self.reader.UpdateTimeStep(tArray[-1])               #最新の時間406を出力設定
        self.reader.Update()

        self.filter = vtk.vtkGeometryFilter()
        self.filter.SetInputConnection(self.reader.GetOutputPort()) #filterにreaderを設定


        # mapper
        self.mapper = vtk.vtkCompositePolyDataMapper2()
        self.mapper.SetInputConnection(self.filter.GetOutputPort()) #mapperにfilterを設定
        ##スカラー値の設定
        self.mapper.SetScalarModeToUseCellFieldData() #scalarデータ用に設定
        self.mapper.SelectColorArray("p")             #圧力を表示する
        self.mapper.SetScalarRange(-10,50)            #圧力を[-10,50]の範囲で表示

        # actor
        self.actor = vtk.vtkActor()
        self.actor.SetMapper(self.mapper)             #actorにmapperを設定

        # renderer
        self.renderer = vtk.vtkRenderer()
        self.renderer.AddActor(self.actor)            #rendererにactorを設定

        ##背景色の設定
        self.renderer.GradientBackgroundOn()      #グラデーション背景を設定
        self.renderer.SetBackground2(0.2,0.4,0.6) #上面の色
        self.renderer.SetBackground(1,1,1)        #下面の色

        #Window
        #########追加
        self.iren.GetRenderWindow().AddRenderer(self.renderer)
        self.iren.SetSize(850, 850)
        self.iren.Initialize()
        self.iren.Start();
        self.show()



if __name__ == "__main__":
    app = Qt.QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

```
##結果
枠のタイトルがPyQtのQtSampleとなっていることがわかる。
![result.png](https://qiita-image-store.s3.amazonaws.com/0/132299/fe12492a-bb02-4abb-7407-9a29645d8b25.png)

##リンク
続編
[PyQt5とvtkを使ってOpenFOAMの結果を可視化してみた その2(「ファイルを開く」の実装編) ](https://qiita.com/matsubaradaisuke/items/956b9ade4a74fcbb7521 "PyQt5とvtkを使ってOpenFOAMの結果を可視化してみた その2(「ファイルを開く」の実装編) ")

#不具合
macOS High Sierra v10.13.2で動作確認をしたところ以下のような不具合が発生した。枠全体に表示されずに、左下に小さく表示されてしまう。

<img width="610" alt="スクリーンショット 2018-01-22 21.21.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/132299/0cb15b5a-1e22-7549-2cd2-36d6b73ffb21.png">