interact(*args, **kwds)
Use interact as a decorator to create interactive Sage notebook
cells with sliders, text boxes, radio buttons, check boxes, and
color selectors.  Simply put ``@interact`` on the line before a
function definition in a cell by itself, and choose appropriate
defaults for the variable names to determine the types of
controls (see tables below).
 
INPUT:
 
- ``f`` - a Python function
 
- ``layout`` (optional) - a dictionary with keys 'top', 'bottom', 'left', 'right' and values lists of rows of control variable names.  Controls are laid out according to this pattern.  If ``layout`` is not a dictionary, it is assumed to be the 'top' value.  If ``layout`` is None, then all controls are assigned separate rows in the ``top`` value.
 
EXAMPLES:
 
In each example below we use a single underscore for the function
name.  You can use *any* name you want; it does not have to
be an underscore.
 
We create an interact control with two inputs, a text input for
the variable ``a`` and a ``y`` slider that runs through the range of
integers from `0` to `19`.
 
::
 
    sage: @interact
    ... def _(a=5, y=(0..20)): print a + y
    ...
    <html>...
 
::
 
    sage: @interact(layout=[['a','b'],['d']])
    ... def _(a=x^2, b=(0..20), c=100, d=x+1): print a+b+c+d
    ...
    <html>...
 
::
 
    sage: @interact(layout={'top': [['a', 'b']], 'left': [['c']], 'bottom': [['d']]})
    ... def _(a=x^2, b=(0..20), c=100, d=x+1): print a+b+c+d
    ...
    <html>...
 
 
Draw a plot interacting with the "continuous" variable ``a``.  By
default continuous variables have exactly 50 possibilities.
 
::
 
    sage: @interact
    ... def _(a=(0,2)):
    ...     show(plot(sin(x*(1+a*x)), (x,0,6)), figsize=4)
    <html>...
 
Interact a variable in steps of 1 (we also use an unnamed
function)::
 
    sage: @interact
    ... def _(n=(10,100,1)):
    ...     show(factor(x^n - 1))
    <html>...
 
Interact two variables::
 
    sage: @interact
    ... def _(a=(1,4), b=(0,10)):
    ...     show(plot(sin(a*x+b), (x,0,6)), figsize=3)
    <html>...
 
Place a block of text among the controls::
 
    sage: @interact
    ... def _(t1=text_control("Factors an integer."), n="1"):
    ...     print factor(Integer(n))
    <html>...
 
You do not have to use interact as a decorators; you can also
simply write ``interact(f)`` where ``f`` is any Python function
that you have defined, though this is frowned upon.  E.g., ``f``
can also be a library function as long as it is written in
Python::
 
    sage: interact(matrix)   # put ZZ, 2,2,[1..4] in boxes...
    <html>...
 
If your the time to evaluate your function takes awhile, you may
not want to have it reevaluated every time the inputs change.  In
order to prevent this, you can add a keyword ``auto_update=False`` to
your function to prevent it from updating whenever the values are
changed.  This will cause a button labeled 'Update' to appear
which you can click on to re-evaluate your function.
 
::
 
    sage: @interact
    ... def _(n=(10,100,1), auto_update=False):
    ...     show(factor(x^n - 1))
    <html>...
 
DEFAULTS:
 
Defaults for the variables of the input function determine
interactive controls.  The standard controls are ``input_box``,
``slider``, ``range_slider``, ``checkbox``, ``selector``,
``input_grid``, and ``color_selector``.  There is also a text
control (see the defaults below).
 
 
* ``u = input_box(default=None, label=None, type=None)`` -
  input box with given ``default``; use ``type=str`` to get
  input as an arbitrary string
 
 
* ``u = slider(vmin, vmax=None, step_size=1, default=None,
  label=None)`` - slider with given list of possible values;
  ``vmin`` can be a list
 
 
* ``u = range_slider(vmin, vmax=None, step_size=1,
  default=None, label=None)`` - range slider with given list
  of possible values; ``vmin`` can be a list
 
 
* ``u = checkbox(default=True, label=None)`` - a checkbox
 
 
* ``u = selector(values, label=None, nrows=None, ncols=None,
  buttons=False)`` - a dropdown menu or buttons (get buttons
  if ``nrows``, ``ncols``, or ``buttons`` is set, otherwise a
  dropdown menu)
 
 
* ``u = input_grid(nrows, ncols, default=None, label=None,
  to_value=lambda x:x, width=4)`` - an editable grid of
  objects (a matrix or array)
 
* ``u = color_selector(default=(0,0,1), label=None,
  widget='farbtastic', hide_box=False)`` - a color selector with a
  possibly hidden input box; the ``widget`` can also be ``'jpicker'``
  or ``'colorpicker'``
 
* ``u = text_control(value='')`` - a block of text
 
You can also create a color selector by setting the default value for
an ``input_box`` to ``Color(...)``.
 
There are also some convenient defaults that allow you to make
controls automatically without having to explicitly specify them.
E.g., you can make ``x`` a continuous slider of values between ``u``
and ``v`` by just writing ``x=(u,v)`` in the argument list of
your function.  These are all just convenient shortcuts for
creating the controls listed above.
 
* ``u`` - blank input_box field
 
* ``u = element`` - input_box with ``default=element``, if
  element not below.
 
* ``u = (umin,umax)`` - continuous slider (really `100` steps)
 
* ``u = (umin,umax,du)`` - slider with step size ``du``
 
* ``u = list`` - buttons if ``len(list)`` at most `5`;
  otherwise, drop down
 
* ``u = generator`` - a slider (up to `10000` steps)
 
* ``u = bool`` - a checkbox
 
* ``u = Color('blue')`` - a color selector; returns ``Color``
  object
 
* ``u = (default, v)`` - ``v`` as above, with given
  ``default`` value
 
* ``u = (label, v)`` - ``v`` as above, with given ``label``
  (a string)
 
* ``u = matrix`` - an ``input_grid`` with ``to_value`` set to
  ``matrix.parent()`` and default values given by the matrix
 
.. note::
 
    Suppose you would like to make an interactive with a default
    RGB color of ``(1,0,0)``, so the function would have signature
    ``f(color=(1,0,0))``.  Unfortunately, the above shortcuts
    reinterpret the ``(1,0,0)`` as a discrete slider with step
    size 0 between 1 and 0.  Instead you should do the
    following::
 
        sage: @interact
        ... def _(v = input_box((1,0,0))):
        ...       show(plot(sin,color=v))
        <html>...
 
    An alternative::
 
        sage: @interact
        ... def _(c = color_selector((1, 0, 0))):
        ...       show(plot(sin, color = c))
        <html>...
 
MORE EXAMPLES:
 
We give an input box that allows one to enter completely arbitrary
strings::
 
    sage: @interact
    ... def _(a=input_box('sage', label="Enter your name", type=str)):
    ...        print "Hello there %s"%a.capitalize()
    <html>...
 
The scope of variables that you control via :func:`interact` are local
to the scope of the function being interacted with. However, by
using the ``global`` Python keyword, you can still modify global
variables as follows::
 
    sage: xyz = 10
    sage: @interact
    ... def _(a=('xyz',5)):
    ...       global xyz
    ...       xyz = a
    <html>...
 
If you enter the above you obtain an :func:`interact` canvas.
Entering values in the box changes the global variable ``xyz``.
Here's a example with several controls::
 
    sage: @interact
    ... def _(title=["A Plot Demo", "Something silly", "something tricky"], a=input_box(sin(x*sin(x*sin(x))), 'function'),
    ...     clr = Color('red'), thickness=[1..30], zoom=(1,0.95,..,0.1), plot_points=(200..2000)):
    ...     html('<h1 align=center>%s</h1>'%title)
    ...     print plot_points
    ...     show(plot(a, -zoom*pi,zoom*pi, color=clr, thickness=thickness, plot_points=plot_points))
    <html>...
 
For a more compact color control, use an empty label, a different
widget (``'colorpicker'`` or ``'jpicker'``), and hide the input
box::
 
    sage: @interact
    ... def _(color=color_selector((1,0,1), label='', widget='colorpicker', hide_box=True)):
    ...     show(plot(x/(8/7+sin(x)), (x,-50,50), fill=True, fillcolor=color))
    <html>...
 
We give defaults and name the variables::
 
    sage: @interact
    ... def _(a=('first', (1,4)), b=(0,10)):
    ...       show(plot(sin(a*x+sin(b*x)), (x,0,6)), figsize=3)
    <html>...
 
Another example involving labels, defaults, and the slider
command::
 
    sage: @interact
    ... def _(a = slider(1, 4, default=2, label='Multiplier'),
    ...       b = slider(0, 10, default=0, label='Phase Variable')):
    ...     show(plot(sin(a*x+b), (x,0,6)), figsize=4)
    <html>...
 
An example where the range slider control is useful::
 
    sage: @interact
    ... def _(b = range_slider(-20, 20, 1, default=(-19,3), label='Range')):
    ...     plot(sin(x)/x, b[0], b[1]).show(xmin=b[0],xmax=b[1])
    <html>...
 
An example using checkboxes, obtained by making the default values
bools::
 
    sage: @interact
    ... def _(axes=('Show axes', True), square=False):
    ...       show(plot(sin, -5,5), axes=axes, aspect_ratio = (1 if square else None))
    <html>...
 
An example generating a random walk that uses a checkbox control
to determine whether points are placed at each step::
 
    sage: @interact
    ... def foo(pts = checkbox(True, "points"), n = (50,(10..100))):
    ...       s = 0; v = [(0,0)]
    ...       for i in range(n):
    ...            s += random() - 0.5
    ...            v.append((i, s))
    ...       L = line(v, rgbcolor='#4a8de2')
    ...       if pts: L += points(v, pointsize=20, rgbcolor='black')
    ...       show(L)
    <html>...
 
You can rotate and zoom into 3-D graphics while interacting with a
variable::
 
    sage: @interact
    ... def _(a=(0,1)):
    ...     x,y = var('x,y')
    ...     show(plot3d(sin(x*cos(y*a)), (x,0,5), (y,0,5)), figsize=4)
    <html>...
 
A random polygon::
 
    sage: pts = [(random(), random()) for _ in xrange(20)]
    sage: @interact
    ... def _(n = (4..len(pts)), c=Color('purple') ):
    ...     G = points(pts[:n],pointsize=60) + polygon(pts[:n], rgbcolor=c)
    ...     show(G, figsize=5, xmin=0, ymin=0)
    <html>...
 
Two "sinks" displayed simultaneously via a contour plot and a 3-D
interactive plot::
 
    sage: @interact
    ... def _(q1=(-1,(-3,3)), q2=(-2,(-3,3))):
    ...     x,y = var('x,y')
    ...     f = q1/sqrt((x+1)^2 + y^2) + q2/sqrt((x-1)^2+(y+0.5)^2)
    ...     C = contour_plot(f, (-2,2), (-2,2), plot_points=30, contours=15, cmap='cool')
    ...     show(C, figsize=3, aspect_ratio=1)
    ...     show(plot3d(f, (x,-2,2), (y,-2,2)), figsize=4)
    <html>...
 
This is similar to above, but you can select the color map from a
dropdown menu::
 
    sage: @interact
    ... def _(q1=(-1,(-3,3)), q2=(-2,(-3,3)),
    ...    cmap=['autumn', 'bone', 'cool', 'copper', 'gray', 'hot', 'hsv',
    ...          'jet', 'pink', 'prism', 'spring', 'summer', 'winter']):
    ...     x,y = var('x,y')
    ...     f = q1/sqrt((x+1)^2 + y^2) + q2/sqrt((x-1)^2+(y+0.5)^2)
    ...     C = contour_plot(f, (x,-2,2), (y,-2,2), plot_points=30, contours=15, cmap=cmap)
    ...     show(C, figsize=3, aspect_ratio=1)
    <html>...
 
A quadratic roots etch-a-sketch::
 
    sage: v = []
    sage: html('<h2>Quadratic Root Etch-a-sketch</h2>')
    <html>...<h2>Quadratic Root Etch-a-sketch</h2>...</html>
    sage: @interact
    ... def _(a=[-10..10], b=[-10..10], c=[-10..10]):
    ...       f = a*x^2 + b*x + c == 0; show(f)
    ...       soln = solve(a*x^2 + b*x + c == 0, x)[0].rhs()
    ...       show(soln)
    ...       P = tuple(CDF(soln))
    ...       v.append(P)
    ...       show(line(v, rgbcolor='purple') + point(P, pointsize=200))
    <html>...
 
In the following example, we only generate data for a given ``n``
once, so that as one varies ``p`` the data does not randomly change.
We do this by simply caching the results for each ``n`` in a
dictionary.::
 
    sage: data = {}
    sage: @interact
    ... def _(n=(500,(100,5000,1)), p=(1,(0.1,10))):
    ...     n = int(n)
    ...     if not data.has_key(n):
    ...         data[n] = [(random(), random()) for _ in xrange(n)]
    ...     show(points([(x^p,y^p) for x,y in data[n]], rgbcolor='black'), xmin=0, ymin=0, axes=False)
    <html>...
 
A conchoid::
 
    sage: @interact
    ... def _(k=(1.2,(1.1,2)), k_2=(1.2,(1.1,2)), a=(1.5,(1.1,2))):
    ...     u, v = var('u,v')
    ...     f = (k^u*(1+cos(v))*cos(u), k^u*(1+cos(v))*sin(u), k^u*sin(v)-a*k_2^u)
    ...     show(parametric_plot3d(f, (u,0,6*pi), (v,0,2*pi), plot_points=[40,40], texture=(0,0.5,0)))
    <html>...
 
An input grid::
 
    sage: @interact
    ... def _(A=matrix(QQ,3,3,range(9)), v=matrix(QQ,3,1,range(3))):
    ...     try:
    ...         x = A\v
    ...         html('$$%s %s = %s$$'%(latex(A), latex(x), latex(v)))
    ...     except:
    ...         html('There is no solution to $$%s x=%s$$'%(latex(A), latex(v)))
    <html>...