Trameツールバーのカスタマイズ#

jupyterのビューにtrameのパワーをもっともたらします.

import asyncio

import pyvista as pv
from pyvista.trame.ui.vuetify2 import button, divider, select, slider, text_field

まず,trameのツールバーに追加したいメニュー項目を作成しましょう.ここでは, button_play 関数を通してsliderに接続される "play" ボタンを作成します.sliderはレンダリングするモデルの "resolution" を表し, "resolution" の値が表示されるテキストフィールドになります.また,モデルの表示を切り替えるドロップダウンメニューも追加します.dividerは,ツールバーを分割して整理するために既に使用したものと同じです.

def custom_tools():
    divider(vertical=True, classes='mx-1')
    button(
        click=button_play,
        icon='mdi-play',
        tooltip='Play',
    )

    slider(
        model=("resolution", 10),
        tooltip="Resolution slider",
        min=3,
        max=20,
        step=1,
        dense=True,
        hide_details=True,
        style="width: 300px",
        classes='my-0 py-0 ml-1 mr-1',
    )
    text_field(
        model=("resolution", 10),
        tooltip="Resolution value",
        readonly=True,
        type="number",
        dense=True,
        hide_details=True,
        style="min-width: 40px; width: 60px",
        classes='my-0 py-0 ml-1 mr-1',
    )

    divider(vertical=True, classes='mx-1')
    select(
        model=("visibility", "Show"),
        tooltip="Toggle visibility",
        items=['Visibility', ["Hide", "Show"]],
        hide_details=True,
        dense=True,
    )

ボタンコールバック関数 button_play はサーバーを起動する前に作成する必要があります.この関数はブール値の状態変数 play をトグルし,サーバーをフラッシュします.ステート変数についてはもう少し詳しく説明しますが,ここで関数を作成する必要があります.

def button_play():
    state.play = not state.play
    state.flush()

vtk vtkConeSouce アルゴリズムを使用して,コーンの簡単なレンダリングを行います.

pl.show メソッドを使用する場合.作成した custom_tools 関数を jupyter_kwargs 引数として add_menu_items キーで渡す必要があります.

pl = pv.Plotter(notebook=True)
algo = pv.ConeSource()
mesh_actor = pl.add_mesh(algo)

widget = pl.show(jupyter_kwargs=dict(add_menu_items=custom_tools), return_viewer=True)
customization trame toolbar

trame のサーバーと対話するためには,サーバーの状態を取得する必要があります.

共有ステートで play 変数を初期化し,作成した再生ボタンでコントロールできるようにします.なお, slidertext_fieldselect ツールを作成する際に, model=("variable", value) のようなものを渡しています.これにより,サーバーの共有ステートに値 value を持つ変数 "variable" が自動的に作成されるため, state.resolutionstate.visibility を作成する必要はありません.

state, ctrl = widget.viewer.server.state, widget.viewer.server.controller
state.play = False
ctrl.view_update = widget.viewer.update

これで,メニュー項目のコールバック関数を作成できるようになりました.

関数は state.change("variable") でデコレートされています.これは,この特定の変数の値がサーバーの共有ステートで変更されたときに呼び出されることを意味します. resolution が変更されると,コーンアルゴリズムの解像度を更新します. visibility が変更されると,コーンの可視性を切り替えます.

変数 play は少しトリッキーです.アニメーションを再生するためにタイマーのようなものをスタートさせたいです.これを trame で行うには,非同期関数が必要です.関数 _play は,変数 play が変更された時に (再生ボタンをクリックした時、コールバック button_play を通して) 呼び出されます. state.playTrue の間,アニメーションを再生したいです. state.resolution の値を変更しますが,実際に update_resolution 関数を呼び出すには,サーバーを flush して,共有変数の変更を確認させる必要があります. state.playFalse に変更されると,アニメーションは停止します.

実際のステート変数ではなく,コールバック関数に渡される引数値でしかないため, while play: ... を使用してもここでは機能しないことに注意してください.

# trame callbacks
@state.change("play")
async def _play(play, **kwargs):
    while state.play:
        state.resolution += 1
        state.flush()
        if state.resolution >= 20:
            state.play = False
        await asyncio.sleep(0.3)


@state.change("resolution")
def update_resolution(resolution, **kwargs):
    algo.resolution = resolution
    ctrl.view_update()


@state.change("visibility")
def set_visibility(visibility, **kwargs):
    toggle = {"Hide": 0, "Show": 1}
    mesh_actor.visibility = toggle[visibility]
    ctrl.view_update()


widget
Widget(value='<iframe src="http://localhost:41139/index.html?ui=P_0x7f21660bbd70_0&reconnect=auto" class="pyvista" style="width: 99%; height: 600px; border: 1px solid rgb(221,221,221);"></iframe>')

Total running time of the script: (0 minutes 0.188 seconds)

Sphinx-Galleryによるギャラリー