Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added links notebook #195

Merged
merged 1 commit into from
Jan 22, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
310 changes: 310 additions & 0 deletions examples/user_guide/Links.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Links parameters in panel"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the [param user guide](Param.ipynb), we have seen how parameterized classes are transformed to user interface at free cost. However in certain cases, we need more customisation over widgets automatically generated. Indeed widgets created with `widgets` modules exposed more attributes and allow more possibilities.\n",
"\n",
"In this notebook we will see how to links custom panels between them:\n",
"\n",
" - links between `Parameters` of `Parameterized` classes (most of panel inherit from `param.Parameterized`) with `link` method\n",
" - links between `Parameters` and custom functions with `watch` method"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import param\n",
"import panel as pn\n",
"pn.extension()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Links between `params` of `Parameterized` classes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this example we will link a markdown panel to a text input widget"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mkdown_pane = pn.pane.Markdown('Markdown display')\n",
"mkdown_pane"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"widget_text = pn.widgets.TextInput(value=mkdown_pane.object)\n",
"widget_text"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We verify both objects we want to link are `param.Parameterized` objects"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(isinstance(mkdown_pane, param.Parameterized), isinstance(widget_text, param.Parameterized))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Link of widget `value` attribute to the `object` attribute of the panel"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"widget_text.link(mkdown_pane, value = 'object')\n",
"widget_text.value = 'New text' #above displays should reflect change"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Accessing to available parameters using `params` method"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"widget_text.params()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Link `params` with `watch` method "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Previously we have seen how to link one to one parameters between to Parameterized classes. However value between `parameters` must be the same. Sometimes parameters are linked but values differ. In this case we will add a `watcher`. A `watcher` is a function called when the attribute is changed."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's see how to link the disabled property of a `TextInput` widget to a `ToggleButton`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"widget text creation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"widget_text = pn.widgets.TextInput(value='text', disabled=True)\n",
"widget_text"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"toggle button creation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"widget_toggle = pn.widgets.Toggle(active=False, name='Click to enable text')\n",
"widget_toggle"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We could link toggle `active` parameter to the text widget `disabled` parameter with:\n",
"```python\n",
"widget_toggle.link(widget_text, active = 'disabled')\n",
"```\n",
"However we want the opposite behavior, when toggle is `active=True` text input is enabled (`disabled=False`)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To do it we use the `watch` method of the class `parameters` to connect the toggle button to the text input"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"watcher = widget_toggle.param.watch(lambda change: setattr(widget_text, 'disabled', not change.new), 'active' )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now cliking on the toggle button enable or disable the text input"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`param.watch` return a reference to the watcher which can be used to remove it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"widget_toggle.param.unwatch(watcher)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"the two widgets are not linked anymore"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## More advance usage"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Using the `Sine` example of the [param user guide](Param.ipynb), we will create sliders with a custom step value. Indeed the default step of sliders automatically generated is 0.1 and is not always adapted."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"class Sine(param.Parameterized):\n",
"\n",
" phase = param.Number(default=0, bounds=(0, np.pi))\n",
"\n",
" frequency = param.Number(default=1, bounds=(0.1, 2))\n",
" \n",
" \n",
" def widgets(self):\n",
" phase_params = self.params()['phase']\n",
" frequency_params = self.params()['frequency']\n",
" phase_slider = pn.widgets.FloatSlider(value=phase_params.default,\n",
" start=phase_params.bounds[0],\n",
" end=phase_params.bounds[1], step=1e-2)\n",
" frequency_slider = pn.widgets.FloatSlider(value=frequency_params.default,\n",
" start=frequency_params.bounds[0],\n",
" end=frequency_params.bounds[1], step=1e-2)\n",
" phase_slider.link(self, value='phase')\n",
" frequency_slider.link(self, value='frequency')\n",
" return pn.widgets.WidgetBox(frequency_slider, phase_slider)\n",
"\n",
" @param.depends('phase', 'frequency')\n",
" def view(self):\n",
" y = np.sin(np.linspace(0, np.pi*3, 40)*self.frequency+self.phase)\n",
" y = ((y-y.min())/y.ptp())*20\n",
" array = np.array([list((' '*(int(round(d))-1) + '*').ljust(20)) for d in y])\n",
" return pn.pane.Str('\\n'.join([''.join(r) for r in array.T]), height=325, width=500)\n",
"\n",
"sine = Sine(name='ASCII Sine Wave')\n",
"pn.panel(pn.Row(sine.widgets(), sine.view))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}