Calling your Python functions with graphical controls

We need to import a few functions from IPython.


In [1]:
import IPython.html.widgets as widgets
from IPython.html.widgets import interact, interactive, fixed

Let's create a simple function.


In [2]:
def f(x):
    print("%d^2=%d" % (x, x*x))

In [3]:
f(3)


3^2=9

To make our function interactive, we add the decorator @interact. The argument to @interact specifies the domain for the x argument. IPython understands that (0, 10) means "a slider with an integer ranging from 0 to 10".


In [4]:
@interact(x=(0, 10))
def f(x):
    print("%d^2=%d" % (x, x*x))


5^2=25

We can set a default value easily.


In [5]:
@interact(x=(0, 10))
def f(x=3):
    print("%d^2=%d" % (x, x*x))


3^2=9

Widget abbreviations

Other controls can be created easily:

  • checkbox
  • text area
  • slider
  • dropdown

Here is a complete example.


In [6]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

In [7]:
@interact(fun=('sin', 'cos', 'arctan'),  # dropdown menu
          title='my function',  # text area
          dashed=False,  # checkbox
          xscale=(.1, 100.))  # float slider

def complex_plot(fun='sin', 
                 title='sine', 
                 dashed=False, 
                 xscale=5.):
    
    f = getattr(np, fun)
    t = np.linspace(-xscale, +xscale, 1000)
    s = '--' if dashed else '-'
    
    plt.plot(t, f(t), s, lw=3);
    plt.xlim(-xscale, +xscale);
    plt.title(title);


IPython adopts the following conventions, called widget abbreviations.



Keyword argumentWidget
True or FalseCheckboxWiget
'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

More widgets

For more fine-grained control, it is possible to specify widgets explicitly. A widget is just a graphical control like a dropdown list, a button, or a slider. Here is the list of all available widgets:


In [8]:
[widget for widget in dir(widgets) if widget.endswith('Widget')]


Out[8]:
['AccordionWidget',
 'BoundedFloatTextWidget',
 'BoundedIntTextWidget',
 'ButtonWidget',
 'CheckboxWidget',
 'ContainerWidget',
 'DOMWidget',
 'DropdownWidget',
 'FloatProgressWidget',
 'FloatSliderWidget',
 'FloatTextWidget',
 'HTMLWidget',
 'ImageWidget',
 'IntProgressWidget',
 'IntSliderWidget',
 'IntTextWidget',
 'LatexWidget',
 'PopupWidget',
 'RadioButtonsWidget',
 'SelectWidget',
 'TabWidget',
 'TextWidget',
 'TextareaWidget',
 'ToggleButtonWidget',
 'ToggleButtonsWidget',
 'Widget']

We're going to replace a few widgets: the checkbox by a toggle button, and the dropdown list by a sequence of radio buttons. The first step is to recover the widget instance created with @interact.


In [9]:
interact(complex_plot,
         title='my function',
         xscale=(.1, 100.),
         fun=widgets.RadioButtonsWidget(values=['sin', 'cos', 'arctan']),
         dashed=widgets.ToggleButtonWidget(),);


This would also work with custom widgets.