We’ve recently been improving the support between PyVista and Trame to provide a cutting-edge viewer for Jupyter. This is included in PyVista’s latest 0.38.1 release!
pip install 'pyvista[jupyter]>=0.38.1'
Trame provides a high-level framework for building reactive, stateful web applications
PyVista provides a high-level framework for 3D visualization, exposing VTK in a “Pythonic” manner
High-level framework 1 + high-level framework 2 = a streamlined approach to making powerful web applications with 3D visualization front and center.
An example of this I am most thrilled to share is with Jupyter Notebooks. For PyVista’s latest release, we included a Jupyter widget built on Trame that will connect to a PyVista Plotter to stream both server-rendered visualizations and/or the scene data for client-side rendering with VTK.js.
I’d include a video, but I’m limited to upload sizes of 4Mb. Perhaps check out my tweet:
I also want to highlight a long-requested feature for PyVista from VTK power-users: vtkAgorithm support with PyVista’s Plotter API. This was also added in PyVista’s 0.38.1 release, and we have examples here:
You only need an offscreen version of vtk and trame.
pip uninstall vtk
pip install vtk-osmesa --extra-index-url https://wheels.vtk.org # or vtk-egl if you have a GPU
pip install trame trame-vtk trame-vuetify
Then in a cell you can do
from trame.app import get_server
from trame.decorators import TrameApp, change
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
@TrameApp()
class Cone:
def __init__(self, server_or_name=None):
self.server = get_server(server_or_name, client_type="vue2")
self._vtk_rw, self._vtk_cone = self._vtk_setup()
self.ui = self._generate_ui()
@property
def ctrl(self):
return self.server.controller
@property
def state(self):
return self.server.state
@change("resolution")
def on_resolution_change(self, resolution, **kwargs):
self._vtk_cone.SetResolution(resolution)
self.ctrl.view_update()
@property
def resolution(self):
return self.state.resolution
@resolution.setter
def resolution(self, v):
with self.state:
self.state.resolution = v
def reset_resolution(self):
self.resolution = 6
def _vtk_setup(self):
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()
return renderWindow, cone_source
def _generate_ui(self):
with SinglePageLayout(self.server) as layout:
layout.title.set_text("Trame demo")
with layout.toolbar as toolbar:
toolbar.dense = True
vuetify.VSpacer()
vuetify.VSlider(
v_model=("resolution", 6),
min=3,
max=60,
step=1,
hide_details=True,
style="max-width: 300px;",
)
with vuetify.VBtn(icon=True, click=self.reset_resolution):
vuetify.VIcon("mdi-lock-reset")
with vuetify.VBtn(icon=True, click=self.ctrl.view_reset_camera):
vuetify.VIcon("mdi-crop-free")
with layout.content:
with vuetify.VContainer(fluid=True, classes="pa-0 fill-height"):
view = vtk_widgets.VtkRemoteView(self._vtk_rw)
self.ctrl.view_update = view.update
self.ctrl.view_reset_camera = view.reset_camera
return layout
I start the environment with jupyter-notebook in docker container. With the codes you provided, I got the error:
ERROR:root:Exception raised by task = <Task finished name=‘Task-5’ coro=<WebAppServer.start() done, defined at /usr/local/envs/ssenv/lib/python3.8/site-packages/wslink/backends/aiohttp/init.py:110> exception=OSError(99, “error while attempting to bind on address (‘::1’, 0, 0, 0): cannot assign requested address”)>
Traceback (most recent call last):
File “/usr/local/envs/ssenv/lib/python3.8/site-packages/trame_server/core.py”, line 686, in on_done
task.result()
File “/usr/local/envs/ssenv/lib/python3.8/site-packages/wslink/backends/aiohttp/init.py”, line 123, in start
await self._site.start()
File “/usr/local/envs/ssenv/lib/python3.8/site-packages/aiohttp/web_runner.py”, line 119, in start
self._server = await loop.create_server(
File “/usr/local/envs/ssenv/lib/python3.8/asyncio/base_events.py”, line 1463, in create_server
raise OSError(err.errno, ‘error while attempting ’
OSError: [Errno 99] error while attempting to bind on address (’::1’, 0, 0, 0): cannot assign requested address
Interactive visualisation using PyVista
I was trying to generate an interactive visualisation but it was throwing errors,
so installed these modules along with ipywidgets to generate viz in jupyter notebook and it worked fine.
Hope this might help someone