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

Updated the Responding to Events guide with streams dictionary examples #4822

Merged
merged 7 commits into from
Feb 14, 2021
Merged
Changes from 4 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
114 changes: 96 additions & 18 deletions examples/user_guide/12-Responding_to_Events.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"source": [
"The core concept behind a stream is simple: it defines one or more parameters that can change over time that automatically refreshes code depending on those parameter values. \n",
"\n",
"Like all objects in HoloViews, these parameters are declared using [param](https://ioam.github.io/param) and streams are defined as a parameterized subclass of the ``holoviews.streams.Stream``. A more convenient way is to use the ``Stream.define`` classmethod:"
"Like all objects in HoloViews, these parameters are declared using [param](https://param.holoviz.org/) and streams are defined as a parameterized subclass of the ``holoviews.streams.Stream``. A more convenient way is to use the ``Stream.define`` classmethod:"
]
},
{
Expand Down Expand Up @@ -335,7 +335,7 @@
"source": [
"## Using Parameterized classes as a stream\n",
"\n",
"Creating a custom ``Stream`` class is one easy way to declare parameters, however in many cases you may have already expressed your domain knowledge on a ``Parameterized`` class. A ``DynamicMap`` can easily be linked to the parameters of the class using a so called ``Params`` stream, let's define a simple example which will let use dynamically alter the style applied to the ``Image`` from the previous example. We define a ``Style`` class with two parameters, one to control the colormap and another to vary the number of color levels and then use the `.apply` accessor to set those options:"
"Creating a custom ``Stream`` class is one easy way to declare parameters, however in many cases you may have already expressed your domain knowledge on a ``Parameterized`` class. Here is a simple parameterized `BankAccount` class:\n"
jlstevens marked this conversation as resolved.
Show resolved Hide resolved
]
},
{
Expand All @@ -344,26 +344,77 @@
"metadata": {},
"outputs": [],
"source": [
"from holoviews.streams import Params\n",
"class BankAccount(param.Parameterized):\n",
" balance = param.Number(default=0, doc=\"Bank balance in USD\")\n",
" overdraft = param.Number(default=200, doc=\"Overdraft limit\")\n",
"\n",
"class Style(param.Parameterized):\n",
"\n",
" cmap = param.ObjectSelector(default='viridis', objects=['viridis', 'plasma', 'magma'])\n",
"\n",
" color_levels = param.Integer(default=255, bounds=(1, 255))\n",
"\n",
"style = Style()\n",
"account = BankAccount(balance=300) # Jane's instance"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can link parameter changes straight to DynamicMap callable parameters using the streams dictionary format (HoloViews version >= 1.14.2):"
jlstevens marked this conversation as resolved.
Show resolved Hide resolved
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"bank_dmap = hv.DynamicMap(lambda total, overdraft: hv.Table({'balance':['$%s' % total],\n",
" 'overdraft limit':['$%s' % overdraft]}, \n",
" ['balance', 'overdraft limit']), \n",
" streams=dict(total=account.param.balance, overdraft=account.param.overdraft))\n",
"bank_dmap.opts(height=100, xaxis=None, yaxis=None, title=\"Jane's bank account\")"
jlstevens marked this conversation as resolved.
Show resolved Hide resolved
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now is you set the `balance` parameter on the `janes_account` insteance, the DynamicMap above updates. Note that the dictionary specifies that the `balance` parameter is mapped to the `total` argument of the callable."
jlstevens marked this conversation as resolved.
Show resolved Hide resolved
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"account.balance=65.4\n",
"account.overdraft=350"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Use with `panel`\n",
"\n",
"stream = Params(style)\n",
"This dictionary format is particularly useful when used with the [Panel](http://panel.pyviz.org/) library (a dependency of HoloViews that should always be available) as `panel` widgets always reflect their values on the `value` parameter. This means that if you declare two panel widgets as follows:"
jlstevens marked this conversation as resolved.
Show resolved Hide resolved
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import panel as pn\n",
"\n",
"image.apply.opts(streams=[stream]).opts(colorbar=True, width=400)"
"slider = pn.widgets.FloatSlider(start=0, end=500, name='Balance')\n",
"checkbox = pn.widgets.Select(options=['student','regular', 'savings'], name='Account Type')\n",
"pn.Row(slider, checkbox)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Using the `.apply` accessor in this automatically makes resulting `DynamicMap` depend on the streams. Unlike a regular streams class the plot will update whenever a parameter on the instance or class changes, e.g. we can update set the ``cmap`` and ``color_level`` parameters and watch the plot update in response:"
"You can map both widget values into a `DynamicMap` callback without having a name clash as follows:"
]
},
{
Expand All @@ -372,15 +423,25 @@
"metadata": {},
"outputs": [],
"source": [
"style.color_levels = 10\n",
"style.cmap = 'plasma'"
"overdraft_limits = {'student':300, 'regular':100, 'savings':0} # Overdraft limits for different account types\n",
"widget_dmap = hv.DynamicMap(lambda total, acc: hv.Table({'account type' : [acc],\n",
" 'balance':['$%s' % total],\n",
" 'overdraft limit':['$%s' % overdraft_limits[acc]]}, \n",
" ['account type', 'balance', 'overdraft limit']), \n",
" streams=dict(total=slider.param.value, acc=checkbox.param.value))\n",
"widget_dmap.opts(height=100, xaxis=None, yaxis=None, title=\"Jane's bank account\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is also possible to be even more explicit and directly map parameters to `.apply` keywords without manually constructing a stream, e.g. the example may also be written as:"
"\n",
"You can now update the plot above using the slider and dropdown widgets. Note that for all these examples, a `Params` stream is created internally. This type of stream can wrap parameterized objects or sets of parameters but it is rare that it needs to be used directly at the user level (though this was necessary in HoloViews < 1.10.8). To see more examples of how to use `panel` with HoloViews, see the [Dashboards user guide](./16-Dashboards.ipynb).\n",
jlstevens marked this conversation as resolved.
Show resolved Hide resolved
"\n",
"### Using `.apply.opts`\n",
"\n",
"You can supplying parameters in a similar manner to the `.apply.opts` method. In the following example, a `Style` class has parameters that indicate the desired colorma and color levels for the `image` instance defined earlier. We can link these together as follows:"
jlstevens marked this conversation as resolved.
Show resolved Hide resolved
]
},
{
Expand All @@ -389,14 +450,31 @@
"metadata": {},
"outputs": [],
"source": [
"image.apply.opts(cmap=style.param.cmap, color_levels=style.param.color_levels, colorbar=True, width=400)"
"class Style(param.Parameterized):\n",
"\n",
" colormap = param.ObjectSelector(default='viridis', objects=['viridis', 'plasma', 'magma'])\n",
"\n",
" color_levels = param.Integer(default=255, bounds=(1, 255))\n",
"\n",
"style = Style()\n",
"image.apply.opts(colorbar=True, width=400, cmap=style.param.colormap, color_levels=style.param.color_levels)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is a powerful pattern to link parameters to a plot, particularly when combined with the [Panel](http://panel.pyviz.org/) library, which makes it easy to generate a set of widgets from a Parameterized class. To see how this works in practice see the [Dashboards user guide](./16-Dashboards.ipynb)."
"Using the `.apply` accessor in this automatically makes resulting `DynamicMap` depend on the streams specified by the parameters. Unlike a regular streams class the plot will update whenever a parameter on the instance or class changes, e.g. we can update set the ``cmap`` and ``color_level`` parameters and watch the plot update in response:"
jlstevens marked this conversation as resolved.
Show resolved Hide resolved
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"style.color_levels = 10\n",
"style.colormap = 'plasma' # Note that this is mapped to the 'cmap' keyword in .apply.opts"
]
},
{
Expand Down