I’m deploying an app in Streamlit where I would like to upload a .stl file, and show/visualize it within the app. I have done some research and I found at least one way to do it, with pyplot. However, that doesn’t allow me to rotate the object to see all the views. In the example below, I uploaded a stl file of a frog, and I can actually display the frog, but I can not rotate to see other views.
Here is an idea daisy-chaining pyvista with streamlit,component.v1.html
import streamlit as st
import pyvista as pv
from pyvista import examples
## Using pythreejs as pyvista backend
pv.set_jupyter_backend('pythreejs')
## Download an stl file
# filename = examples.download_cad_model(load=False)
uploadedFile = st.file_uploader("Upload a STL:",["stl"],False)
## Streamlit layout
st.sidebar.title("STL viewer")
if uploadedFile:
stlTemp = "./temp.stl"
with open(stlTemp, "wb") as f:
f.write(uploadedFile.getbuffer())
color = st.sidebar.selectbox("Pick a color:",["white","green","blue"])
## Initialize pyvista reader and plotter
reader = pv.STLReader(stlTemp)
plotter = pv.Plotter(
border=True,
window_size=[580,400])
plotter.background_color = "white"
## Read data and send to plotter
mesh = reader.read()
plotter.add_mesh(mesh,color=color)
## Export to an external pythreejs
model_html = "model.html"
other = plotter.export_html(model_html, backend='pythreejs')
## Read the exported model
with open(model_html,'r') as file:
model = file.read()
## Show in webpage
st.components.v1.html(model,height=500)
This could be extended to all the formats that pyvista supports, namely Paraview’s vtk.
Just a little refactoring to avoid writing multiple files
import streamlit as st
import pyvista as pv
import io
import tempfile
## Using pythreejs as pyvista backend
pv.set_jupyter_backend('pythreejs')
## Upload a pyvista file
uploadedFile = st.file_uploader("Upload a STL:",["stl"],False)
## Streamlit layout
st.sidebar.title("STL viewer")
if uploadedFile:
## Color panel
col1,col2 = st.sidebar.columns(2)
color_stl = col1.color_picker("Element","#0BD88D")
color_bkg = col2.color_picker("Background","#FFFFFF")
## Initialize pyvista reader and plotter
plotter = pv.Plotter(border=False, window_size=[500,400])
plotter.background_color = color_bkg
## Create a tempfile to keep the uploaded file as pyvista's API
## only supports file paths but not buffers
with tempfile.NamedTemporaryFile(suffix="_streamlit") as f:
f.write(uploadedFile.getbuffer())
reader = pv.STLReader(f.name)
## Read data and send to plotter
mesh = reader.read()
plotter.add_mesh(mesh,color=color_stl)
## Export to a pythreejs HTML
model_html = io.StringIO()
plotter.export_html(model_html, backend='pythreejs')
## Show in webpage
st.components.v1.html(model_html.getvalue(),height=400)
Here it is on Streamlit Cloud (which to my understanding is just a Debian machine). The packages and requirements are in the repo. Hope it helps.
As per the blank page, the html file that pyvista generates with the threejs model retrieves a couple of packages that might fail to load when your browser tries to render the model. It works with those sources & requirements but something breaks with @html-manager v.1.0.3
threejs requirements that work:
<!-- Load require.js. Delete this if your page already loads require.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" integrity="sha256-Ae2Vz/4ePdIu6ZyI/5ZGsYnb+m0JlOmKPjt6XZ9JJkA=" crossorigin="anonymous"></script>
<script src="https://unpkg.com/@jupyter-widgets/html-manager@^0.20.1/dist/embed-amd.js" crossorigin="anonymous"></script>
threejs requirements that fail to load:
<!-- Load require.js. Delete this if your page already loads require.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" integrity="sha256-Ae2Vz/4ePdIu6ZyI/5ZGsYnb+m0JlOmKPjt6XZ9JJkA=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@^1.0.1/dist/embed-amd.js" crossorigin="anonymous"></script>
This might be a problem from using the latest version of ipywidgets so sticking to 7.7.1 should be fix enough for the time being.
pythreejs was deprecated from pyvista so this method will likely not work anymore. But you can check stpyvista to visualize pyvista 3D models on streamlit.