Using Interact.ipynb
769 lines
| 18.7 KiB
| text/plain
|
TextLexer
Brian E. Granger
|
r16057 | { | |
"metadata": { | |||
"name": "", | |||
Brian E. Granger
|
r17484 | "signature": "sha256:6d8c7c51322c4911e478068e8fa8e897bd72c614096f5df110ed86d01d66001c" | |
Brian E. Granger
|
r16057 | }, | |
"nbformat": 3, | |||
"nbformat_minor": 0, | |||
"worksheets": [ | |||
{ | |||
"cells": [ | |||
{ | |||
"cell_type": "heading", | |||
"level": 1, | |||
"metadata": {}, | |||
"source": [ | |||
Brian E. Granger
|
r17484 | "Using Interact" | |
Brian E. Granger
|
r16057 | ] | |
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
Brian E. Granger
|
r17484 | "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." | |
Brian E. Granger
|
r16057 | ] | |
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
"from IPython.html.widgets import interact, interactive, fixed\n", | |||
Brian E. Granger
|
r17484 | "from IPython.html import widgets" | |
Brian E. Granger
|
r16057 | ], | |
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 1 | |||
}, | |||
{ | |||
Brian E. Granger
|
r17484 | "cell_type": "markdown", | |
"metadata": {}, | |||
"source": [ | |||
"<div class=\"alert alert-success\">\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", | |||
"</div>" | |||
] | |||
}, | |||
{ | |||
Brian E. Granger
|
r16057 | "cell_type": "heading", | |
"level": 2, | |||
"metadata": {}, | |||
"source": [ | |||
Brian E. Granger
|
r17484 | "Basic `interact`" | |
Brian E. Granger
|
r16057 | ] | |
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
Brian E. Granger
|
r17484 | "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`." | |
Brian E. Granger
|
r16057 | ] | |
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
Brian E. Granger
|
r17484 | "def f(x):\n", | |
" print x" | |||
Brian E. Granger
|
r16057 | ], | |
"language": "python", | |||
"metadata": {}, | |||
"outputs": [], | |||
"prompt_number": 2 | |||
}, | |||
{ | |||
Brian E. Granger
|
r17484 | "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." | |||
] | |||
}, | |||
{ | |||
Brian E. Granger
|
r16057 | "cell_type": "code", | |
"collapsed": false, | |||
"input": [ | |||
Brian E. Granger
|
r17484 | "interact(f, x=10);" | |
Brian E. Granger
|
r16057 | ], | |
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
Brian E. Granger
|
r17484 | "output_type": "stream", | |
"stream": "stdout", | |||
Brian E. Granger
|
r16057 | "text": [ | |
Brian E. Granger
|
r17484 | "9\n" | |
Brian E. Granger
|
r16057 | ] | |
} | |||
], | |||
"prompt_number": 3 | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
Brian E. Granger
|
r17484 | "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:" | |||
Brian E. Granger
|
r16057 | ] | |
}, | |||
{ | |||
"cell_type": "code", | |||
"collapsed": false, | |||
"input": [ | |||
Brian E. Granger
|
r17484 | "interact(f, x=True);" | |
Brian E. Granger
|
r16057 | ], | |
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
Brian E. Granger
|
r17484 | "output_type": "stream", | |
"stream": "stdout", | |||
Brian E. Granger
|
r16057 | "text": [ | |
Brian E. Granger
|
r17484 | "True\n" | |
Brian E. Granger
|
r16057 | ] | |
} | |||
], | |||
"prompt_number": 4 | |||
}, | |||
{ | |||
Brian E. Granger
|
r17484 | "cell_type": "markdown", | |
"metadata": {}, | |||
"source": [ | |||
"If you pass a string, `interact` will generate a text area." | |||
] | |||
}, | |||
{ | |||
Brian E. Granger
|
r16057 | "cell_type": "code", | |
"collapsed": false, | |||
"input": [ | |||
Brian E. Granger
|
r17484 | "interact(f, x='Hi there!');" | |
Brian E. Granger
|
r16057 | ], | |
"language": "python", | |||
"metadata": {}, | |||
"outputs": [ | |||
{ | |||
Brian E. Granger
|
r17484 | "output_type": "stream", | |
"stream": "stdout", | |||
Brian E. Granger
|
r16057 | "text": [ | |
Brian E. Granger
|
r17484 | "Hi there!\n" | |
Brian E. Granger
|
r16057 | ] | |
} | |||
], | |||
"prompt_number": 5 | |||
Brian E. Granger
|
r17484 | }, | |
{ | |||
"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", | |||
"<table class=\"table table-condensed table-bordered\">\n", | |||
" <tr><td><strong>Keyword argument</strong></td><td><strong>Widget</strong></td></tr> \n", | |||
" <tr><td>`True` or `False`</td><td>CheckboxWiget</td></tr> \n", | |||
" <tr><td>`'Hi there'`</td><td>TextareaWidget</td></tr>\n", | |||
" <tr><td>`value` or `(min,max)` or `(min,max,step)` if integers are passed</td><td>IntSliderWidget</td></tr>\n", | |||
" <tr><td>`value` or `(min,max)` or `(min,max,step)` if floats are passed</td><td>FloatSliderWidget</td></tr>\n", | |||
" <tr><td>`('orange','apple')` or `{'one':1,'two':2}`</td><td>DropdownWidget</td></tr>\n", | |||
"</table>" | |||
] | |||
}, | |||
{ | |||
"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": [ | |||
"(<IPython.html.widgets.widget_int.IntSliderWidget at 0x10557ee90>,\n", | |||
" <IPython.html.widgets.widget_int.IntSliderWidget at 0x10616ebd0>)" | |||
] | |||
} | |||
], | |||
"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 | |||
Brian E. Granger
|
r16057 | } | |
], | |||
"metadata": {} | |||
} | |||
] | |||
} |