I am having trouble plotting the 3D voxels through streamlit. I am able to plot it using matplotlib in jupyter notebook but I am not sure how to translate that to streamlit.
This is the code snippet I am using to plot voxels in matplotlib:
volume is a 3 dimesional tensor
volume = generated_volume.reshape(32,32,32)
%matplotlib notebook
fig = plt.figure()
ax = fig.gca(projection=‘3d’)
#ax.set_aspect(‘equal’)
volume = volume.squeeze().ge(0.5)
ax.voxels(volume, edgecolor=“k”)
ax.view_init(30, 240)
plt.show()
Hello and welcome to the forums @sidhartha 
You should use st.pyplot() in place of plt.show()
to show the plot in Streamlit.
Since I don’t have a generated_volume
variable, I rebuilt an example with data from matplotlib’s help where I cache some voxel data, display it on matplotlib and use Streamlit sliders to rotate axis without recomputing the data each time you interact with the slider. You can put this into an app.py
script and run streamlit run app.py
to see the results.
"""From https://matplotlib.org/3.1.0/gallery/mplot3d/voxels.html in Streamlit"""
import matplotlib.pyplot as plt
import numpy as np
import streamlit as st
# This import registers the 3D projection, but is otherwise unused.
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
@st.cache
def generate_data():
"""Let's put the data in cache so it doesn't reload each time we rerun the script when modifying the slider"""
# prepare some coordinates
x, y, z = np.indices((8, 8, 8))
# draw cuboids in the top left and bottom right corners, and a link between them
cube1 = (x < 3) & (y < 3) & (z < 3)
cube2 = (x >= 5) & (y >= 5) & (z >= 5)
link = abs(x - y) + abs(y - z) + abs(z - x) <= 2
# combine the objects into a single boolean array
voxels = cube1 | cube2 | link
colors = np.empty(voxels.shape, dtype=object)
colors[link] = 'red'
colors[cube1] = 'blue'
colors[cube2] = 'green'
return voxels, colors
voxels, colors = generate_data()
# let's put sliders to modify view init, each time you move that the script is rerun, but voxels are not regenerated
# TODO : not sure that's the most optimized way to rotate axis but well, demo purpose
azim = st.sidebar.slider("azim", 0, 90, 30, 1)
elev = st.sidebar.slider("elev", 0, 360, 240, 1)
# and plot everything
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.voxels(voxels, facecolors=colors, edgecolor='k')
ax.view_init(azim, elev)
st.pyplot()
1 Like
Thanks a lot for your reply @andfanilo. Your code works quite well. The only thing is that I have to toggle is the angle toggle bars to visualize the plot. However, this is a very good solution for now.
1 Like