From 7a847a0ca1294cbff2f191275a09fe7007d6f66e Mon Sep 17 00:00:00 2001 From: Sebastien Jourdain Date: Thu, 13 Apr 2023 08:51:12 -0600 Subject: [PATCH] docs(examples): Add docker remote rendering example --- examples/00_howdoi/interactive.py | 1 + examples/02_vuetify/00_dataframe-table.py | 1 - .../06_vtk/Applications/SurfacePicking/app.py | 1 - .../deploy/docker/VtkRendering/Dockerfile | 5 + examples/deploy/docker/VtkRendering/README.md | 31 ++++++ examples/deploy/docker/VtkRendering/app.py | 102 ++++++++++++++++++ .../docker/VtkRendering/captain-definition | 4 + .../deploy/docker/VtkRendering/setup/apps.yml | 11 ++ .../VtkRendering/setup/requirements.txt | 2 + examples/validation/core/00_state.py | 1 + examples/validation/core/01_trigger.py | 1 + examples/validation/core/17_hot_reload.py | 1 + examples/validation/core/21_file_browser.py | 1 - .../core/26_vtk_swap_view_remote.py | 1 - 14 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 examples/deploy/docker/VtkRendering/Dockerfile create mode 100644 examples/deploy/docker/VtkRendering/README.md create mode 100644 examples/deploy/docker/VtkRendering/app.py create mode 100644 examples/deploy/docker/VtkRendering/captain-definition create mode 100644 examples/deploy/docker/VtkRendering/setup/apps.yml create mode 100644 examples/deploy/docker/VtkRendering/setup/requirements.txt diff --git a/examples/00_howdoi/interactive.py b/examples/00_howdoi/interactive.py index 6beeb4f8..70e285dd 100644 --- a/examples/00_howdoi/interactive.py +++ b/examples/00_howdoi/interactive.py @@ -14,6 +14,7 @@ DEFAULT_VALUE = 5 state.trame_title = "Counter" + # Updates def increment(): state.my_number += 1 diff --git a/examples/02_vuetify/00_dataframe-table.py b/examples/02_vuetify/00_dataframe-table.py index dc10676e..9e681842 100644 --- a/examples/02_vuetify/00_dataframe-table.py +++ b/examples/02_vuetify/00_dataframe-table.py @@ -89,7 +89,6 @@ def fetch_data(samples=15): @state.change("selection") def selection_change(selection=[], **kwargs): - global DATA_FRAME selected_df = pd.DataFrame(selection) diff --git a/examples/06_vtk/Applications/SurfacePicking/app.py b/examples/06_vtk/Applications/SurfacePicking/app.py index 6cb97e52..69b17a86 100644 --- a/examples/06_vtk/Applications/SurfacePicking/app.py +++ b/examples/06_vtk/Applications/SurfacePicking/app.py @@ -163,7 +163,6 @@ def update_tooltip(pickData, pixel_ratio, **kwargs): xyx = data["worldPosition"] idx = f1_mesh.FindPoint(xyx) if idx > -1: - messages = [] cone_state = { "resolution": 12, diff --git a/examples/deploy/docker/VtkRendering/Dockerfile b/examples/deploy/docker/VtkRendering/Dockerfile new file mode 100644 index 00000000..717362f4 --- /dev/null +++ b/examples/deploy/docker/VtkRendering/Dockerfile @@ -0,0 +1,5 @@ +FROM kitware/trame + +COPY --chown=trame-user:trame-user . /deploy + +RUN /opt/trame/entrypoint.sh build diff --git a/examples/deploy/docker/VtkRendering/README.md b/examples/deploy/docker/VtkRendering/README.md new file mode 100644 index 00000000..07fb245a --- /dev/null +++ b/examples/deploy/docker/VtkRendering/README.md @@ -0,0 +1,31 @@ +# Disclaimer + +The current example rely on OSMesa for doing remote rendering but for good rendering performance +using the nvidia-runtime with __kitware/trame:glvnd__ base image and an EGL build of VTK would be preferred. + +# Build the image + +```bash +docker build -t trame-vtk-app . +``` + +# Run the image on port 8080 + +```bash +docker run -it --rm -p 8080:80 trame-vtk-app +``` + +# Deploying into CapRover + +If that directory was at the root of a git repo you could run the following command line + +```bash +caprover deploy +``` + +That app could also be deployed by running the following set of commands + +```bash +tar -cvf trame-vtk-app.tar captain-definition Dockerfile app.py setup +caprover deploy -t trame-vtk-app.tar +``` diff --git a/examples/deploy/docker/VtkRendering/app.py b/examples/deploy/docker/VtkRendering/app.py new file mode 100644 index 00000000..adbac39c --- /dev/null +++ b/examples/deploy/docker/VtkRendering/app.py @@ -0,0 +1,102 @@ +from trame.app import get_server +from trame.widgets import vuetify, vtk as vtk_widgets +from trame.ui.vuetify import SinglePageLayout + +from vtkmodules.vtkFiltersSources import vtkConeSource +from vtkmodules.vtkRenderingCore import ( + vtkRenderer, + vtkRenderWindow, + vtkRenderWindowInteractor, + vtkPolyDataMapper, + vtkActor, +) + +# VTK factory initialization +from vtkmodules.vtkInteractionStyle import vtkInteractorStyleSwitch # noqa +import vtkmodules.vtkRenderingOpenGL2 # noqa + +# ----------------------------------------------------------------------------- +# Trame initialization +# ----------------------------------------------------------------------------- + +server = get_server() +state, ctrl = server.state, server.controller + +state.trame__title = "VTK Remote rendering" + +# ----------------------------------------------------------------------------- +# VTK code +# ----------------------------------------------------------------------------- + +DEFAULT_RESOLUTION = 6 + +renderer = vtkRenderer() +renderWindow = vtkRenderWindow() +renderWindow.AddRenderer(renderer) +renderWindow.OffScreenRenderingOn() + +renderWindowInteractor = vtkRenderWindowInteractor() +renderWindowInteractor.SetRenderWindow(renderWindow) +renderWindowInteractor.GetInteractorStyle().SetCurrentStyleToTrackballCamera() + +cone_source = vtkConeSource() +mapper = vtkPolyDataMapper() +actor = vtkActor() +mapper.SetInputConnection(cone_source.GetOutputPort()) +actor.SetMapper(mapper) +renderer.AddActor(actor) +renderer.ResetCamera() +renderWindow.Render() + + +@state.change("resolution") +def update_cone(resolution=DEFAULT_RESOLUTION, **kwargs): + cone_source.SetResolution(resolution) + ctrl.view_update() + + +def update_reset_resolution(): + state.resolution = DEFAULT_RESOLUTION + + +# ----------------------------------------------------------------------------- +# GUI +# ----------------------------------------------------------------------------- + +with SinglePageLayout(server) as layout: + layout.icon.click = ctrl.view_reset_camera + layout.title.set_text("Cone Application") + + with layout.toolbar: + vuetify.VSpacer() + vuetify.VSlider( + v_model=("resolution", DEFAULT_RESOLUTION), + min=3, + max=60, + step=1, + hide_details=True, + dense=True, + style="max-width: 300px", + ) + vuetify.VDivider(vertical=True, classes="mx-2") + with vuetify.VBtn(icon=True, click=update_reset_resolution): + vuetify.VIcon("mdi-undo-variant") + + with layout.content: + with vuetify.VContainer( + fluid=True, + classes="pa-0 fill-height", + ): + view = vtk_widgets.VtkRemoteView( + renderWindow, + ref="view", + ) + ctrl.view_update = view.update + ctrl.view_reset_camera = view.reset_camera + +# ----------------------------------------------------------------------------- +# Main +# ----------------------------------------------------------------------------- + +if __name__ == "__main__": + server.start() diff --git a/examples/deploy/docker/VtkRendering/captain-definition b/examples/deploy/docker/VtkRendering/captain-definition new file mode 100644 index 00000000..0e14f823 --- /dev/null +++ b/examples/deploy/docker/VtkRendering/captain-definition @@ -0,0 +1,4 @@ +{ + "schemaVersion": 2, + "dockerfilePath": "./Dockerfile" +} diff --git a/examples/deploy/docker/VtkRendering/setup/apps.yml b/examples/deploy/docker/VtkRendering/setup/apps.yml new file mode 100644 index 00000000..09e0e534 --- /dev/null +++ b/examples/deploy/docker/VtkRendering/setup/apps.yml @@ -0,0 +1,11 @@ +trame: + cmd: + - python + - /deploy/app.py + - --host + - ${host} + - --port + - ${port} + - --authKey + - ${secret} + - --server \ No newline at end of file diff --git a/examples/deploy/docker/VtkRendering/setup/requirements.txt b/examples/deploy/docker/VtkRendering/setup/requirements.txt new file mode 100644 index 00000000..d7a1d62b --- /dev/null +++ b/examples/deploy/docker/VtkRendering/setup/requirements.txt @@ -0,0 +1,2 @@ +trame +--find-links wheels.vtk.org vtk-osmesa \ No newline at end of file diff --git a/examples/validation/core/00_state.py b/examples/validation/core/00_state.py index c5fa4a16..0f7d201d 100644 --- a/examples/validation/core/00_state.py +++ b/examples/validation/core/00_state.py @@ -25,6 +25,7 @@ # ----------------------------------------------------------------------------- layout = DivLayout(server) + # UI helper to extent layout def create_variable_editor(name): with layout: diff --git a/examples/validation/core/01_trigger.py b/examples/validation/core/01_trigger.py index 1ebd6cb5..3b3eca0a 100644 --- a/examples/validation/core/01_trigger.py +++ b/examples/validation/core/01_trigger.py @@ -33,6 +33,7 @@ def update_variable(var_name="a", delta=+1): with layout: trame.LifeCycleMonitor() + # UI helper to extent layout def create_variable_editor(name): with layout: diff --git a/examples/validation/core/17_hot_reload.py b/examples/validation/core/17_hot_reload.py index b9c3214c..12d8ed1d 100644 --- a/examples/validation/core/17_hot_reload.py +++ b/examples/validation/core/17_hot_reload.py @@ -18,6 +18,7 @@ html.initialize(server) vuetify.initialize(server) + # ----------------------------------------------------------------------------- # Dynamically modify any `ChangeMe` to see the new code execute while # interacting with the app. diff --git a/examples/validation/core/21_file_browser.py b/examples/validation/core/21_file_browser.py index 4c9d15b9..ba5547c8 100644 --- a/examples/validation/core/21_file_browser.py +++ b/examples/validation/core/21_file_browser.py @@ -47,7 +47,6 @@ def open_directory(): layout = SinglePageLayout(server) with layout: - # Toolbar with layout.toolbar as toolbar: toolbar.clear() diff --git a/examples/validation/core/26_vtk_swap_view_remote.py b/examples/validation/core/26_vtk_swap_view_remote.py index cc57cdfe..2ba91205 100644 --- a/examples/validation/core/26_vtk_swap_view_remote.py +++ b/examples/validation/core/26_vtk_swap_view_remote.py @@ -140,7 +140,6 @@ async def refresh_function(**kwargs): with VAppLayout(server) as layout: - with layout.root: with vuetify.VContainer(fluid=True, classes="pa-0 fill-height"): view = vtk.VtkRemoteView(cone_window)