Sage Interact Quickstart

This Sage worksheet was developed for the MAA PREP Workshop "Sage: Using Open-Source Mathematics Software with Undergraduates" (funding provided by NSF DUE 0817071).

Invaluable resources are the Sage wiki http://wiki.sagemath.org/interact (type "sage interact" into Google) and the interact documentation, as well as http://interact.sagemath.org.

 

{{{id=43| /// }}}

Start by getting the commands for what you want the output to look like.  Here we just want a simple plot.

{{{id=27| plot(x^2,(x,-3,3)) /// }}}

Then abstract out the parts you want to change.  We'll be letting the user change the function, so let's make that a variable $f$.

{{{id=28| f=x^3 plot(f,(x,-3,3)) /// }}}

Now make this a "def" function.  The "show" or "print" is needed since the output is not automatically printed from within a function.  Note also that we give the variable a default value of x^2.  This is what $f$ is if the user does not specify a value for $f$.

{{{id=29| def myplot(f=x^2): show(plot(f,(x,-3,3))) /// }}}

Let's test the def function myplot by just calling it.

{{{id=30| myplot() /// }}}

If we call it with a different value for f, we should get a different plot.

{{{id=32| myplot(f=x^3) /// }}}

Now to make a control to enter the function, we just preface the function with @interact.

{{{id=35| @interact def myplot(f=x^2): show(plot(f,(x,-3,3))) /// }}}

Tech tip: Technically what the @interact does is wrap the function, so the above is equivalent to:

def myplot(..): ...

myplot=interact(myplot)

{{{id=54| /// }}}

Note that we can still call our function, even when we've used @interact.  This is often useful in debugging it.

{{{id=51| myplot(x^4) /// }}}

We can go ahead and replace other parts of the expression with variables.  Note the "_" is the function name now.  That is a convention for throw-away names that we don't care about.

{{{id=15| @interact def g(f=x^2,a=-3,b=3): show(plot(f,(x,a,b))) /// }}} {{{id=59| g(x^3,a=2) /// }}}

If we pass ('label', default_value) in for a control, then the control gets the label when printed.

{{{id=56| @interact def _(f=('$f$',x^2),a=('lower',-3),b=('upper',3)): show(plot(f,(x,a,b))) /// }}}

We can specify the type of control explicitly, along with options.

{{{id=79| input_box? ///

File: /home/sageserver/sage-5.0.1/devel/sagenb/sagenb/notebook/interact.py

Type: <type ‘classobj’>

Definition: input_box( [noargspec] )

Docstring:

An input box interactive control. Use this in conjunction with the interact() command.

INPUT:

  • default - an object; the default put in this input box
  • label - a string; the label rendered to the left of the box.
  • type - a type; coerce inputs to this; this doesn’t have to be an actual type, since anything callable will do.
  • height - an integer (default: 1); the number of rows. If greater than 1 a value won’t be returned until something outside the textarea is clicked.
  • width - an integer; width of text box in characters
  • kwargs - a dictionary; additional keyword options

EXAMPLES:

sage: input_box("2+2", 'expression')
Interact input box labeled 'expression' with default value '2+2'
sage: input_box('sage', label="Enter your name", type=str)
Interact input box labeled 'Enter your name' with default value 'sage'
sage: input_box('Multiline\nInput',label='Click to change value',type=str,height=5)
Interact input box labeled 'Click to change value' with default value 'Multiline\nInput'
}}} {{{id=21| @interact def _(f=('$f$',input_box(x^2))): show(plot(f,(x,-3,3))) /// }}}

Here's another type of control: a color picker.

{{{id=81| color_selector? ///

File: /home/sageserver/sage-5.0.1/devel/sagenb/sagenb/notebook/interact.py

Type: <type ‘classobj’>

Definition: color_selector( [noargspec] )

Docstring:

A color selector (also called a color chooser, picker, or tool) interactive control. Use this with the interact() command.

INPUT:

  • default - an instance of or valid constructor argument to Color (default: (0,0,1)); the selector’s default color; a string argument must be a valid color name (e.g., ‘red’) or HTML hex color (e.g., ‘#abcdef’)
  • label - a string (default: None); the label rendered to the left of the selector.
  • widget - a string (default: ‘jpicker’); the color selector widget to use; choices are ‘colorpicker’, ‘jpicker’ and ‘farbtastic’
  • hide_box - a boolean (default: False); whether to hide the input box associated with the color selector widget

EXAMPLES:

sage: color_selector()
Interact color selector labeled None, with default RGB color (0.0, 0.0, 1.0), widget 'jpicker', and visible input box
sage: color_selector((0.5, 0.5, 1.0), widget='jpicker')
Interact color selector labeled None, with default RGB color (0.5, 0.5, 1.0), widget 'jpicker', and visible input box
sage: color_selector(default = Color(0, 0.5, 0.25))
Interact color selector labeled None, with default RGB color (0.0, 0.5, 0.25), widget 'jpicker', and visible input box
sage: color_selector('purple', widget = 'colorpicker')
Interact color selector labeled None, with default RGB color (0.50..., 0.0, 0.50...), widget 'colorpicker', and visible input box
sage: color_selector('crayon', widget = 'colorpicker')
Traceback (most recent call last):
...
ValueError: unknown color 'crayon'
sage: color_selector('#abcdef', label='height', widget='jpicker')
Interact color selector labeled 'height', with default RGB color (0.6..., 0.8..., 0.9...), widget 'jpicker', and visible input box
sage: color_selector('abcdef', label='height', widget='jpicker')
Traceback (most recent call last):
...
ValueError: unknown color 'abcdef'
}}} {{{id=19| @interact def _(f=input_box(x^2,width=20), color=color_selector(widget='colorpicker', default='red')): show(plot(f,(x,-3,3), color=color)) /// }}} {{{id=37| /// }}} {{{id=38| /// }}}

Here are a bunch of options.  Notice the new controls:

{{{id=18| @interact def _(f=input_box(x^2,width=20), color=color_selector(widget='colorpicker', label=""), axes=True, fill=True, zoom=range_slider(-3,3,default=(-3,3))): show(plot(f,(x,zoom[0], zoom[1]), color=color, axes=axes,fill=fill)) /// }}}

That was a bit ugly because all of the controls were stacked on top of each other.  We can layout the controls in a grid in the top, bottom, left, or right using the 'layout' parameter.

{{{id=24| @interact(layout=dict(top=[['f', 'color']], left=[['axes'],['fill']], bottom=[['zoom']])) def _(f=input_box(x^2,width=20), color=color_selector(widget='colorpicker', label=""), axes=True, fill=True, zoom=range_slider(-3,3, default=(-3,3))): show(plot(f,(x,zoom[0], zoom[1]), color=color, axes=axes,fill=fill)) /// }}}

Control Types

Sage has:

We illustrate some of these.

{{{id=9| @interact def _(frame=checkbox(True, label='Use frame')): show(plot(sin(x), (x,-5,5)), frame=frame) /// }}} {{{id=10| var('x,y') colormaps=sage.plot.colors.colormaps.keys() @interact def _(cmap=selector(colormaps)): contour_plot(x^2-y^2,(x,-2,2),(y,-2,2),cmap=cmap).show() /// }}} {{{id=13| var('x,y') colormaps=sage.plot.colors.colormaps.keys() @interact def _(cmap=selector(['RdBu', 'jet', 'gray','gray_r'],buttons=True), type=['density','contour']): if type=='contour': contour_plot(x^2-y^2,(x,-2,2),(y,-2,2),cmap=cmap, aspect_ratio=1).show() else: density_plot(x^2-y^2,(x,-2,2),(y,-2,2),cmap=cmap, frame=True,axes=False,aspect_ratio=1).show() /// }}} {{{id=65| /// }}}

By default, ranges are sliders that divide the range into 500 steps (I think that's the right number...)

{{{id=33| @interact def _(n=(1,20)): print factorial(n) /// }}}

You can set the step size to get, for example, just integer values.

{{{id=42| @interact def _(n=slider(1,20,step_size=1)): print factorial(n) /// }}}

Or you can explicitly specify the slider values.

{{{id=40| @interact def _(n=slider([1..20])): print factorial(n) /// }}}

And the slider values don't even have to be numbers!

{{{id=41| @interact def _(fun=('function', slider([sin,cos,tan,sec,csc,cot]))): print fun(4.39293) /// }}} {{{id=72| /// }}}

Matrices are automatically converted to a grid of input boxes.

{{{id=71| @interact def _(m=('matrix', identity_matrix(2))): print m.eigenvalues() /// }}}

Here's how to get vectors from a grid of boxes.

{{{id=69| @interact def _(v=('vector', input_grid(1, 3, default=[[1,2,3]], to_value=lambda x: vector(flatten(x))))): print v.norm() /// }}}

Sometimes we don't want any updates until we specifically say so.  We can use the auto_update=False option for that.

{{{id=76| @interact def _(m=('matrix', identity_matrix(2)), auto_update=False): print m.eigenvalues() /// }}} {{{id=78| /// }}}