Skip to content

Commit

Permalink
Add throttled argument to pn.param widgets parameter (#1800)
Browse files Browse the repository at this point in the history
* Adding throttled to param

* Moved throttled to widgets argument

* Added value_throttled to updates

* Added unittest

* More clear seperation if widget is throttled or not

* Added documentation
  • Loading branch information
hoxbro committed Dec 10, 2020
1 parent 0b62f7a commit f01a739
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
45 changes: 44 additions & 1 deletion examples/reference/panes/Param.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Model building\n",
"Let's build a model of a cycling Athlete and her PowerCurve. \n",
"\n",
"The PowerCurve is a recording of her maximum power output in Watt per kg for fixed durations of time."
Expand Down Expand Up @@ -325,12 +326,54 @@
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Disabling continuous updates for slider widgets\n",
"When a function takes a long time to run and depends on a parameter, realtime feedback can be a burden instead of being helpful.\n",
"\n",
"Therefore if a slider widget is used for a parameter and you have a function which takes long time to calculate, you can set the `throttled` keyword in the `panel.param.widgets` to `True` for the given parameter. This will then first run the function after the release of the mouse button of the slider.\n",
"\n",
"An example can be seen below where two parameters is connected to two sliders, one with and one without `throttled` enabled."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
"source": [
"class A(param.Parameterized):\n",
" without_throttled_enabled = param.Range(\n",
" default=(100, 250),\n",
" bounds=(0, 250),\n",
" )\n",
"\n",
" with_throttled_enabled = param.Range(\n",
" default=(100, 250),\n",
" bounds=(0, 250),\n",
" )\n",
"\n",
" def __init__(self, **params):\n",
" super().__init__(**params)\n",
" widgets = {\n",
" \"without_throttled_enabled\": pn.widgets.IntRangeSlider,\n",
" \"with_throttled_enabled\": {\n",
" \"type\": pn.widgets.IntRangeSlider,\n",
" \"throttled\": True,\n",
" },\n",
" }\n",
" self.controls = pn.Param(self, widgets=widgets)\n",
"\n",
" @param.depends(\"controls\")\n",
" def calculation(self):\n",
" return self.without_throttled_enabled, self.with_throttled_enabled\n",
"\n",
"\n",
"a = A()\n",
"pn.Column(a.controls, a.calculation)"
]
}
],
"metadata": {
Expand Down
4 changes: 4 additions & 0 deletions panel/param.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ def event(change):
def action(change):
value(self.object)
watcher = widget.param.watch(action, 'clicks')
elif kw_widget.get('throttled', False) and hasattr(widget, 'value_throttled'):
watcher = widget.param.watch(link_widget, 'value_throttled')
else:
watcher = widget.param.watch(link_widget, 'value')
watchers.append(watcher)
Expand Down Expand Up @@ -462,6 +464,8 @@ def action(event):
idx = self._callbacks.index(prev_watcher)
self._callbacks[idx] = watchers[0]
return
elif kw_widget.get('throttled', False) and hasattr(widget, 'value_throttled'):
updates['value_throttled'] = change.new
else:
updates['value'] = change.new

Expand Down
41 changes: 41 additions & 0 deletions panel/tests/test_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,47 @@ class Test(param.Parameterized):
assert number.height == 100
assert isinstance(text, TextInput)


def test_set_widgets_throttled(document, comm):
class Test(param.Parameterized):
a = param.Number(default=0, bounds=(0, 10), precedence=1)

test = Test()
pane = Param(test)
model = pane.get_root(document, comm=comm)

pane.widgets = {"a": {"throttled": False}}
assert len(model.children) == 2
_, number = model.children

number.value = 1
assert number.value == 1
assert number.value_throttled != 1
assert test.a == 1

test.a = 2
assert number.value == 2
assert number.value_throttled != 2
assert test.a == 2

# By setting throttled to true,
# `test.a` is linked to `number.value_throttled`
# instead of `number.value`.
pane.widgets = {"a": {"throttled": True}}
assert len(model.children) == 2
_, number = model.children

number.value_throttled = 3
assert number.value != 3
assert number.value_throttled == 3
assert test.a == 3

test.a = 4
assert number.value != 4
assert number.value_throttled == 4
assert test.a == 4


def test_set_show_name(document, comm):
class Test(param.Parameterized):
a = param.Number(bounds=(0, 10))
Expand Down

0 comments on commit f01a739

Please sign in to comment.