Visualization of stl files

Hey everyone,

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.

I would like to display the content of the .stl file like the molecules are displayed in this example https://share.streamlit.io/napoles-uach/stl2mol/main/app.py. I would appreciate any suggestions.

Best,
Paulo

Here is an idea daisy-chaining pyvista with streamlit,component.v1.html :melting_face:

renderpyvista

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.

2 Likes

Just a little refactoring to avoid writing multiple files :nerd_face:

renderpyvista_v2

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)
2 Likes

That looks promising, thank you. Can you please share your packages.txt and requirements.txt files that are need to make this work? Thanks!

When I try to run this on Streamlit Cloud, I get a blank page after uploading the STL file. Any ideas what could be causing this? Thanks.

:link: 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

:white_check_mark: 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>

:x: 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.