🧊 stpyvista: Show PyVista 3D visualizations in Streamlit

:ice_cube: stpyvista: Show PyVista 3D visualizations in Streamlit.

Github Repo PyPi version Github tests repo

howto-stpyvista
Streamlit App

This is a simple component that takes a PyVista plotter object and shows it on Streamlit as an interactive element (as in it can be zoomed in/out, moved and rotated, but the visualization state is not returned). It uses Panel’s VTK implementation and it basically takes the PyVista plotter, exports it to HTML and displays that within an iframe.


Installation:

pip install stpyvista 

Demos:

:outbox_tray: Display your own STL file on Streamlit:

uploadstl-stpyvista

Streamlit App

:bread: Physically Based Rendering (PBR):

textures-stpyvista

Streamlit App


Usage example:

import pyvista as pv
import streamlit as st
from stpyvista import stpyvista

st.title("A cube")
st.info("""Code adapted from https://docs.pyvista.org/user-guide/jupyter/pythreejs.html#scalars-support""")

## Initialize a plotter object
plotter = pv.Plotter(window_size=[400,400])

## Create a mesh with a cube 
mesh = pv.Cube(center=(0,0,0))

## Add some scalar field associated to the mesh
mesh['myscalar'] = mesh.points[:, 2] * mesh.points[:, 0]

## Add mesh to the plotter
plotter.add_mesh(mesh, scalars='myscalar', cmap='bwr')

## Final touches
plotter.view_isometric()
plotter.background_color = 'white'

## Send to streamlit
stpyvista(plotter, key="pv_cube")

Result:


Also check:

10 Likes

Great job @edsaac !

Feel free to add it to the Components Tracker: Streamlit Components - Community Tracker so we don’t lose track of it!

Have a nice day,
Fanilo

1 Like

Really cool! Well done!

1 Like

Very nice work.

I have an curved sufrace object. Can I use the stpyvista to show curvsurf object on streamlit?

ex)
curvsurf = pv.StructuredGrid(xx, yy, zz)

Have a nice day,
kotai2003

1 Like

Yes, all the formats supported by pyvista should be rendered by stpyvista. For creating a StructuredGrid from scratch:

structuredGrid


Code:

import streamlit as st
import pyvista as pv
import numpy as np
from stpyvista import stpyvista

"# 🧱 Structured grid"

## Create coordinate data
x = np.arange(-10, 10, 0.25)
y = np.arange(-10, 10, 0.25)
x, y = np.meshgrid(x, y)
z = np.sin(np.sqrt(x**2 + y**2))

## Set up plotter
plotter = pv.Plotter(window_size=[600,600])
surface = pv.StructuredGrid(x, y, z)
plotter.add_mesh(surface, color='teal', show_edges=True)

## Pass the plotter (not the mesh) to stpyvista
stpyvista(plotter, key="surface")
2 Likes

Thanks so much. Your stpyvista is really awesome!

1 Like

really love it. For some reason the Slider widget is not working in streamlit, i used the example from Slider Bar Widget — PyVista 0.38.5 documentation and passed it into stpyvista. I just get the Plot but without the slider.

stpyvista takes the pyvista plotter and converts it to a panel object that is embeded within streamlit. My guess is that those sliders are not supported by panel and get stripped away, You can use regular streamlit sliders to achieve a similar behavior:

stpyvista_sphere_slider

Code:

import streamlit as st
import pyvista as pv
from stpyvista import stpyvista

res = st.slider("Resolution", 5, 100, 20, 5)

p = pv.Plotter(window_size=[300,300])
sphere = pv.Sphere(phi_resolution=res, theta_resolution=res)
p.add_mesh(sphere, name='sphere', show_edges=True)

p.view_isometric()
p.set_background("white")
stpyvista(p)

love it, thank you!

@edsaac, Is there a way to make the cube transparent?

Sure, you are probably looking for the opacity argument in pyvista.Plotter.add_mesh.

import streamlit as st
import pyvista as pv
from stpyvista import stpyvista

## Initialize a plotter object
plotter = pv.Plotter(window_size=[300,600])

## Create a mesh with a cube 

for i in range(1, 11):
    cube = pv.Cube(center=(0, 0, i), x_length=2, y_length=2, z_length=0.8)
    plotter.add_mesh(cube, edge_color='black', color='purple', opacity=i/10, show_edges=True)

## Final touches
plotter.background_color = '#dddddd'
plotter.view_isometric()

## Send to streamlit
"# 🗼 Opacity tower"
stpyvista(plotter, horizontal_align='left')
2 Likes

@edsaac, this is very useful. I think I will use stpyvista. I have a few questions.

  • I wonder if there is a way to add panning and home button to reset to initial view similar to mpld3 below?
  • Is there a way to rotate cubes as they go up?
  • why isn’t plotter.add_axes not working to show XYZ Coordinates? I used it this way: _ = plotter.add_axes(line_width=5, labels_off=False)

fig_html = mpld3.fig_to_html(fig)
components.html(fig_html, width=width, height=height)

1 Like
  • Panning is done by dragging while pressing the shift key. I am not aware of a way to reset to the initial view, other than re-rendering the element, although there is the option to set an interactive_orientation_widget = True to reset the view to a plane, i.e., xy, yz, etc.

  • Sure! That’s a common transformation in pyvista. For example, check pyvista.DataSet.rotate_x — PyVista 0.39.1 documentation .

  • That is one of the things that panel does not support. Axes must be passed directly as a dictionary of tickers. Check the docs here VTK — Panel v1.1.0 for details.
    image


I’ve updated a few examples at stpyvista’s demo at https://stpyvista.streamlit.app/

1 Like

Does someone know how to visualize the colorbar?
plotter.add_scalar_bar() doesn’t seem to work for me.

1 Like

That’s a bug on panel’s side so will have to look for a workaround, like exporting the colors and limits of the pyvista colorbar and put them in an independent image.

2 Likes

Thank you!

1 Like

@m_b_33, colorbars are displayed using old versions of holoviz stuff:

panel==0.14.4
bokeh==2.4.3
param==1.12.0

That would be the temporary solution while the issue is addressed (#5809)

1 Like

The bug has been fixed in panel 1.3.2 :tada:

1 Like

Can we measure dimensions for each rotation of 3d file?

1 Like

Hi there! In the initial post it was explicitely mentioned that visualization state is not returned. Is there a way to still get it?

At the moment, I am working on an app that generates aircraft configurations based on certain inputs and displays them via stpyvista in the app. I would like the visualization state to be returned such that I can store it in session_state.

In this way, I am hoping that the last user defined camera position is shown again once the inputs are changed. Thanks in advance for your help!

1 Like