diff --git a/doc/AdditionalFeatures.ipynb b/doc/AdditionalFeatures.ipynb index 7483b96..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", @@ -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": [ + "

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", + "\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": { @@ -212,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 6d52196..2b2d638 100644 --- a/paramnb/__init__.py +++ b/paramnb/__init__.py @@ -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: @@ -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: @@ -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( + '

' + 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) value = getattr(self.parameterized, view.name) @@ -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 += '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