{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using Interact"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `interact` function (`panel.interact`) automatically creates user interface (UI) controls for exploring code and data interactively. It is the easiest way to get started using Panel, and it provides enough flexibility that it may be all you need to learn in Panel."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "\n",
    "from panel.interact import interact, interactive, fixed, interact_manual\n",
    "from panel import widgets\n",
    "\n",
    "pn.extension()"
   ]
  },
  {
   "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 prints its only argument `x`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(x):\n",
    "    return 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, which prints the current value of `x`.\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 area."
   ]
  },
  {
   "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 how to 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": [
    "@interact(x=True, y=1.0)\n",
    "def g(x, y):\n",
    "    return (x, y)\n",
    "g"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Laying out interact widgets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``interact`` function returns a Panel containing the widgets and the display output. By indexing into this Panel we can lay out the objects precisely how we want:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "layout = interact(f, x=10)\n",
    "\n",
    "pn.Column('**A custom interact layout**', pn.Row(layout[0], layout[1]))"
   ]
  },
  {
   "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(start=-10,end=30,step=1,value=10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This examples clarifies how `interact` proceses 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",
    "<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>Checkbox</td></tr>  \n",
    "  <tr><td>'Hi there'</td><td>Text</td></tr>\n",
    "  <tr><td>value or (min,max,[step,[value]]) if integers are passed</td><td>IntSlider</td></tr>\n",
    "  <tr><td>value or (min,max,[step,[value]]) if floats are passed</td><td>FloatSlider</td></tr>\n",
    "  <tr><td>['orange','apple'] or {'one':1,'two':2}</td><td>Dropdown</td></tr>\n",
    "</table>\n",
    "Note that a dropdown is used if a list or a dict 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 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)`, 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": [
    "If a 3-tuple of integers is passed `(min,max,step)`, the step size can also be set."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "interact(f, x=(0, 8, 2))"
   ]
  },
  {
   "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",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "interact(f, x=(0.0, 10.0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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.0, 10.0, 0.01))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For both integer and float-valued sliders, you can pick the initial value of the widget by supplying a default keyword argument when you define 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\n",
    "\n",
    "h"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also set the initial value by passing a fourth element in the tuple."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "interact(f, x=(0.0, 20.0, 0.5, 5.5))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Use `None` as the third element to just set min, max, and value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "interact(f, x=(0.0, 20.0, None, 5.5))"
   ]
  },
  {
   "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": [
    "When working with numeric data ``interact`` will automatically add a discrete slider:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "interact(f, x=dict([('one', 10), ('two', 20)]))"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
