import pyvista as pv
from streamlit_pyvista.mesh_viewer_component import MeshViewerComponent
from streamlit_pyvista.server_managers import ServerManagerProxified
from streamlit_pyvista.trame_viewers import get_advanced_viewer_path
import solidipes.loaders.data_container
from .viewer import Viewer
from .. import loaders
from ..loaders import FileSequence
from ..utils import viewer_backends
[docs]
class PyvistaPlotter(Viewer):
"""Viewer for pyvista meshes
Args:
**kwargs: keyword arguments passed to the pyvista.Plotter constructor
"""
def __init__(self, data_container=None, add_kwargs={}, show_kwargs={}, **kwargs):
self.compatible_data_types = [loaders.PyvistaMesh]
#: keeps track of whether the plotter has already been shown
self.shown = False
#: Pyvista plotter
self.plotter = None
if viewer_backends.current_backend == "streamlit":
self.plotter = pv.Plotter(off_screen=True, **kwargs)
else: # python or jupyter notebook
self.plotter = pv.Plotter(**kwargs)
self.plotter.background_color = "black"
self.meshes = []
self.points = []
self.path_list = []
super().__init__(data_container, add_kwargs=add_kwargs, show_kwargs=show_kwargs)
self._update_path_list(data_container)
[docs]
def add(self, data_container, **kwargs):
"""Add mesh to the viewer
Args:
**kwargs: keyword arguments passed to the pyvista.Plotter.add_mesh
method
"""
self.check_data_compatibility(data_container)
if isinstance(data_container, loaders.Abaqus):
for name, m in data_container.meshes.items():
self.meshes.append((m, kwargs))
elif isinstance(data_container, loaders.DataContainer):
self.add_mesh(data_container, **kwargs)
[docs]
def add_mesh(self, data_container: solidipes.loaders.data_container.DataContainer, **kwargs):
"""Add mesh to the viewer
Args:
**kwargs: keyword arguments passed to the pyvista.Plotter.add_mesh
method
"""
data = data_container.mesh
self.meshes.append((data, kwargs))
self._update_path_list(data_container)
[docs]
def _update_path_list(self, data_container):
if isinstance(data_container, FileSequence):
path = data_container.paths.copy()
self.path_list.extend(path)
else:
if data_container is not None:
path = data_container.file_info.path
self.path_list.append(path)
[docs]
def add_points(self, data_container, **kwargs):
"""Add mesh as points to the viewer
Args:
**kwargs: keyword arguments passed to the
pyvista.Plotter.add_points method
"""
data = data_container.mesh
self.points.append((data, kwargs))
[docs]
def show(self, auto_close=False, **kwargs):
"""Show the viewer
Args:
auto_close: whether to close the viewer after showing it
**kwargs: keyword arguments passed to the pyvista.Plotter.show
method
"""
for p, _kwargs in self.points:
self.plotter.add_points(p, **_kwargs)
for m, _kwargs in self.meshes:
self.plotter.add_mesh(m, **_kwargs)
if viewer_backends.current_backend == "streamlit":
key = f"pyvista_ploter_{self.path_list}"
import streamlit as st
for p, _ in self.points:
st.write(p)
# Display arrays of the raw data
for i, (m, kw) in enumerate(self.meshes):
options_key = key + f"mesh_{i}_options"
if options_key not in st.session_state:
st.session_state[options_key] = ["None"] + m.array_names
st.write(m)
if len(self.path_list) == 0:
st.error("No mesh passed to the PyvistaPlotter")
return
self.shown = True
# Instantiate the viewer
MeshViewerComponent(self.path_list, trame_viewer_class=get_advanced_viewer_path(),
server_manager_class=ServerManagerProxified).show()
elif viewer_backends.current_backend == "python":
self.shown = True
self.plotter.show(kwargs)
else:
self.shown = True
MeshViewerComponent(self.path_list, trame_viewer_class=get_advanced_viewer_path(),
server_manager_class=ServerManagerProxified).show()
[docs]
def save(self, path, **kwargs):
"""Save the view to a file
Args:
path: path to the file
**kwargs: keyword arguments passed to the
pyvista.Plotter.screenshot method
"""
# Pyvista Plotter must be shown before saving
if not self.shown:
self.plotter.show(auto_close=False) # also for streamlit backend
self.shown = True
self.plotter.screenshot(path, **kwargs)