Skip to content
This repository has been archived by the owner on Nov 28, 2019. It is now read-only.

Add a show_widgets option #76

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
199 changes: 167 additions & 32 deletions doc/AdditionalFeatures.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"import param\n",
Expand All @@ -24,9 +22,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"class TooltipExample(param.Parameterized):\n",
Expand All @@ -36,9 +32,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"paramnb.Widgets(TooltipExample)"
Expand All @@ -56,9 +50,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"class Location(param.Parameterized):\n",
Expand All @@ -75,9 +67,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"paramnb.Widgets(Task)"
Expand All @@ -86,9 +76,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"Task.employee.location.duration"
Expand All @@ -113,9 +101,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
Expand All @@ -125,9 +111,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"class HTMLExample(param.Parameterized):\n",
Expand Down Expand Up @@ -155,9 +139,7 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"import holoviews as hv\n",
Expand Down Expand Up @@ -187,13 +169,166 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
"source": [
"### Alternate display outputs \n",
"\n",
"You can alter the output of the widget using the \"`display_type`\" option which is set to `'widgets'` by default. \n",
"\n",
"Widgets options can be displayed as text by setting `display_type` to `'text'` or as a table with `'table'`, which may be useful for batch runs.\n",
"\n",
"#### Suppressing display output\n",
"\n",
"You can also suppress the output entirely by setting the `display_type` option to `None`. \n",
"\n",
"For example, you can add the ParamNB widgets (Which themselves are constructed of and contained in `ipywidgets` containers) inside an `ipywidgets` Tabs container to create an interface that combines usage of paramnb widgets with some unrelated, regular `ipywidgets`:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "cb50446444b74a0bb4135affbbaf6a80",
"version_major": 2,
"version_minor": 0
},
"text/html": [
"<p>Failed to display Jupyter Widget of type <code>Tab</code>.</p>\n",
"<p>\n",
" If you're reading this message in Jupyter Notebook or JupyterLab, it may mean\n",
" that the widgets JavaScript is still loading. If this message persists, it\n",
" likely means that the widgets JavaScript library is either not installed or\n",
" not enabled. See the <a href=\"https://ipywidgets.readthedocs.io/en/stable/user_install.html\">Jupyter\n",
" Widgets Documentation</a> for setup instructions.\n",
"</p>\n",
"<p>\n",
" If you're reading this message in another notebook frontend (for example, a static\n",
" rendering on GitHub or <a href=\"https://nbviewer.jupyter.org/\">NBViewer</a>),\n",
" it may mean that your frontend doesn't currently support widgets.\n",
"</p>\n"
],
"text/plain": [
"Tab(children=(VBox(children=(HTML(value='\\n <style>\\n .widget-dropdown .dropdown-menu { width: 100% }\\n .widget-select-multiple select { min-height: 100px; min-width: 300px;}\\n </style>\\n <div class=\"ttip\"><b>HiddenExample</b></div>'), HBox(children=(HTML(value='<div title=\"\" style=\"padding: 5px; width: 67px;\\n text-align: right;\">color</div>'), ColorPicker(value='#000000'))), HBox(children=(HTML(value='<div title=\"\" style=\"padding: 5px; width: 67px;\\n text-align: right;\">num_range</div>'), FloatSlider(value=1.0, continuous_update=False, max=10.0))))), Text(value='', description='A Text Widget')), _titles={'0': 'ParamNB Widgets', '1': 'Non-ParamNB Widgets'})"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"\n",
" var num = 1;\n",
" var run = false;\n",
" var current = $(this)[0];\n",
" $.each(IPython.notebook.get_cells(), function (idx, cell) {\n",
" if ((cell.output_area === current) && !run) {\n",
" run = true;\n",
" } else if ((cell.cell_type == 'code') && !(num < 1) && run) {\n",
" cell.execute();\n",
" num = num - 1;\n",
" }\n",
" });\n",
" "
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"\n",
" var num = 1;\n",
" var run = false;\n",
" var current = $(this)[0];\n",
" $.each(IPython.notebook.get_cells(), function (idx, cell) {\n",
" if ((cell.output_area === current) && !run) {\n",
" run = true;\n",
" } else if ((cell.cell_type == 'code') && !(num < 1) && run) {\n",
" cell.execute();\n",
" num = num - 1;\n",
" }\n",
" });\n",
" "
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Import ipywidgets\n",
"import ipywidgets\n",
"\n",
"# Declare a parameterized class with a number range slider parameter\n",
"class HiddenExample(param.Parameterized):\n",
" \n",
" num_range = param.Number(1, bounds=(0, 10))\n",
" color = param.Color(default='#000000', precedence=0)\n",
"\n",
"# Instantiate the ParamNB Widgets\n",
"opts_widgets = paramnb.Widgets.instance()\n",
"\n",
"# Use the parameterized class and set the show_widgets option to None to hide the paramnb widget display\n",
"opts_widgets(HiddenExample, next_n=1, display_type=None)\n",
"\n",
"# Select the internal paramNB ipython widgets\n",
"param_nb_widgets = opts_widgets.widgets()[0]\n",
"\n",
"# Create the ipywidgets tabs and add a tab containing the paramNB widgets\n",
"tabs = ipywidgets.Tab()\n",
"tabs.children = [ipywidgets.VBox(children=param_nb_widgets), ipywidgets.Text(description='A Text Widget')]\n",
"\n",
"# Set the Tab titles\n",
"tabs.set_title(0, 'ParamNB Widgets')\n",
"tabs.set_title(1, 'Non-ParamNB Widgets')\n",
"\n",
"# Display the tabs\n",
"display(tabs)"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.6"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Output Range Slider Value\n",
"HiddenExample.num_range"
]
}
],
"metadata": {
Expand All @@ -212,7 +347,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.0"
"version": "3.6.3"
}
},
"nbformat": 4,
Expand Down
51 changes: 49 additions & 2 deletions paramnb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ class Widgets(param.ParameterizedFunction):
If true, will continuously update the next_n and/or callback,
if any, as a slider widget is dragged.""")

display_type = param.ObjectSelector(default='widgets',
objects=['widgets', 'text', 'table', None],
doc="""
Format to use for displaying the parameter. By default will output widgets.
Other options: 'table', 'text', or None to suppress ouput of widgets.""")

def __call__(self, parameterized, **params):
self.p = param.ParamOverrides(self, params)
if self.p.initializer:
Expand All @@ -139,6 +145,9 @@ def __call__(self, parameterized, **params):
self._widgets = {}
self.parameterized = parameterized

# Placeholder for widget information for alt display types
self.display_rows = ''

widgets, views = self.widgets()
layout = ipywidgets.Layout(display='flex', flex_flow=self.p.layout)
if self.p.close_button:
Expand All @@ -155,10 +164,40 @@ def __call__(self, parameterized, **params):
box = ipywidgets.VBox if layout in ['below', 'above'] else ipywidgets.HBox
widget_box = box(children=children)

display(Javascript(WIDGET_JS))
display(widget_box)
self._widget_box = widget_box

# Manage display type for widgets
if self.p.display_type is 'widgets':
display(Javascript(WIDGET_JS))
display(widget_box)
if (self.p.display_type is 'text'):
display(ipywidgets.HTML(
'<h4>' + self.parameterized.name + '</h4>' +
self.display_rows
))
elif self.p.display_type is 'table':

table_styles = """
<style>
.paramnb_display_table { border:1px solid grey; border-collapse: collapse;}
.paramnb_display_table th {font-weight:bold;}
.paramnb_display_table th, .paramnb_display_table td {padding:5px; border: 1px solid #ccc;}
.paramnb_display_table tr:nth-child(even) {background-color: #eee;}
</style>
"""

display(ipywidgets.HTML(
table_styles +
'<table class="paramnb_display_table">'+
'<tr><td colspan="5"><h4>' + self.parameterized.name + '</h4></td></tr>'
'<tr><th>Parameter</th><th>Value</th><th>Param Type</th><th>Widget Class</th><th>Description</th></tr>'+
self.display_rows +
'</table>'
))

elif self.p.display_type is None:
pass

for view in views:
p_obj = self.parameterized.params(view.name)
value = getattr(self.parameterized, view.name)
Expand Down Expand Up @@ -191,6 +230,14 @@ def _make_widget(self, p_name):
widget_class = wtype(p_obj)

value = getattr(self.parameterized, p_name)
p_type = type(p_obj).__name__

# Populate alt display outputs for text and table
if self.p.display_type is 'text':
self.display_rows += '<b>Name:</b> {0}, <b>Value:</b> {1}, <b>Param Type:</b> {2}, <b>Widget Class:</b> {3}, <b>Description:</b> {4} </br>'.format(p_name, value, p_type, widget_class.__name__, p_obj.doc)

elif self.p.display_type is 'table':
self.display_rows += '<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>'.format(p_name, value, p_type, widget_class.__name__, p_obj.doc)

# For ObjectSelector, pick first from objects if no default;
# see https://github.com/ioam/param/issues/164
Expand Down