Skip to content

Controls

Controls Preview 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.

def my_button_callback(viewer):
    print('MyButton was pressed!')

viewer.button(callback=my_button_callback, name='MyButton')

Slider
Slider

A slider with on-change callbacks. Supports manual expression entry in viewer and has increment/decrement buttons (controlled by step parameter).

def my_slider_callback(viewer, val):
    print(f"MySlider was set to: {val}!")

viewer.slider(callback=my_slider_callback, 
            name='MySlider', 
            min=0.0, 
            max=1.0, 
            initial=0.0, 
            step=0.01, 
            description='Your optional description here')

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...')

def my_label_callback(viewer):
    print(f"This callback is triggered when MyLabel is updated.")

viewer.label(callback=my_label_callback,
             name='MyLabel', 
             text='I support **markdown**!')

Checkbox
Checkbox

A checkbox with on-change callbacks.

def my_checkbox_callback(viewer, val):
    print(f"MyCheckbox was set to: {val}!")

viewer.checkbox(callback=my_checkbox_callback, 
                name='MyCheckbox', 
                initial=True)

Dropdown

A dropdown menu with on-change callbacks.

def my_dropdown_callback(viewer, val):
    print(f"MyDropdown was set to: {val}!")

viewer.dropdown(callback=my_dropdown_callback, 
                name='MyDropdown', 
                options=['Option 1', 'Option 2', 'Option 3'], 
                initial=0)

Color Picker
Color Picker

A color picker with on-change callbacks.

initial expects an RGBA color.

def my_color_picker_callback(viewer, color):
    print(f"Color picked (in RGBA): {color}")

viewer.color_picker(callback=my_color_picker_callback, 
                    name='MyColorPicker', 
                    initial=(0.5, 0.5, 0.5, 1.0))

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.