Understanding Manipulate

Lou D’Andria, Senior UI Developer, Wolfram Research

The Manipulate function continues to provide a unique and convenient way to interact with the Wolfram Language™, empowering any user to easily create flexible interfaces for investigating any output on any platform that supports Wolfram Notebooks™, including cloud and mobile. In this talk, we give a refresher of Manipulate basics and an overview of the key features that will allow you to take full advantage of this inimitable function.

Much of this talk was motivated by actual difficulties frequently encountered by people in online forums like Wolfram Community, Stack Exchange and Stack Overflow.

Manipulate Basics

You can use Manipulate to interact with anything that can be generated as output:

Manipulate[
Plot[Sin[a x],{x,0,10},PlotStyle->{Directive[color,AbsoluteThickness[thickness]]},Axes->axes],
{a,1,10},
{axes,{True,False}},
{{color, Orange},{Red,Orange,Yellow,Green,Blue,Purple}},
{thickness,Range[1,10],ControlType -> RadioButtonBar}]

Manipulate…

… uses system appearance of sliders, popup menus and other controls, so it will look right on macOS, Windows, etc.

… automatically uses sliders when sliders are appropriate, popup menus when they are appropriate, etc.

… localizes variables to avoid naming conflicts

… lets you customize initial values and labeling of controls

… lets you place controls at the top, bottom, left, right or some combination of locations

… lets you interact directly with things in the content area: rotate, pan, etc.

… lets you extract the input that generates the current display

… lets you easily start animations

Most importantly, Manipulate does not require that you know anything about the mechanics of hooking controls up to variables. You do not have to become an interface programmer to create interfaces. If you know how to use Table, you already know how to use Manipulate.

Variable Specifications

The types of controls used by Manipulate are determined automatically, depending on the form of the variable specifications:

Manipulate[x,{x,0,1}]

Common Specifications

CellPrint[ExpressionCell[TextGrid[{
{Style["Variable Specification", Bold], Style["Valid ControlType Settings", Bold]},
{{"var", "xmin", "xmax"}, Row[{Animator, InputField, IntervalSlider, Locator, Style[Manipulator, Bold],Slider, Slider2D,VerticalSlider, None}, ","]},
{{"var","xmin","xmax","Δx"},Row[{Animator, InputField, IntervalSlider,Locator, Style[Manipulator, Bold], PopupMenu, RadioButtonBar, SetterBar, Slider, Slider2D,VerticalSlider, None}, ","]},
{{"var",{"xmin","ymin"},{"xmax","ymax"}}, Row[{InputField, Locator, Style[Slider2D, Bold],None}, ","]},
{{"var",{"xmin","ymin"},{"xmax","ymax"},{"Δx","Δy"}}, Row[{InputField, Locator, Style[Slider2D, Bold],None}, ","]},
{{"var",{True, False}}, Row[{Animator, Style[Checkbox, Bold], CheckboxBar, InputField, Manipulator, Opener, PopupMenu, RadioButtonBar, SetterBar,Slider, TogglerBar, VerticalSlider, None}, ","]},
{{"var", "list"}, Row[{Animator, Checkbox, CheckboxBar, InputField, Manipulator, Style[PopupMenu, Bold], RadioButtonBar, Style[SetterBar, Bold], Slider, TogglerBar, VerticalSlider, None}, ","]},
{{"var", "color"}, Row[{ColorSetter, Style[ColorSlider, Bold], InputField, None}, ","]},
{{"var", "other"}, Row[{Style[InputField, Bold], None}, ","]}
}, Alignment->{Center,Center},ItemSize -> {"Columns" -> {{Scaled[0.5]}}},Background-> {"Rows" -> {{White, GrayLevel[0.9]}}}, Dividers->{"ColumnsIndexed"->{2 -> True},"RowsIndexed"->{2 -> True}},
Spacings -> {1,1}], "Print",FontFamily->"Source Sans Pro", FontSize -> 15,TextAlignment -> Center,CellMargins -> {{50,Inherited},{Inherited,Inherited}}]]

Modifying Specifications

By default, the initial value of the variable var is taken to be the first element of the specified range, and the label for the control uses the name of the variable var.

Custom initial value: {{var,init}, spec}

Manipulate[x,{{x,0.5},0,1}]

Custom label: {{var, init, label}, spec}

Manipulate[x,{{x,0.5,"variable"},0,1}]

Custom control type: {var, spec, ControlType -> type}

Manipulate[x,{x,0,1,ControlType -> IntervalSlider}]

Custom control options: {var, spec, opt -> val, opt -> val, …}

Manipulate[x,{x,0,1,ControlType -> Animator,AnimationRunning -> False}]

Variable Scoping

The local variables in Manipulate are lexically scoped, very much like scoping done by Module. Here are two different Manipulate expressions that use the same variable name, but they do not conflict:

Manipulate[Fibonacci[n,z],{n,1,100,1}]
Manipulate[Plot[Sin[n x],{x,0,2π}],{n,1,10}]

And neither of these variables uses the global variable of the same name:

n

Copy and paste

DynamicModuleBox is an internal function. OK to mention?

Variable scoping happens during evaluation, and again at the box level in the front end when an object is displayed, which includes when an object is pasted. The box-level scoping happens via DynamicModuleBox.

File saving

The current values of the local variables are stored in the file itself, and the state of those variables is refreshed when the file is reopened.

vFAQ: Lexical Scoping

Scoping is a good thing, but it does mean that certain scoping combinations just will not work, by design.

Very frequently asked question: Why does something like this not work?

f[x_]:=Sin[a x]
Manipulate[Plot[f[x],{x,0,10}],{a,1,5}]

Lexical Scoping

Manipulate and DynamicModule use the same scoping for local variables that Module does: lexical scoping.

A lexically scoped symbol can only be referenced from within the scope where it is declared.

A refresher on Module might be useful to understand lexical scoping.

• Module
• How Modules Work
• Modules and Local Variables
• Blocks Compared with Modules

Module example

So the previous example does not work for the same reason this one does not:

f[x_] := Sin[a x]
Module[{a=1},Plot[f[x],{x,0,10}]]

Or even simpler:

f[x_] := Sin[a x]
Module[{a=1},f[1]]

The right way

Any local variables that are used by a function should be passed into that function as an argument:

ClearAll[f];
f[a_,x_] := Sin[a x]
Module[{a=1},f[a,1]]

ClearAll[f];
f[a_, x_]:=Sin[a x]
Manipulate[Plot[f[a, x],{x,0,10}],{a,1,5}]

Another example

This does not work, and for the same reason: referring to a local variable as if it were a global one:

ClearAll[f,y];
f[x_]=x^2;
y[x_]=f[x0]+f'[x0]*(x-x0);
Manipulate[Plot[{y[x],f[x]},{x,-4,10}],{x0,0,6}]

Passing it as an argument is the best thing to do:

ClearAll[f,y];
f[x_]=x^2;
y[x_, x0_]=f[x0]+f'[x0]*(x-x0);
Manipulate[Plot[{y[x,x0],f[x]},{x,-4,10}],{x0,0,6}]

FAQ: Interdependent Variables (BONUS)

Interdependent Variables

Variable specifications can depend on other local variables:

Manipulate[Graphics[{Polygon[{{0,0},{x,-y},{x,y},{-x,-y},{-x,y}}],Dashing[0.03],Red,Line[{{{-1,-1},{1,1}},{{-1,1},{1,-1}}}]},PlotRange->1],{{x,0.5},0,1},{{y,0.5},0,x}]

Be aware of circular references!

This can lead to circular references, which work exactly as they should, but which may take some effort to understand:

Manipulate[Grid[{
{"","value","endpoints"},
{"x slider",x,{0,y}},
{"y slider",y,{0,x}}},Dividers -> {Center,Center},ItemSize -> Scaled[0.2]],{{x,0.5},0,y},{{y,0.5},0,x}]

vFAQ: Paste Snapshot

Why does my Manipulate not work?

Why is my Manipulate pinking?

How do I export a single frame of a Manipulate?

A Useful Tool, Hidden in Plain Sight

Paste Snapshot in the FEBitmapsCirclePlusIcon menu gives an expression that typically no longer involves Manipulate or Dynamic:

Manipulate[ParametricPlot[{r Cos[x],r Sin[y]},{y,1,k},{x,0,n},Mesh->Full],{n,0,2 Pi},{k,1,2},{r,1,2}]

Advanced Technique: Setting and DynamicSetting

Setting allows you to effectively extract a snapshot via evaluation.

DynamicSetting does this automatically when using its output as input:

Manipulate[ParametricPlot[{r Cos[x],r Sin[y]},{y,1,k},{x,0,n},Mesh->Full],{n,0.1,2 Pi},{k,1.1,2},{r,1,2}]//DynamicSetting

Pinking Due to Suppressed Kernel Messages (BONUS)

One cause of boxes drawing with a pink background (indicating an error of some sort) is kernel messages generated during a Dynamic evaluation:

Dynamic[1/0]

You can click the Badge of Shame (the yellow icon that appears on the cell bracket) to rerun the evaluation and show the messages this time, but what if you do not want suppression of the messages to begin with?

You can turn off this message suppression, and instead see these kernel messages explicitly (which obviously can be very useful!) for the remainder of your front end session, by setting some front end message options:

SetOptions[$FrontEndSession,MessageOptions->{"ConsoleMessageAction"->{"Beep","PrintToConsole","Unsuppressible"},"ErrorAction"->{"Beep","DialogBox","Unsuppressible"},"KernelMessageAction"->{"Beep","PrintToNotebook","Unsuppressible"},"WarningAction"->{"Beep","Unsuppressible"}}]

Turn message suppression back on:

SetOptions[$FrontEndSession,MessageOptions->{"ConsoleMessageAction"->{"Beep","PrintToConsole"},"ErrorAction"->{"Beep","DialogBox"},"KernelMessageAction"->{"Beep","PrintToNotebook"},"WarningAction"->{"Beep"}}]

FAQ: Work Smarter, Not Harder

Why is my Manipulate so slow?

Why does the cell bracket stay lit?

How can I avoid updating this when this other thing is updating?

CPU “Spinning”

Dynamic[expr] evaluates expr whenever it needs its value and it determines that any type of value of symbols on which it depends might have changed.

If evaluating expr itself causes one of those symbols to change its value over and over, then the Dynamic will update over and over.

Sometimes spinning is good

This Manipulate displays a simple random walk as it happens. Appending to the value of list triggers a Dynamic update, which again appends to the value of list and so on:

Manipulate[Graphics[{Line[Dynamic[If[!paused,AppendTo[list,Last[list]+RandomChoice[stepsize {{1,0},{0,1},{-1,0},{0,-1}}]],list]]],Hue[1],AbsolutePointSize[10],Point[Dynamic[Last[list]]]},PlotRange->All,ImageSize->{300,300}],{{list,{{0,0}}},_,ControlType->None},{{stepsize,5},Range[10]},{paused,{False,True}},Button["clear",list={{0,0}}]]

Sometimes it is not

Bad:

Manipulate[x=x0;x=x+1;x,{x0,0,1}]

Better:

Manipulate[x=x0;x=x+1;x,{x0,0,1},TrackedSymbols:>{x0}]

Manipulate[x=x0;x=x+1;x,{x0,0,1},TrackedSymbols:>True]

Manipulate[DynamicModule[{x=x0},x=x+1;x],{x0,0,1}]

Manipulate[Module[{x=x0},x=x+1;x],{x0,0,1}]

Rule of thumb: Do not make assignments in the first argument of Manipulate lightly.

Separating Static Content from Dynamic Content

Why does the ContourPlot update when I move the unrelated disk around?

Manipulate[Show[ContourPlot[Cos[a x]+Cos[a y],{x,0,1},{y,0,1}],Graphics[Disk[p,0.02]]],{{a,10},0,20},{p,{0,0},{1,1}}]

Using explicit Dynamic in Manipulate

Add Dynamic around bits that can update independent of the rest:

Manipulate[Show[ContourPlot[Cos[a x]+Cos[a y],{x,0,1},{y,0,1}],Graphics[Dynamic[Disk[p,0.02]]]],{{a,10},0,20},{p,{0,0},{1,1}}]

See Principle of Minimal Dynamics for more details:

Manipulate[Show[ContourPlot[Cos[a x]+Cos[a y],{x,0,1},{y,0,1}],Graphics[Disk[Dynamic[p],0.02]]],{{a,10},0,20},{p,{0,0},{1,1}}]

Manipulate Cannot Make Slow Computations Fast

See Principle of Evaluation Blocking.

Queued versus preemptive evaluations
SynchronousUpdating / SynchronousInitialization
ContinuousAction
ControlActive / PerformanceGoal
Handling aborts

Advanced Tweaks to Dynamic Tracking (BONUS)

DynamicBox is an internal function. OK to mention?

Consider a DynamicBox that updates anytime the value of a symbol or the mouse position changes:

$var=0;Dynamic[{++$var, CurrentValue["MousePosition"]}]

Use Refresh[expr,none] to turn off most kernel tracking during evaluation of expr, but it does not prevent dynamic updates triggered by other changes:

$var1=0;Dynamic[Refresh[{++$var1, CurrentValue["MousePosition"]}, None]]

Use SingleEvaluation->True to mark the contents of a particular DynamicBox as completely constant, which avoids even more Dynamic updates, including CurrentValue changes:

$var2=0;Dynamic[{++$var2, CurrentValue["MousePosition"]},SingleEvaluation->True]

Disable all dynamic tracking for a given symbol with Internal`SetValueNoTrack[sym,True]:

$var3=0;Dynamic[++$var3]

Internal`SetValueNoTrack[$var3,True]

Initializing Manipulate

Initialization Option

You can use the Initialization option to Manipulate to specify some code that gets evaluated when the Manipulate output is first displayed, for instance in a new Mathematica® session:

ClearAll[f]
Manipulate[f[x],{x,0,1},Initialization:>(f[x_] := x+1)]

SaveDefinitions Option

The SaveDefinitions option determines whether external definitions required to display the content area are automatically included in the Manipulate output:

ClearAll[f];
f[x_]:=x+1;
Manipulate[f[x],{x,0,1},SaveDefinitions->True]

FAQ: Manipulate Evaluation Sequence (BONUS)

In what order do these pieces of Manipulate evaluate?

body (first argument)

variable specifications (other arguments)

Initialization option

option->True

SynchronousUpdating -> True | False

SynchronousInitialization -> True | False

Literal Dynamic in various places

If you thought that the Initialization evaluates before everything else in the Manipulate, you are wrong:

nb = NotebookCreate[WindowTitle -> "Manipulate Log", WindowSize -> 500, WindowMargins -> {{Automatic,0},{Automatic,0}}];

log[label_] := (SelectionMove[nb, After, Notebook]; NotebookWrite[nb,Cell[BoxData[ToBoxes[Row[{AbsoluteTime[]-$t, ": ",label, " (", If[$SynchronousEvaluation,"sync","async"],")"}]]],"Output"]]);

$t=AbsoluteTime[];
Manipulate[
log["body"];Dynamic[log["inner dynamic"];x],
{x,0,log["control spec"];1},
Initialization:>(log["init"])
]

Experiment with putting calls to log elsewhere within Manipulate, and see what happens…

Another Example to Investigate

From Stack Overflow:

Manipulate[ControlActive[Graphics[{LightRed,Circle[{0,0},r]},PlotRange->{{-1,1},{-1,1}}],DynamicModule[{exprs={Red,Circle[{0,0},r]},rr=r},Graphics[Dynamic[exprs],PlotRange->{{-1,1},{-1,1}}],Initialization:>(Pause[1];
AppendTo[exprs,{Red,Disk[{0,0},rr]}];Pause[1];
AppendTo[exprs,{Thickness[0.05],Black,Circle[{0,0},rr]}]),SynchronousInitialization->False]],{{r,0.5},0,1}]

FAQ: SaveDefinitions Details

How Does It Work?

Manipulate[…,SaveDefinitions->True] uses FullDefinition on every symbol used in that Manipulate expression and stores those definitions in the Initialization option.

FullDefinition[symbol] recursively prints as all definitions for the symbol and for the symbols that appear in these definitions, unless those symbols have the attribute Protected.

FullDefinition does not show rules associated with symbols that have attribute ReadProtected.

Note that FullDefinition is also used by Save[].

Example: Circle Inversion

Michael Trott, circa 2007

invert[Circle[{X_,Y_},R_],Circle[{x_,y_},r_]]:=With[{𝒹=(((x-X))^2)+(((y-Y))^2)},Circle[{X,Y}+(((R^2) {x-X,y-Y})/(𝒹-(r^2))),Abs[((r (R^2))/((r^2)-𝒹))]]]

inversionGraphics[n_Integer,o_Integer,r_,α_]:=With[{δφ=((2 π)/n)},Module[{circles},Graphics@@{Reverse[MapIndexed[{Hue[((0.72 (#2[[1]]-1))/o)],#1}&,circles=(DeleteCases[#1,_Circle?(MemberQ[#1,Indeterminate,{-1}]||Negative[Last[#1]]&),∞]&)[NestList[Flatten[Outer[invert,#1,#1]]&,N[Table[Circle[(1+α (((-1))^(jφ))) {Cos[(π/2)+jφ δφ],Sin[(π/2)+jφ δφ]},r],{jφ,n}]],o]]]],PlotRange->Max[Apply[Abs[#1]+#2&,Flatten[circles],{1}]] {{-1,1},{-1,1}}}]]//Internal`DeactivateMessages

ClearAll[n,r, x, y]

Manipulate[inversionGraphics[n,o,Tan[r],α],{{r,0.4},0,(π/2)},{{α,0},-2,2},{{o,2},{1,2}},{{n,4},{2,4,6,8,10,12}},SaveDefinitions->True]

FullDefinition[inversionGraphics]

Manipulate`Dump`HeldFullDefinition[Manipulate[inversionGraphics[n,o,Tan[r],α],{{r,0.4},0,(π/2)},{{α,0},-2,2},{{o,2},{1,2}},{{n,4},{2,4,6,8,10,12}},SaveDefinitions->True]]

When to Use SaveDefinitions

Storing definitions for simple functions, which only refer to variables you pass as arguments.

When sending interfaces to your future self, to other people, or to the Demonstrations Project.

When NOT to Use SaveDefinitions

Storing definitions from a package.

Storing definitions of functions that have the Protected and/or ReadProtected attributes.

iFAQ: SaveDefintions and Iterative Development (BONUS)

Consider this sequence when building a Manipulate:

Define a function.

Evaluate a Manipulate input that uses that function.

Change the function definition.

Evaluate that Manipulate again.

Change the function again.

Evaluate the Manipulate again.

Keep iterating until you are happy with the results.

Question: At what point should you introduce SaveDefinitions->True to the Manipulate?

Answer: Wait until the very end. If you add it any earlier, the intermediate versions of the function may wind up being re-added to your session from a Manipulate generated during that time:

ClearAll[f]

f[x_] := {x,1};Manipulate[f[x],{x,0,1},SaveDefinitions->True]

f[x_,y_] := {x,y};Manipulate[f[x,y],{x,0,1},{y,0,1},SaveDefinitions->True]

f[x_,y_:1] := {x,y};Manipulate[f[x],{x,0,1},SaveDefinitions->True]

Now quit the kernel. What do you think the definition of f will be after displaying those three Manipulates in your next kernel session?

iFAQ: Lexical Scoping and Initialization / SaveDefinitions (BONUS)

Note that lexical scoping of Manipulate variables also applies to the expression in the Initialization option:

ClearAll[f]

Manipulate[f[x],{x,0,1},{y,0,1},Initialization:>(f[x_] := x + y)]

Manipulate[f[x],{x,0,1},{y,0,1},Initialization:>(f[x_] := x + y)]

Notice the y in the definition of f. That’s the local y from that Manipulate.

Also notice that this means the preceding examples create a global definition of f that refers to the local variable y of a particular Manipulate, and so it very likely will not work correctly outside that Manipulate. It will even break to various degrees if you have multiple copies of this one Manipulate, as in the preceding example. It is probably best to avoid such definitions when possible.

Conclusion

Manipulate issues like scoping, evaluation control and initialization are not too hard to understand, but require a bit of care when encountering them in the wild. Mastering these concepts will help you get the most out of this powerful function and build interactive interfaces with ease.