diff --git a/examples/Interactive Widgets/Using Interact.ipynb b/examples/Interactive Widgets/Using Interact.ipynb index 7190534..e6312f8 100644 --- a/examples/Interactive Widgets/Using Interact.ipynb +++ b/examples/Interactive Widgets/Using Interact.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:3f30c6e839ac39f890da34a2af6bf50bf0d99ea32f7aadc043f3e31f619e4bc9" + "signature": "sha256:6d8c7c51322c4911e478068e8fa8e897bd72c614096f5df110ed86d01d66001c" }, "nbformat": 3, "nbformat_minor": 0, @@ -13,14 +13,14 @@ "level": 1, "metadata": {}, "source": [ - "Interact" + "Using Interact" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The `interact` function provides a high-level interface for creating user interface controls to use in exploring code and data interactively." + "The `interact` function (`IPython.html.widgets.interact`) automatically creates user interface (UI) controls for exploring code and data interactively. It is the easiest way to get started using IPython's widgets." ] }, { @@ -28,8 +28,7 @@ "collapsed": false, "input": [ "from IPython.html.widgets import interact, interactive, fixed\n", - "from IPython.html import widgets\n", - "from IPython.display import clear_output, display, HTML" + "from IPython.html import widgets" ], "language": "python", "metadata": {}, @@ -37,30 +36,35 @@ "prompt_number": 1 }, { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "As of IPython 2.0, the widgets in this notebook won't show up on http://nbviewer.ipython.org. To view the widgets and interact with them, you will need to download this notebook and run it with an IPython Notebook server.\n", + "
" + ] + }, + { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ - "Basic interact" + "Basic `interact`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Here is a simple function that displays its arguments as an HTML table:" + "At the most basic level, `interact` autogenerates UI controls for function arguments, and then calls the function with those arguments when you manipulate the controls interactively. To use `interact`, you need to define a function that you want to explore. Here is a function that prints its only argument `x`." ] }, { "cell_type": "code", "collapsed": false, "input": [ - "def show_args(**kwargs):\n", - " s = '

Arguments:

\\n'\n", - " for k,v in kwargs.items():\n", - " s += '\\n'.format(k,v)\n", - " s += '
{0}{1}
'\n", - " display(HTML(s))" + "def f(x):\n", + " print x" ], "language": "python", "metadata": {}, @@ -68,26 +72,26 @@ "prompt_number": 2 }, { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you pass this function as the first argument to `interact` along with an integer keyword argument (`x=10`), a slider is generated and bound to the function." + ] + }, + { "cell_type": "code", "collapsed": false, "input": [ - "show_args(a=10, b='Hi There', c=True)" + "interact(f, x=10);" ], "language": "python", "metadata": {}, "outputs": [ { - "html": [ - "

Arguments:

\n", - "\n", - "\n", - "\n", - "
a10
cTrue
bHi There
" - ], - "metadata": {}, - "output_type": "display_data", + "output_type": "stream", + "stream": "stdout", "text": [ - "" + "9\n" ] } ], @@ -97,71 +101,667 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's use this function to explore how `interact` works." + "When you move the slider, the function is called and the current value of `x` is printed.\n", + "\n", + "If you pass `True` or `False`, `interact` will generate a checkbox:" ] }, { "cell_type": "code", "collapsed": false, "input": [ - "i = interact(show_args,\n", - " Temp=(0,10),\n", - " Current=(0.,10.,0.01),\n", - " z=True,\n", - " Text=u'Type here!',\n", - " #Algorithm=['This','That','Other'],\n", - " a=widgets.FloatSliderWidget(min=-10.0, max=10.0, step=0.1, value=5.0, description=\"Float (a)\")\n", - " )" + "interact(f, x=True);" ], "language": "python", "metadata": {}, "outputs": [ { - "html": [ - "

Arguments:

\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
Current4.99
TextType here!
zTrue
Temp5
Float (a)5.0
" - ], - "metadata": {}, - "output_type": "display_data", + "output_type": "stream", + "stream": "stdout", "text": [ - "" + "True\n" ] } ], "prompt_number": 4 }, { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you pass a string, `interact` will generate a text area." + ] + }, + { "cell_type": "code", "collapsed": false, "input": [ - "i.widget" + "interact(f, x='Hi there!');" ], "language": "python", "metadata": {}, "outputs": [ { - "html": [ - "

Arguments:

\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
Current4.99
TextType here!
zTrue
Temp5
Float (a)5.0
" - ], - "metadata": {}, - "output_type": "display_data", + "output_type": "stream", + "stream": "stdout", "text": [ - "" + "Hi there!\n" ] } ], "prompt_number": 5 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`interact` can also be used as a decorator. This allows you to define a function and interact with it in a single shot. As this example shows, `interact` also works with functions that have multiple arguments." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "@interact(x=True, y=1.0)\n", + "def g(x, y):\n", + " print x, y" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "True 1.0\n" + ] + } + ], + "prompt_number": 6 + }, + { + "cell_type": "heading", + "level": 2, + "metadata": {}, + "source": [ + "Fixing arguments using `fixed`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are times when you may want to explore a function using `interact`, but fix one or more of its arguments to specific values. This can be accomplished by wrapping values with the `fixed` function." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "def h(p, q):\n", + " print p, q" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When we call `interact`, we pass `fixed(20)` for q to hold it fixed at a value of `20`." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(h, p=5, q=fixed(20));" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "5 20\n" + ] + } + ], + "prompt_number": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that a slider is only produced for `p` as the value of `q` is fixed." + ] + }, + { + "cell_type": "heading", + "level": 2, + "metadata": {}, + "source": [ + "Widget abbreviations" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you pass an integer valued keyword argument (`x=10`) to `interact`, it generates an integer valued slider control with a range of $[-10,+3\\times10]$. In this case `10` is an *abbreviation* for an actual slider widget:\n", + "\n", + "```python\n", + "IntSliderWidget(min=-10,max=30,step=1,value=10)\n", + "```\n", + "\n", + "In fact, we can get the same result if we pass this `IntSliderWidget` as the keyword argument for `x`:" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(f, x=widgets.IntSliderWidget(min=-10,max=30,step=1,value=10));" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "10\n" + ] + } + ], + "prompt_number": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This examples clarifies how `interact` proceses its keyword arguments:\n", + "\n", + "1. If the keyword argument is `Widget` instance with a `value` attribute, that widget is used. Any widget with a `value` attribute can be used, even custom ones.\n", + "2. Otherwise, the value is treated as a *widget abbreviation* that is converted to a widget before it is used.\n", + "\n", + "The following table gives an overview of different widget abbreviations:\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Keyword argumentWidget
`True` or `False`CheckboxWiget
`'Hi there'`TextareaWidget
`value` or `(min,max)` or `(min,max,step)` if integers are passedIntSliderWidget
`value` or `(min,max)` or `(min,max,step)` if floats are passedFloatSliderWidget
`('orange','apple')` or `{'one':1,'two':2}`DropdownWidget
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You have seen how the checkbox and textarea widgets work above. Here, more details about the different abbreviations for sliders and dropdowns are given.\n", + "\n", + "If a 2-tuple of integers is passed `(min,max)` a integer valued slider is produced with those minimum and maximum (inclusive) values. In this case, the default step size of `1` is used." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(f, x=(0,4));" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "2\n" + ] + } + ], + "prompt_number": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If a 3-tuple of integers is passed `(min,max,step)` the step size can also be set." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(f, x=(0,8,2));" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "4\n" + ] + } + ], + "prompt_number": 11 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A float valued slider is produced if the elements of the tuples are floats. Here the minimum is `0.0`, the maximum is `10.0` and step size is `0.1` (the default)." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(f, x=(0.0,10.0));" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "5.0\n" + ] + } + ], + "prompt_number": 12 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The step size can be changed by passing a 3rd element in the tuple." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(f, x=(0.0,10.0,0.01));" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "4.99\n" + ] + } + ], + "prompt_number": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For both integer and float valued sliders, you can pick the initial value of the widget by passing a default keyword argument to the underlying Python function. Here we set the initial value of a float slider to `5.5`." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "@interact(x=(0.0,20.0,0.5))\n", + "def h(x=5.5):\n", + " print x" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "5.5\n" + ] + } + ], + "prompt_number": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dropdown menus can be produced by passing a tuple of strings. In this case, the strings are both used as the names in the dropdown menu UI and passed to the underlying Python function." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(f, x=('apples','oranges'));" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "apples\n" + ] + } + ], + "prompt_number": 15 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want a dropdown menu that passes non-string values to the Python function, you can pass a dictionary. The keys in the dictionary are used for the names in the dropdown menu UI and the values are the arguments that are passed to the underlying Python function." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(f, x={'one': 10, 'two': 20});" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "20\n" + ] + } + ], + "prompt_number": 16 + }, + { + "cell_type": "heading", + "level": 2, + "metadata": {}, + "source": [ + "Using function annotations with `interact`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are using Python 3, you can also specify widget abbreviations using [function annotations](https://docs.python.org/3/tutorial/controlflow.html#function-annotations). This is a convenient approach allows the widget abbreviations to be defined with a function.\n", + "\n", + "Define a function with an checkbox widget abbreviation for the argument `x`." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "def f(x:True):\n", + " print x" + ], + "language": "python", + "metadata": {}, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then, because the widget abbreviation has already been defined, you can call `interact` with a single argument." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(f);" + ], + "language": "python", + "metadata": {}, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are running Python 2, function annotations can be defined using the `@annotate` function." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "from IPython.utils.py3compat import annotate" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 50 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "@annotate(x=True)\n", + "def f(x):\n", + " print x" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 51 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "interact(f);" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "True\n" + ] + } + ], + "prompt_number": 52 + }, + { + "cell_type": "heading", + "level": 2, + "metadata": {}, + "source": [ + "`interactive`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to `interact` IPython provides another function, `interactive`, that is useful when you want to reuse the widget that are produced or access the data that is bound to the UI controls." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is a function that returns the sum of its two arguments." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "def f(a, b):\n", + " return a+b" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 18 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Unlike `interact`, `interactive` returns a `Widget` instance rather than immediately displaying the widget." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "w = interactive(f, a=10, b=20)" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The widget is a `ContainerWidget`, which is a container for other widgets." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "type(w)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 20, + "text": [ + "IPython.html.widgets.widget_container.ContainerWidget" + ] + } + ], + "prompt_number": 20 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The children of the `ContainerWidget` are two integer valued sliders produced by the widget abbreviations above." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "w.children" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 21, + "text": [ + "(,\n", + " )" + ] + } + ], + "prompt_number": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To actually display the widgets, you can use IPython's `display` function." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "from IPython.display import display\n", + "display(w)" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At this point, the UI controls work just like they would if `interact` had been used. You can manipulate them interactively and the function will be called. However, the widget instance returned by `interactive` also give you access to the current keyword arguments and return value of the underlying Python function.\n", + "\n", + "Here are the current keyword arguments. If you rerun this cell after manipulating the sliders, the values will have changed." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "w.kwargs" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 23, + "text": [ + "{u'a': 10, u'b': 20}" + ] + } + ], + "prompt_number": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is the current return value of the function." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "w.result" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 24, + "text": [ + "30" + ] + } + ], + "prompt_number": 24 } ], "metadata": {}