Controls
Panopti supports a handful of controls elements such as buttons, sliders, color pickers, and even Plotly figures. These controls appear in the viewer UI and optionally call back into your Python code whenever the user interacts with them. The snippets below show their basic usage.
Note that these control callbacks are different from the viewer.events
handlers (see Events), which respond to built-in viewer actions like camera movement.
An example for control elements is given below. In general, control elements are defined through an (optional) Python callback function, and with a name that is used to access it later through viewer.get(name)
. The name will also serve as a display label in the frontend. The state of control elements can be retrieved with the .value()
function (see below).
Your control callback function's signature should resembles those below, e.g. for sliders:
def mycallback(viewer, value)
. All callbacks get a reference to the viewer as the first positional argument, relevant control-specific arguments follow.
import panopti
viewer = panopti.connect(server_url='http://localhost:8080', viewer_id='client')
def callback_submit_button(viewer):
# User clicked submit, let's run a compute job
# update label:
label = viewer.get('compute_label')
label.update('Running job...')
extra_fancy = viewer.get('Extra fancy').value() # grab the current checkbox value
result = run_fancy_calculation(extra_fancy=extra_fancy)
label.update('Done! Results: ', results)
viewer.button(callback=callback_submit_button, name='Submit')
# Add a checkbox that modifies our function above, no callback needed
viewer.checkbox(callback=None, name='Extra Fancy')
# Add a label that is updated when our job is complete
viewer.label(callback=None, name='compute_label', text='Waiting...')
viewer.hold()
Available control elements:
Button
Button
A simple button with on-click callbacks.
Slider
Slider
A slider with on-change callbacks. Supports manual expression entry in viewer and has increment/decrement buttons (controlled by step
parameter).
Label
Label
A label that supports markdown text. Its callback behaves differently compared to the other control elements -- a label's callback will be triggered when the label is updated, e.g. by calling viewer.get('MyLabel').update('updated text here...')
Checkbox
Checkbox
A checkbox with on-change callbacks.
Dropdown
Dropdown
A dropdown menu with on-change callbacks.
Color Picker
Color Picker
A color picker with on-change callbacks.
initial
expects an RGBA color.
Download Button
Download Button
A special button wrapper that allows user code to send arbitrary file downloads to the browser on click. The defined callback must return a bytes
object, which represents the binary content of the file to be downloaded. In the example below, f.read()
returns the contents of the in-memory file-like object (io.BytesIO
) as a bytes
object. This binary data is then sent to the browser for download when the button the clicked. For example, push an .obj
file download to your viewer:
import io, numpy as np, trimesh
def download_mesh_callback(viewer):
tm = trimesh.Trimesh(vertices=verts, faces=faces, process=False)
f = io.BytesIO()
tm.export(file_obj=f, file_type='obj') # write to BytesIO object
f.seek(0)
return f.read()
viewer.download_button(callback=download_mesh_callback,
name="Download Mesh",
filename="mesh.obj")
Plotly figure
Plotly figure
You can embed interactive Plotly figures into the viewer as well. Below we customize a Plotly figure in Python, then send its JSON schematic to the viewer. Currently Plotly elements do not support callbacks. Of course, this functionality requires Plotly: pip install plotly==5.22.0
.
import plotly.graph_objects as go
fig = go.Figure(...)
# ... define figure here ...
viewer.add_plotly(fig.to_plotly_json(), name='Histogram')
Warning
Some versions of Plotly seem to misbehave with this functionality. We recommend using version plotly==5.22.0
.