From 887831e72b0735ace1cba1101512488f3c506fbe Mon Sep 17 00:00:00 2001 From: Orestis Herodotou Date: Wed, 13 Dec 2017 12:41:11 -0800 Subject: [PATCH 1/3] Add 'show_widgets' option --- paramnb/__init__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/paramnb/__init__.py b/paramnb/__init__.py index 6d52196..76c6086 100644 --- a/paramnb/__init__.py +++ b/paramnb/__init__.py @@ -131,6 +131,9 @@ class Widgets(param.ParameterizedFunction): If true, will continuously update the next_n and/or callback, if any, as a slider widget is dragged.""") + show_widgets = param.Boolean(default=True, doc=""" + Whether to immediately output the display of the ipython widget""") + def __call__(self, parameterized, **params): self.p = param.ParamOverrides(self, params) if self.p.initializer: @@ -155,8 +158,10 @@ 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) + if self.p.show_widgets: + display(Javascript(WIDGET_JS)) + display(widget_box) + self._widget_box = widget_box for view in views: From bffdea498f1e4a197169e09e009441090606c7a4 Mon Sep 17 00:00:00 2001 From: Orestis Herodotou Date: Wed, 13 Dec 2017 12:43:51 -0800 Subject: [PATCH 2/3] Add 'show_widgets' example to Additional Features example notebook --- doc/AdditionalFeatures.ipynb | 63 ++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/doc/AdditionalFeatures.ipynb b/doc/AdditionalFeatures.ipynb index 7483b96..365dbe8 100644 --- a/doc/AdditionalFeatures.ipynb +++ b/doc/AdditionalFeatures.ipynb @@ -186,6 +186,69 @@ "paramnb.Widgets(example, callback=example.update, on_init=True, view_position='right')" ] }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "## Hiding widgets display\n", + "\n", + "You may choose to suppress the output of the widget using the \"`show_widgets`\" option which is set to `True` by default. \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. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "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 False to hide the paramnb widget display\n", + "opts_widgets(HiddenExample, next_n=1, show_widgets=False)\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": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Output Range Slider Value\n", + "HiddenExample.num_range" + ] + }, { "cell_type": "code", "execution_count": null, From 284d5ff3b0e9d402c4224290eebdc44463aeb388 Mon Sep 17 00:00:00 2001 From: Orestis Herodotou Date: Thu, 21 Dec 2017 12:56:42 -0800 Subject: [PATCH 3/3] Add additional display options: text, table --- doc/AdditionalFeatures.ipynb | 176 ++++++++++++++++++++++++----------- paramnb/__init__.py | 52 ++++++++++- 2 files changed, 171 insertions(+), 57 deletions(-) diff --git a/doc/AdditionalFeatures.ipynb b/doc/AdditionalFeatures.ipynb index 365dbe8..59c8124 100644 --- a/doc/AdditionalFeatures.ipynb +++ b/doc/AdditionalFeatures.ipynb @@ -3,9 +3,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "import param\n", @@ -24,9 +22,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "class TooltipExample(param.Parameterized):\n", @@ -36,9 +32,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "paramnb.Widgets(TooltipExample)" @@ -56,9 +50,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "class Location(param.Parameterized):\n", @@ -75,9 +67,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "paramnb.Widgets(Task)" @@ -86,9 +76,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "Task.employee.location.duration" @@ -113,9 +101,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", @@ -125,9 +111,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "class HTMLExample(param.Parameterized):\n", @@ -155,9 +139,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "import holoviews as hv\n", @@ -192,20 +174,110 @@ "collapsed": true }, "source": [ - "## Hiding widgets display\n", + "### 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", - "You may choose to suppress the output of the widget using the \"`show_widgets`\" option which is set to `True` by default. \n", + "#### Suppressing display output\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. " + "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": null, - "metadata": { - "collapsed": true - }, - "outputs": [], + "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": [ + "

Failed to display Jupyter Widget of type Tab.

\n", + "

\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 Jupyter\n", + " Widgets Documentation for setup instructions.\n", + "

\n", + "

\n", + " If you're reading this message in another notebook frontend (for example, a static\n", + " rendering on GitHub or NBViewer),\n", + " it may mean that your frontend doesn't currently support widgets.\n", + "

\n" + ], + "text/plain": [ + "Tab(children=(VBox(children=(HTML(value='\\n \\n
HiddenExample
'), HBox(children=(HTML(value='
color
'), ColorPicker(value='#000000'))), HBox(children=(HTML(value='
num_range
'), 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": [ + "" + ] + }, + "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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Import ipywidgets\n", "import ipywidgets\n", @@ -219,8 +291,8 @@ "# Instantiate the ParamNB Widgets\n", "opts_widgets = paramnb.Widgets.instance()\n", "\n", - "# Use the parameterized class and set the show_widgets option to False to hide the paramnb widget display\n", - "opts_widgets(HiddenExample, next_n=1, show_widgets=False)\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", @@ -239,24 +311,24 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], + "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" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] } ], "metadata": { @@ -275,7 +347,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.0" + "version": "3.6.3" } }, "nbformat": 4, diff --git a/paramnb/__init__.py b/paramnb/__init__.py index 76c6086..2b2d638 100644 --- a/paramnb/__init__.py +++ b/paramnb/__init__.py @@ -131,8 +131,11 @@ class Widgets(param.ParameterizedFunction): If true, will continuously update the next_n and/or callback, if any, as a slider widget is dragged.""") - show_widgets = param.Boolean(default=True, doc=""" - Whether to immediately output the display of the ipython widget""") + 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) @@ -142,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: @@ -158,11 +164,39 @@ def __call__(self, parameterized, **params): box = ipywidgets.VBox if layout in ['below', 'above'] else ipywidgets.HBox widget_box = box(children=children) - if self.p.show_widgets: + self._widget_box = widget_box + + # Manage display type for widgets + if self.p.display_type is 'widgets': display(Javascript(WIDGET_JS)) display(widget_box) - - self._widget_box = widget_box + if (self.p.display_type is 'text'): + display(ipywidgets.HTML( + '

' + self.parameterized.name + '

' + + self.display_rows + )) + elif self.p.display_type is 'table': + + table_styles = """ + + """ + + display(ipywidgets.HTML( + table_styles + + ''+ + '' + ''+ + self.display_rows + + '

' + self.parameterized.name + '

ParameterValueParam TypeWidget ClassDescription
' + )) + + elif self.p.display_type is None: + pass for view in views: p_obj = self.parameterized.params(view.name) @@ -196,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 += 'Name: {0}, Value: {1}, Param Type: {2}, Widget Class: {3}, Description: {4}
'.format(p_name, value, p_type, widget_class.__name__, p_obj.doc) + + elif self.p.display_type is 'table': + self.display_rows += '{0}{1}{2}{3}{4}'.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