PyVista 可視化 (plot3d)¶
PyVista backend は、2D スライスを 3D 空間に置く、3D スカラー場を volume / slice / contour として描く、3D ベクトル場を streamlines / quiver として描くための 3D 可視化 API です。通常の 1D/2D 解析は プロット の plot() / cmap() / contour() を使い、3D の視点操作や重ね描きが必要なときに PyVista を使います。
入口の選び方¶
対象 |
推奨 API |
戻り値 |
|---|---|---|
2D scalar slice |
|
|
3D scalar volume |
|
|
3D vector field |
|
|
Boundary meshes |
|
|
Backtrace / trace paths |
|
|
Mesh construction only |
|
PyVista mesh object |
Data2d.plot3d() と Data3d.plot3d() は PyVista で描画します。VectorData.plot3d() も既定で PyVista backend を使います。Matplotlib 3D backend を使う場合は backend="mpl" を指定します。
インストール¶
PyVista は emout の通常依存としてインストールされます。3D 表示を使う環境でも追加の extra 指定は不要です。
pip install emout
古い環境や editable install で ModuleNotFoundError が出る場合は、emout を再インストールして依存関係を更新してください。
スカラー場¶
2D スライスを 3D 空間に置く¶
2D slice は pyvista.StructuredGrid の平面として描画されます。plot3d() は plotter を返すので、あとからカメラや screenshot を操作できます。
import emout
data = emout.Emout("output_dir")
plotter = data.phisp[-1, 100, :, :].plot3d(
cmap="viridis",
clim=(-20, 20),
show_edges=False,
show=False,
)
plotter.show()
3D ボリュームを描く¶
3D scalar は mode で描き方を切り替えます。
|
描画内容 |
主な追加オプション |
|---|---|---|
|
外側 surface |
|
|
volume rendering |
|
|
直交 slice |
|
|
等値面 |
|
data.phisp[-1].plot3d(mode="box", opacity=0.4, show=True)
data.phisp[-1].plot3d(mode="volume", opacity="sigmoid", show=True)
data.phisp[-1].plot3d(mode="slice", cmap="coolwarm", clim=(-50, 50), show=True)
data.phisp[-1].plot3d(mode="contour", contour_levels=12, show=True)
画像として保存したい場合は、show=False で plotter を受け取り、PyVista の screenshot() を使います。
plotter = data.phisp[-1].plot3d(mode="contour", contour_levels=10, show=False)
plotter.screenshot("phisp_contour.png")
plotter.close()
filename= を渡すと、plot3d() 側で保存まで実行できます。.png などの画像拡張子は screenshot として保存します。.html は PyVista の Jupyter/trame 追加依存が入っている環境では interactive HTML として保存できます。既存の 2D plot と同じく savefilename= も互換エイリアスとして使えます。
data.phisp[-1].plot3d(mode="contour", levels=[0.0], filename="phisp_iso.png")
data.j1xyz[-1].plot3d(mode="stream", filename="j1_stream.png")
ベクトル場¶
3 成分を持つ VectorData は、mode="stream" / "streamline" で streamlines、mode="quiver" / "vec" で glyph arrows を描けます。
data.j1xyz[-1].plot3d(
mode="stream",
backend="pyvista",
n_points=300,
tube_radius=0.02,
show=True,
)
data.j1xyz[-1].plot3d(
mode="quiver",
backend="pyvista",
skip=(3, 3, 2),
factor=0.4,
show=True,
)
streamline の seed は seed_mode で選べます。既定の sphere は中心付近から開始します。plane は 2D streamline に近い見え方になりやすく、volume は領域全体、surface は境界メッシュ上から開始します。任意の開始点を固定したい場合は seed_points を渡します。quiver は skip で間引き、factor で矢印の長さを調整します。
data.j1xyz[-1].plot3d(seed_mode="plane", seed_plane="xz", seed_position="center")
data.j1xyz[-1].plot3d(seed_mode="volume", n_points=1000)
data.j1xyz[-1].plot3d(seed_mode="surface", seed_surface=data.boundaries)
data.j1xyz[-1].plot3d(seed_points=[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]])
重ね描き¶
同じ plotter に追加する¶
各 PyVista API は plotter= を受け取ります。同じ plotter に複数の layer を追加すると、scalar slice、volume outline、vector streamlines を同じ 3D scene に重ねられます。
plotter = data.phisp[-1].plot3d(
mode="slice",
cmap="coolwarm",
clim=(-50, 50),
show=False,
)
data.j1xyz[-1].plot3d(
mode="stream",
backend="pyvista",
plotter=plotter,
tube_radius=0.02,
color="white",
show=True,
)
境界メッシュも同じ plotter に追加できます。data.boundaries.plot3d() は collection 全体、data.boundaries[0].plot3d() は単独境界、data.boundaries.mesh().plot3d() は構築済み MeshSurface3D を描画します。
plotter = data.phisp[-1].plot3d(mode="slice", show=False)
data.boundaries.plot3d(
plotter=plotter,
color="0.7",
opacity=0.35,
show_edges=True,
show=True,
)
境界メッシュ生成引数は mesh_kwargs、境界 index ごとの上書きは per で渡します。Matplotlib / plot_surfaces() 経路の詳細は 境界メッシュ を参照してください。
Backtrace / trace 軌跡を重ねる¶
data.trace.*(..., get_trace=True) の戻り値は plot3d() を持ち、既存 plotter に軌跡を追加できます。確率を計算している場合は、alpha="auto" で軌道ごとの確率を透明度に使います。
trace = data.trace.forward(
x=20.0, y=32.0, z=40.0,
vx=(-5.0, 5.0, 16),
vy=0.0,
vz=(-5.0, 5.0, 16),
get_trace=True,
)
plotter = data.phisp[-1].plot3d(mode="slice", show=False)
trace.plot3d(
plotter=plotter,
direction="forward",
tube_radius=0.05,
color="black",
show=True,
)
get_probabilities=False で trace だけ作った場合、確率由来の alpha はありません。必要なら alpha=0.3 のように明示してください。
単位と軸順序¶
グリッドデータの軸順序は (t, z, y, x)、3D volume は (z, y, x) です。PyVista helper はこの順序を読み取り、PyVista 側の (x, y, z) 座標へ並べ替えます。
use_si=True が既定で、単位 metadata がある場合は座標と値を SI 単位へ変換します。単位 metadata がないデータでは use_si=True を渡しても内部的に grid / raw 値のまま描画します。
offsets=(x_offset, y_offset, z_offset) には数値または "left" / "center" / "right" を指定できます。複数 layer を重ねるときは、すべての layer で同じ use_si と offsets を使ってください。
リモート実行と HPC¶
PyVista 描画は plotter をローカル Python プロセス上に作る API です。data.remote() / remote_figure() は Matplotlib 画像レンダリング向けなので、Data3d.plot3d() の PyVista scene を worker に保持して再描画する用途ではありません。
KUDPC などの login node では、重い PyVista 描画や大きな 3D データ読み込みを直接実行せず、計算ノードや対応する可視化環境へ回してください。スクリプト内では show=False で plotter を作り、screenshot() で画像保存する形にすると batch 実行しやすくなります。
plotter = data.phisp[-1].plot3d(mode="slice", show=False)
plotter.screenshot("phisp_slice.png")
plotter.close()
低水準 helper¶
通常は plot3d() を使います。PyVista mesh を自分で加工したい場合だけ、emout.plot.pyvista_plot の helper を直接使います。
from emout.plot.pyvista_plot import (
create_plane_mesh,
create_surface_mesh,
create_volume_mesh,
create_vector_mesh3d,
)
mesh, scalar_name, axis_labels, scalar_label = create_volume_mesh(data.phisp[-1])
低水準 helper は PyVista オブジェクトを返すだけで、emout の remote rendering や article recording の高水準 API ではありません。
よくあるエラー¶
症状 |
原因 |
対処 |
|---|---|---|
|
古い環境または依存関係が未更新 |
|
|
|
時刻を 1 つに固定して空間 2D slice にする |
|
3D 空間軸が揃っていない |
|
streamlines が出ない |
seed 数や seed 半径が小さい |
|
layer がずれる |
|
すべての layer で同じ指定にする |