Python

VTK 8.2.0をWindowsでビルドしてPythonから使う方法

3D CGや画像処理、可視化のためのライブラリVTKをWindows上でビルドしてPython 3で利用するまでの方法を紹介します。

なお、VTKは、OpenCVのようなライブラリから利用するように設定したり、C++から直接使用することも可能です。

VTK 8.2.0のビルド環境

VTK 8.2.0をWindows上でビルドするために、以下の環境を利用しました。これらのソフトウェアをインストールしていない場合は、それぞれリンク先のURLからアプリケーションをダウンロードしてインストールを行ってください。

 

CMakeやPythonのバージョンが少し違っても、おそらくVTKは問題無く動作すると思われます。以下のビルド時に使用するPythonのバージョンを指定する部分があるので、その設定を変えればPython 2系でも動作するはずです。

VTK 8.2.0のビルドとインストール

今回は、以下のフォルダを利用してビルドとインストールを行います。違うフォルダを利用する場合は適宜読み替えてください。

ビルドに利用するフォルダ C:\build\VTK-8.2.0
VTKのインストール先 C:\lib\VTK

VTK 8.2.0ソースコードのダウンロードと展開

VTKのダウンロードサイトから、VTK 8.2.0(VTK-8.2.0.zip)をダウンロードして、C:\buildフォルダに展開します。

VTK-8.2.0.zipにはVTK-8.2.0というフォルダが含まれているので、C:\build\VTK-8.2.0というフォルダが作成され、その配下にソースコードが展開されるようになります。

CMakeでビルド設定

CMakeを起動し、Where is the source codeC:/build/VTK-8.2.0Where to build the binariesC:/build/VTK-8.2.0/buildフォルダを指定します。

フォルダの指定が完了したらConfigureボタンをクリックします。

CMakeの設定

 

利用するビルド環境の選択画面が表示されるので、ビルドに利用する環境(今回はVisual Studio 2017の64ビット版)を選択してFinishボタンをクリックします。
なお、少し古いバージョンのCMakeを利用している場合はx64の選択項目が分かれておらず「Visual Studio 2017 x64」のような形で選択するようになっています。

コンパイラの設定

 

設定を変更してConfigureボタンをクリック…という操作を何度か繰り返しながら、今回は以下のような設定にしました。

CMakeを利用する時は「設定を変更→Configure」という操作を何度か繰り返しながらビルド設定を行っていきます。

選択した内容によって、新しい項目が表示される場合もあるので、赤い設定項目が消えてエラーが無くなるまで「設定を変更→Configure」という操作を繰り返します。

 

ビルド時に複数CPUが利用されるようにCMAKE_CXX_MP_FLAGを有効にしてCMAKE_CXX_MP_NUM_PROCESSORSに8を指定しています。
今回はPython 3.6.8で利用するため、VTK_WRAP_PYTHONにチェックを入れ、VTK_PYTHON_VERSIONに3.6を指定します。この値は利用するPythonのバージョンに合わせて設定を変更してください。
デフォルトのインストール先(CMAKE_INSTALL_PREFIX)はC:\Program Files\~となっていますが、この場所はインストールに管理者権限が必要になり少し面倒(とは言ってもVisual Studioを管理者モードで起動すれば良いだけ)なので、C:/lib/VTK(区切り文字はスラッシュ)に変更しています。

設定が完了したら、Generateボタンを押してVisual Studio 2017のソリューションファイルを作成し、Open Projectボタンでソリューションファイルを開きます。(ソリューションファイルは、C:\build\VTK-8.2.0\build\VTK.slnに作成されているので、このファイルを直接Visual Studioで開いてもかまいません)

VTKの設定

VTK 8.2.0のビルドとインストール

Visual Studio 2017のメニューから、ビルド(B)>バッチビルド(T)を選択して、以下のINSTALL Release x64にチェックを入れてリビルドボタンをクリックします。

これで、必要なパッケージのビルドが行われ、設定時に指定したC:\lib\VTKフォルダに必要なファイルがインストールされます。

Visual Studioのバッチビルド

インストール後のフォルダ構成は次のようになります。(細かいサブフォルダは省略)

C:\LIB\VTK
├bin
│└Lib
│  └site-packages
│    └vtkmodules
├include
│└vtk-8.2
├lib
│└cmake
└share
  └doc

 

VTK 8.2.0を利用するためのPATH設定

インストールしたVTK 8.2.0を利用するために、環境変数PATHC:\lib\VTK\binを追加します。

PATHの設定後、VTKのファイルが参照できるかどうかはコマンドプロンプトからwhere vtk*とすれば確認できます。もしPATH設定を間違っている(もしくはビルドやインストールで失敗している)場合、VTKのファイルが見つからないか、表示されるファイルの数が圧倒的に少なくなります。(なお、ビルドするパッケージの種類によってファイルの数は変わります)

C:\> where vtk*
C:\lib\VTK\bin\vtkChartsCore-8.2.dll
C:\lib\VTK\bin\vtkChartsCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkCommonColor-8.2.dll
C:\lib\VTK\bin\vtkCommonColorPython36D-8.2.dll
C:\lib\VTK\bin\vtkCommonComputationalGeometry-8.2.dll
C:\lib\VTK\bin\vtkCommonComputationalGeometryPython36D-8.2.dll
C:\lib\VTK\bin\vtkCommonCore-8.2.dll
C:\lib\VTK\bin\vtkCommonCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkCommonDataModel-8.2.dll
C:\lib\VTK\bin\vtkCommonDataModelPython36D-8.2.dll
C:\lib\VTK\bin\vtkCommonExecutionModel-8.2.dll
C:\lib\VTK\bin\vtkCommonExecutionModelPython36D-8.2.dll
C:\lib\VTK\bin\vtkCommonMath-8.2.dll
C:\lib\VTK\bin\vtkCommonMathPython36D-8.2.dll
C:\lib\VTK\bin\vtkCommonMisc-8.2.dll
C:\lib\VTK\bin\vtkCommonMiscPython36D-8.2.dll
C:\lib\VTK\bin\vtkCommonSystem-8.2.dll
C:\lib\VTK\bin\vtkCommonSystemPython36D-8.2.dll
C:\lib\VTK\bin\vtkCommonTransforms-8.2.dll
C:\lib\VTK\bin\vtkCommonTransformsPython36D-8.2.dll
C:\lib\VTK\bin\vtkDICOMParser-8.2.dll
C:\lib\VTK\bin\vtkDomainsChemistry-8.2.dll
C:\lib\VTK\bin\vtkDomainsChemistryOpenGL2-8.2.dll
C:\lib\VTK\bin\vtkDomainsChemistryOpenGL2Python36D-8.2.dll
C:\lib\VTK\bin\vtkDomainsChemistryPython36D-8.2.dll
C:\lib\VTK\bin\vtkdoubleconversion-8.2.dll
C:\lib\VTK\bin\vtkexodusII-8.2.dll
C:\lib\VTK\bin\vtkexpat-8.2.dll
C:\lib\VTK\bin\vtkFiltersAMR-8.2.dll
C:\lib\VTK\bin\vtkFiltersAMRPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersCore-8.2.dll
C:\lib\VTK\bin\vtkFiltersCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersExtraction-8.2.dll
C:\lib\VTK\bin\vtkFiltersExtractionPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersFlowPaths-8.2.dll
C:\lib\VTK\bin\vtkFiltersFlowPathsPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersGeneral-8.2.dll
C:\lib\VTK\bin\vtkFiltersGeneralPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersGeneric-8.2.dll
C:\lib\VTK\bin\vtkFiltersGenericPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersGeometry-8.2.dll
C:\lib\VTK\bin\vtkFiltersGeometryPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersHybrid-8.2.dll
C:\lib\VTK\bin\vtkFiltersHybridPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersHyperTree-8.2.dll
C:\lib\VTK\bin\vtkFiltersHyperTreePython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersImaging-8.2.dll
C:\lib\VTK\bin\vtkFiltersImagingPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersModeling-8.2.dll
C:\lib\VTK\bin\vtkFiltersModelingPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersParallel-8.2.dll
C:\lib\VTK\bin\vtkFiltersParallelImaging-8.2.dll
C:\lib\VTK\bin\vtkFiltersParallelImagingPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersParallelPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersPoints-8.2.dll
C:\lib\VTK\bin\vtkFiltersPointsPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersProgrammable-8.2.dll
C:\lib\VTK\bin\vtkFiltersProgrammablePython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersPython-8.2.dll
C:\lib\VTK\bin\vtkFiltersPythonPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersSelection-8.2.dll
C:\lib\VTK\bin\vtkFiltersSelectionPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersSMP-8.2.dll
C:\lib\VTK\bin\vtkFiltersSMPPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersSources-8.2.dll
C:\lib\VTK\bin\vtkFiltersSourcesPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersStatistics-8.2.dll
C:\lib\VTK\bin\vtkFiltersStatisticsPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersTexture-8.2.dll
C:\lib\VTK\bin\vtkFiltersTexturePython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersTopology-8.2.dll
C:\lib\VTK\bin\vtkFiltersTopologyPython36D-8.2.dll
C:\lib\VTK\bin\vtkFiltersVerdict-8.2.dll
C:\lib\VTK\bin\vtkFiltersVerdictPython36D-8.2.dll
C:\lib\VTK\bin\vtkfreetype-8.2.dll
C:\lib\VTK\bin\vtkGeovisCore-8.2.dll
C:\lib\VTK\bin\vtkGeovisCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkgl2ps-8.2.dll
C:\lib\VTK\bin\vtkglew-8.2.dll
C:\lib\VTK\bin\vtkhdf5-8.2.dll
C:\lib\VTK\bin\vtkhdf5_hl-8.2.dll
C:\lib\VTK\bin\vtkImagingColor-8.2.dll
C:\lib\VTK\bin\vtkImagingColorPython36D-8.2.dll
C:\lib\VTK\bin\vtkImagingCore-8.2.dll
C:\lib\VTK\bin\vtkImagingCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkImagingFourier-8.2.dll
C:\lib\VTK\bin\vtkImagingFourierPython36D-8.2.dll
C:\lib\VTK\bin\vtkImagingGeneral-8.2.dll
C:\lib\VTK\bin\vtkImagingGeneralPython36D-8.2.dll
C:\lib\VTK\bin\vtkImagingHybrid-8.2.dll
C:\lib\VTK\bin\vtkImagingHybridPython36D-8.2.dll
C:\lib\VTK\bin\vtkImagingMath-8.2.dll
C:\lib\VTK\bin\vtkImagingMathPython36D-8.2.dll
C:\lib\VTK\bin\vtkImagingMorphological-8.2.dll
C:\lib\VTK\bin\vtkImagingMorphologicalPython36D-8.2.dll
C:\lib\VTK\bin\vtkImagingSources-8.2.dll
C:\lib\VTK\bin\vtkImagingSourcesPython36D-8.2.dll
C:\lib\VTK\bin\vtkImagingStatistics-8.2.dll
C:\lib\VTK\bin\vtkImagingStatisticsPython36D-8.2.dll
C:\lib\VTK\bin\vtkImagingStencil-8.2.dll
C:\lib\VTK\bin\vtkImagingStencilPython36D-8.2.dll
C:\lib\VTK\bin\vtkInfovisCore-8.2.dll
C:\lib\VTK\bin\vtkInfovisCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkInfovisLayout-8.2.dll
C:\lib\VTK\bin\vtkInfovisLayoutPython36D-8.2.dll
C:\lib\VTK\bin\vtkInteractionImage-8.2.dll
C:\lib\VTK\bin\vtkInteractionImagePython36D-8.2.dll
C:\lib\VTK\bin\vtkInteractionStyle-8.2.dll
C:\lib\VTK\bin\vtkInteractionStylePython36D-8.2.dll
C:\lib\VTK\bin\vtkInteractionWidgets-8.2.dll
C:\lib\VTK\bin\vtkInteractionWidgetsPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOAMR-8.2.dll
C:\lib\VTK\bin\vtkIOAMRPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOAsynchronous-8.2.dll
C:\lib\VTK\bin\vtkIOAsynchronousPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOCityGML-8.2.dll
C:\lib\VTK\bin\vtkIOCityGMLPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOCore-8.2.dll
C:\lib\VTK\bin\vtkIOCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkIOEnSight-8.2.dll
C:\lib\VTK\bin\vtkIOEnSightPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOExodus-8.2.dll
C:\lib\VTK\bin\vtkIOExodusPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOExport-8.2.dll
C:\lib\VTK\bin\vtkIOExportOpenGL2-8.2.dll
C:\lib\VTK\bin\vtkIOExportOpenGL2Python36D-8.2.dll
C:\lib\VTK\bin\vtkIOExportPDF-8.2.dll
C:\lib\VTK\bin\vtkIOExportPDFPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOExportPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOGeometry-8.2.dll
C:\lib\VTK\bin\vtkIOGeometryPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOImage-8.2.dll
C:\lib\VTK\bin\vtkIOImagePython36D-8.2.dll
C:\lib\VTK\bin\vtkIOImport-8.2.dll
C:\lib\VTK\bin\vtkIOImportPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOInfovis-8.2.dll
C:\lib\VTK\bin\vtkIOInfovisPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOLegacy-8.2.dll
C:\lib\VTK\bin\vtkIOLegacyPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOLSDyna-8.2.dll
C:\lib\VTK\bin\vtkIOLSDynaPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOMINC-8.2.dll
C:\lib\VTK\bin\vtkIOMINCPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOMovie-8.2.dll
C:\lib\VTK\bin\vtkIOMoviePython36D-8.2.dll
C:\lib\VTK\bin\vtkIONetCDF-8.2.dll
C:\lib\VTK\bin\vtkIONetCDFPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOParallel-8.2.dll
C:\lib\VTK\bin\vtkIOParallelPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOParallelXML-8.2.dll
C:\lib\VTK\bin\vtkIOParallelXMLPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOPLY-8.2.dll
C:\lib\VTK\bin\vtkIOPLYPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOSegY-8.2.dll
C:\lib\VTK\bin\vtkIOSegYPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOSQL-8.2.dll
C:\lib\VTK\bin\vtkIOSQLPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOTecplotTable-8.2.dll
C:\lib\VTK\bin\vtkIOTecplotTablePython36D-8.2.dll
C:\lib\VTK\bin\vtkIOVeraOut-8.2.dll
C:\lib\VTK\bin\vtkIOVeraOutPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOVideo-8.2.dll
C:\lib\VTK\bin\vtkIOVideoPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOXML-8.2.dll
C:\lib\VTK\bin\vtkIOXMLParser-8.2.dll
C:\lib\VTK\bin\vtkIOXMLParserPython36D-8.2.dll
C:\lib\VTK\bin\vtkIOXMLPython36D-8.2.dll
C:\lib\VTK\bin\vtkjpeg-8.2.dll
C:\lib\VTK\bin\vtkjsoncpp-8.2.dll
C:\lib\VTK\bin\vtklibharu-8.2.dll
C:\lib\VTK\bin\vtklibxml2-8.2.dll
C:\lib\VTK\bin\vtklz4-8.2.dll
C:\lib\VTK\bin\vtklzma-8.2.dll
C:\lib\VTK\bin\vtkmetaio-8.2.dll
C:\lib\VTK\bin\vtkNetCDF-8.2.dll
C:\lib\VTK\bin\vtkogg-8.2.dll
C:\lib\VTK\bin\vtkParallelCore-8.2.dll
C:\lib\VTK\bin\vtkParallelCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkParseJava-8.2.exe
C:\lib\VTK\bin\vtkpng-8.2.dll
C:\lib\VTK\bin\vtkproj-8.2.dll
C:\lib\VTK\bin\vtkpugixml-8.2.dll
C:\lib\VTK\bin\vtkpython.exe
C:\lib\VTK\bin\vtkPythonContext2D-8.2.dll
C:\lib\VTK\bin\vtkPythonContext2DPython36D-8.2.dll
C:\lib\VTK\bin\vtkPythonInterpreter-8.2.dll
C:\lib\VTK\bin\vtkRenderingAnnotation-8.2.dll
C:\lib\VTK\bin\vtkRenderingAnnotationPython36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingContext2D-8.2.dll
C:\lib\VTK\bin\vtkRenderingContext2DPython36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingContextOpenGL2-8.2.dll
C:\lib\VTK\bin\vtkRenderingContextOpenGL2Python36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingCore-8.2.dll
C:\lib\VTK\bin\vtkRenderingCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingFreeType-8.2.dll
C:\lib\VTK\bin\vtkRenderingFreeTypePython36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingGL2PSOpenGL2-8.2.dll
C:\lib\VTK\bin\vtkRenderingGL2PSOpenGL2Python36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingImage-8.2.dll
C:\lib\VTK\bin\vtkRenderingImagePython36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingLabel-8.2.dll
C:\lib\VTK\bin\vtkRenderingLabelPython36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingLOD-8.2.dll
C:\lib\VTK\bin\vtkRenderingLODPython36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingOpenGL2-8.2.dll
C:\lib\VTK\bin\vtkRenderingOpenGL2Python36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingVolume-8.2.dll
C:\lib\VTK\bin\vtkRenderingVolumeOpenGL2-8.2.dll
C:\lib\VTK\bin\vtkRenderingVolumeOpenGL2Python36D-8.2.dll
C:\lib\VTK\bin\vtkRenderingVolumePython36D-8.2.dll
C:\lib\VTK\bin\vtksqlite-8.2.dll
C:\lib\VTK\bin\vtksys-8.2.dll
C:\lib\VTK\bin\vtktheora-8.2.dll
C:\lib\VTK\bin\vtktiff-8.2.dll
C:\lib\VTK\bin\vtkverdict-8.2.dll
C:\lib\VTK\bin\vtkViewsContext2D-8.2.dll
C:\lib\VTK\bin\vtkViewsContext2DPython36D-8.2.dll
C:\lib\VTK\bin\vtkViewsCore-8.2.dll
C:\lib\VTK\bin\vtkViewsCorePython36D-8.2.dll
C:\lib\VTK\bin\vtkViewsGeovis-8.2.dll
C:\lib\VTK\bin\vtkViewsGeovisPython36D-8.2.dll
C:\lib\VTK\bin\vtkViewsInfovis-8.2.dll
C:\lib\VTK\bin\vtkViewsInfovisPython36D-8.2.dll
C:\lib\VTK\bin\vtkWrapHierarchy-8.2.exe
C:\lib\VTK\bin\vtkWrapJava-8.2.exe
C:\lib\VTK\bin\vtkWrappingPython36Core-8.2.dll
C:\lib\VTK\bin\vtkWrapPython-8.2.exe
C:\lib\VTK\bin\vtkWrapPythonInit-8.2.exe
C:\lib\VTK\bin\vtkzlib-8.2.dll

 

PythonからVTKを利用する方法

ここでは、Pythonにvtkという仮想環境を作成してVTK 8.2.0を利用する方法を紹介します。

仮想環境の作成

まずは、コマンドプロンプトで以下のコマンドを実行し、vtkという仮想環境をC:\venvs\vtkに作成します。(Python 3.6で仮想環境を作成する一般的な方法です)

> python -m venv C:\venvs\vtk

 

VTKパッケージのコピー

C:\venvs\vtkに仮想環境が作成されるので、C:\lib\VTK\bin\Lib\site-packagesフォルダを、C:\venvs\vtk\Lib\site-packages上書きコピーします。

これで、C:\venvs\vtk\Lib\site-packagesフォルダに、vtk.pyvtkmodulesフォルダがコピーされ、PythonからVTKが利用可能になります。

利用できるかどうかの確認は、以下コマンドで確認できます。

rem 仮想環境vtkを有効にする
C:\> C:\venvs\vtk\Scripts\activate.bat

rem VTKの動作確認と実行結果
(vtk) C:\>python -c "import vtk; print(vtk.vtkVersion.GetVTKSourceVersion())"
vtk version 8.2.0

 

VTKのサンプルコードの実行

VTKのPythonサンプルはGitHubのVTKExamplesなどでも公開されており、VTKExamplesのサイトなどからも見ることができます。

例えば、以下のソースコードをQuadraticTetra.pyという名前で保存して、python QuadraticTetra.pyとすると、次のような感じで実行出来ます。

PythonからVTKのサンプルを実行
import vtk


def main():
    namedColors = vtk.vtkNamedColors()

    uGrid = MakeQuadraticTetra()

    tessellate = vtk.vtkTessellatorFilter()
    tessellate.SetInputData(uGrid)

    mapper = vtk.vtkDataSetMapper()
    mapper.SetInputConnection(tessellate.GetOutputPort())
    mapper.ScalarVisibilityOff()

    # Create an actor for the grid
    actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetDiffuseColor(
        namedColors.GetColor3d("Tomato"))
    actor.GetProperty().SetEdgeColor(
        namedColors.GetColor3d("IvoryBlack"))
    actor.GetProperty().EdgeVisibilityOn()

    sphereSource = vtk.vtkSphereSource()
    sphereSource.SetRadius(0.02)

    glyph3D = vtk.vtkGlyph3D()
    glyph3D.SetInputData(uGrid)
    glyph3D.SetSourceConnection(sphereSource.GetOutputPort())
    glyph3D.ScalingOff()
    glyph3D.Update()

    glyph3DMapper = vtk.vtkDataSetMapper()
    glyph3DMapper.SetInputConnection(glyph3D.GetOutputPort())
    glyph3DMapper.ScalarVisibilityOff()

    glyph3DActor = vtk.vtkActor()
    glyph3DActor.SetMapper(glyph3DMapper)
    glyph3DActor.GetProperty().SetColor(
        namedColors.GetColor3d("Banana"))

    # Visualize
    renderer = vtk.vtkRenderer()
    renderWindow = vtk.vtkRenderWindow()
    renderWindow.SetWindowName("Quadratic Tetra")
    renderWindow.AddRenderer(renderer)
    interactor = vtk.vtkRenderWindowInteractor()
    interactor.SetRenderWindow(renderWindow)

    renderer.AddActor(actor)
    renderer.AddActor(glyph3DActor)
    renderer.SetBackground(namedColors.GetColor3d("SlateGray"))

    renderWindow.Render()
    interactor.Start()


def MakeQuadraticTetra():
    aTetra = vtk.vtkQuadraticTetra()
    points = vtk.vtkPoints()

    pcoords = aTetra.GetParametricCoords()
    rng = vtk.vtkMinimalStandardRandomSequence()
    points.SetNumberOfPoints(aTetra.GetNumberOfPoints())
    rng.SetSeed(5070)  # for testing
    for i in range(0, aTetra.GetNumberOfPoints()):
        perturbation = [0.0] * 3
        for j in range(0, 3):
            rng.Next()
            perturbation[j] = rng.GetRangeValue(-0.1, 0.1)
        aTetra.GetPointIds().SetId(i, i)
        points.SetPoint(i, pcoords[3 * i] + perturbation[0],
                        pcoords[3 * i + 1] + perturbation[1],
                        pcoords[3 * i + 2] + perturbation[2])

    # Add the points and tetra to an unstructured grid
    uGrid = vtk.vtkUnstructuredGrid()
    uGrid.SetPoints(points)
    uGrid.InsertNextCell(aTetra.GetCellType(), aTetra.GetPointIds())

    return uGrid


if __name__ == '__main__':
    main()