- Interact functions: Auto-generates a full UI (including widgets) given a function
- Reactive functions: Linking functions or methods to widgets using pn.bind or the equivalent pn.depends decorator, declaring that the function should be re-run when those widget values change
- Parameterized class: Declare parameters and their ranges in Parameterized classes, then get GUIs (and value checking!) for free
- Callbacks: Generate a UI by manually declaring callbacks that update panels or panes
First we need dataset autompg.
import hvplot.pandas
from bokeh.sampledata.autompg import autompg
def autompg_plot(x='mpg', y='hp', color='#058805'):
return autompg.hvplot.scatter(x, y, c=color, padding=0.1)
columns = list(autompg.columns[:-2])
autompg_plot()
To control the color and widgets, we use panel components to manipulate.
Reactive Functions
Pros
- Very clear mapping from widgets to the arguments of the function.
- Like interact, doesn’t typically require modifying existing visualization code.
Cons
Typically requires a bit more code than interact.
pn.bind()
helps bind specific arguments to a function.
def fn(a,b): return f'Arguments: {a,b}'
slider = pn.widgets.FloatSlider(value=0.5)
bound_fn = pn.bind(fn, a=slider, b=2)
bound_fn()
pn.Row(slider, bound_fn)
If you are writing code specifically for building an app, and do not wish to keep domain and GUI code separate, the functionality of pn.bind is also available as a decorator @pn.depends
:
x = pn.widgets.Select(value='mpg', options=columns, name='x')
y = pn.widgets.Select(value='hp', options=columns, name='y')
color = pn.widgets.ColorPicker(name='Color', value='#AA0505')
@pn.depends(x, y, color)
def plot(xval, yval, colorval):
return autompg.hvplot.scatter(xval, yval, c=colorval)
pn.Row(
pn.Column('## MPG Explorer', x, y, color),
plot
)
pn.bind()
is preferred, because it it allows you to keep the Panel-specific code separate.
Interact Functions
Pros
Easy to use.
Parameterized Classes
Pros:
Declarative way of expressing parameters and dependencies between parameters and computation
The resulting code is not tied to any particular GUI framework and can be used in other contexts as well
Cons:
Requires writing classes
Less explicit about widgets to use for each parameter; can be harder to customize behavior than if widgets are instantiated explicitly
import param
class MPGExplorer(param.Parameterized):
x = param.Selector(objects=columns)
y = param.Selector(default='hp', objects=columns)
color = param.Color(default='#0f0f0f')
@param.depends('x', 'y', 'color') # optional in this case
def plot(self):
return autompg_plot(self.x, self.y, self.color)
explorer = MPGExplorer()
pn.Row(explorer.param, explorer.plot)
Callbacks
Pros:
Complete and modular control over specific events
Cons:
Complexity grows very quickly with the number of callbacks
Have to handle initializing the plots separately
color = pn.widgets.ColorPicker(name='Color', value='#880588')
layout = pn.Row(
pn.Column('## MPG Explorer', x, y, color),
autompg_plot(x.value, y.value, color.value))
def update(event):
layout[1].object = autompg_plot(x.value, y.value, color.value)
x.param.watch(update, 'value')
y.param.watch(update, 'value')
color.param.watch(update, 'value')
layout