{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [Overview](01.00-overview.ipynb) | [Contents](00.00-index.ipynb) | [OPTIONAL - More about interact](02.01-OPTIONAL-More-About-Interact.ipynb) >" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Widgets without writing widgets: interact" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `interact` function (`ipywidgets.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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ipywidgets import interact, interactive, fixed, interact_manual\n", "import ipywidgets as widgets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic `interact`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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 triples its argument, `x`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def f(x):\n", " return 3 * x" ] }, { "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 parameter." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(f, x=10);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When you move the slider, the function is called, and the return value is printed.\n", "\n", "If you pass `True` or `False`, `interact` will generate a checkbox:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(f, x=True);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you pass a string, `interact` will generate a `Text` field." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(f, x='Hi there!');" ] }, { "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", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@widgets.interact(x=True, y=1.0)\n", "def g(x, y):\n", " return (x, y)" ] }, { "cell_type": "markdown", "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", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def h(p, q):\n", " return (p, q)" ] }, { "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", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(h, p=5, q=fixed(20));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that a slider is only produced for `p` as the value of `q` is fixed." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Widget abbreviations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When you pass an integer-valued keyword argument of `10` (`x=10`) to `interact`, it generates an integer-valued slider control with a range of `[-10, +3*10]`. In this case, `10` is an *abbreviation* for an actual slider widget:\n", "\n", "```python\n", "IntSlider(min=-10, max=30, step=1, value=10)\n", "```\n", "\n", "In fact, we can get the same result if we pass this `IntSlider` as the keyword argument for `x`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(f, x=widgets.IntSlider(min=-10, max=30, step=1, value=10));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This examples clarifies how `interact` processes its keyword arguments:\n", "\n", "1. If the keyword argument is a `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`Checkbox
`'Hi there'`Text
`value` or `(min,max)` or `(min,max,step)` if integers are passedIntSlider
`value` or `(min,max)` or `(min,max,step)` if floats are passedFloatSlider
`['orange','apple']` or `[('one', 1), ('two', 2)]`Dropdown
\n", "Note that a dropdown is used if a list or a list of tuples is given (signifying discrete choices), and a slider is used if a tuple is given (signifying a range)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You have seen how the checkbox and text 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)`, an integer-valued slider is produced with those minimum and maximum values (inclusively). In this case, the default step size of `1` is used." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(f, x=(0, 4));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `FloatSlider` is generated if any of the values are floating point. The step size can be changed by passing a third element in the tuple." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(f, x=(0, 10, 0.01));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise: Reverse some text\n", "\n", "Here is a function that takes text as an input and returns the text backwards." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def reverse(x):\n", " return x[::-1]\n", "\n", "reverse('I am printed backwards.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use `interact` to make interactive controls for this function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# %load solutions/interact-basic-list/reverse-text.py\n" ] }, { "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", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@interact(x=(0.0, 20.0, 0.5))\n", "def h(x=5.5):\n", " return x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dropdown menus are constructed by passing a list 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", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(f, x=['apples','oranges']);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you want a dropdown menu that passes non-string values to the Python function, you can pass a list of tuples of the form `('label', value)`. The first items are the names in the dropdown menu UI and the second items are values that are the arguments passed to the underlying Python function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(f, x=[('one', 10), ('two', 20)]);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic interactive plot\n", "\n", "Though the examples so far in this notebook had very basic output, more interesting possibilities are straightforward. \n", "\n", "The function below plots a straight line whose slope and intercept are given by its arguments." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib widget\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "def f(m, b):\n", " plt.figure(2)\n", " plt.clf()\n", " plt.grid()\n", " x = np.linspace(-10, 10, num=1000)\n", " plt.plot(x, m * x + b)\n", " plt.ylim(-5, 5)\n", " plt.show()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The interactive below displays a line whose slope and intercept is set by the sliders. Note that if the variable containing the widget, `interactive_plot`, is the last thing in the cell it is displayed." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interact(f, m=(-2.0, 2.0), b=(-3, 3, 0.5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise: Make a plot\n", "\n", "Here is a python function that, given $k$ and $p$, plots $f(x) = \\sin(k x - p)$.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def plot_f(k, p):\n", " plt.figure(5)\n", " plt.clf()\n", " plt.grid()\n", " x = np.linspace(0, 4 * np.pi)\n", " y = np.sin(k*x - p)\n", " plt.plot(x, y)\n", " plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Copy the above function definition and make it interactive using `interact`, so that there are sliders for the parameters $k$ and $p$, where $0.5\\leq k \\leq 2$ and $0 \\leq p \\leq 2\\pi$ (hint: use `np.pi` for $\\pi$)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# %load solutions/interact-basic-list/plot-function.py\n", "interact(plot_f, k=(0.5, 2), p=(0, 2 * np.pi))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# For more information \n", "\n", "See the notebook [02.01-More About interact](02.01-OPTIONAL-More-About-Interact.ipynb) for more information about other ways of generating interactive controls for functions and for details about how to control when sliders are updated.\n", "\n", "For more extended examples of `interact` and `interactive`, see [the example in the ipywidgets source repository](https://github.com/jupyter-widgets/ipywidgets/blob/master/docs/source/examples/Index.ipynb)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [Overview](01.00-overview.ipynb) | [Contents](00.00-index.ipynb) | [OPTIONAL - More about interact](02.01-OPTIONAL-More-About-Interact.ipynb) >" ] } ], "metadata": { "kernelspec": { "display_name": "widgets-tutorial", "language": "python", "name": "widgets-tutorial" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.10" } }, "nbformat": 4, "nbformat_minor": 4 }