Manipulate Secrets Revealed

Everything you never knew you didn’t know about Manipulate

Lou D’Andria
Wolfram Research, Inc.

The ubiquitous Manipulate function will be used in many talks at this conference, and is the basis for such ventures as the Demonstrations Project and Wolfram CDF Player. But just how well do you know the Manipulate function? In this talk, we will examine some of its lesser known features, ranging from those that are fully documented to those that are not documented at all. The goal of this talk is to empower you to become a Manipulate expert.

The basics

This talk will not focus on the basics:

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

Manipulate[x,{x,{True,False}}]

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

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

We'll assume you have used Manipulate, possibly extensively, and will focus on features which are less widely known.

Refresher

If you'd like study the basics of Manipulate, please see the two very fine Manipulate tutorials. Or check out talks from previous conferences. Or come talk to me.

• Introduction to Manipulate

• Advanced Manipulate Functionality

• http://library.wolfram.com/infocenter/Conferences/6526/

• http://library.wolfram.com/infocenter/Conferences/6531/

• http://library.wolfram.com/infocenter/Conferences/7325/

Three parts to this talk

1. Synchronicity: Understand what this is and why it’s important

2. Syntax: Look at some of the more obscure Manipulate featurettes

3. Bonus content: For you, for later

Synchronicity

Manipulate should always be responsive, but some evaluations just take time.

Manipulate[(Pause[10];x),{x,0,1}]

Manipulate[x,{x,0,1},Initialization:>(Pause[10];x=1)]

Manipulate[x,{x,0,Pause[10];1}]

Manipulate[x,{x,0,1,Dynamic[Pause[10];Slider[##]]&}]

What’s the right way to handle evaluations that take longer than a seconds?

Synchronicity options

There are two evaluation modes for dynamic content: synchronous and asynchronous.

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

c=0;While[True,Pause[2];Print[++c]]

“Synchronous” vs “Asynchronous”

“Synchronous”
• preemptive
• very responsive
• no indication on the cell bracket
• can handle short evaluations
• effectively pauses the front end while waiting
• times out after a few seconds

“Asynchronous”
• queued
• same queue as shift-return
• can handle long running evaluations
• cell bracket highlights until evaluation is complete
• can be preempted
• doesn’t interfere with other front end interactions

Dynamic option: SynchronousUpdating

The default for Dynamic is SynchronousUpdating -> True, which is perfect for short evaluations, but can cause trouble for longer ones.

Dynamic[Pause[10];2+2]

Dynamic[Pause[10];2+2,SynchronousUpdating->False]

DynamicModule option: SynchronousInitialization

The default for DynamicModule is SynchronousInitialization -> True, which again can cause problems for longer running initializations.

DynamicModule[{x=0},Dynamic[x],Initialization:>(Pause[10];x=1)]

DynamicModule[{x=0},Dynamic[x],Initialization:>(Pause[10];x=1),SynchronousInitialization -> False]

Button option: Method

Button and ActionMenu take a Method option for determining whether to evaluate synchronously (Method -> “Preemptive”) or asynchronously (Method -> “Queued”).

Like Dynamic and DynamicModule, these options are set to synchronous mode by default.

Dynamic[x]

Button["click",Pause[2];x=π,Method -> "Queued"]

ActionMenu["click",MapThread[#1:>(Pause[#2];x=#2)&,{{"one","two","three"},{1,2,3}}],Method -> "Queued"]

FileNameSetter

There’s not even a Method option here, because the button should always use Method -> “Queued”.

FileNameSetter[Dynamic[file]]

Bonus

Note that depending on the values of these options, a DynamicModule’s initialization might evaluate after some Dynamics that are inside the DynamicModule.

list={};
DynamicModule[{x=(AppendTo[list,"var init"];0)},Dynamic[AppendTo[list,"dynamic display"];Pause[1];x, TrackedSymbols:>{x},SynchronousUpdating->True],Initialization:>(AppendTo[list,"init"];Pause[2];x=1),SynchronousInitialization->False]

list

This is actually a fairly common idiom for showing progress during long running evaluations.

DynamicModule[{x=0},Dynamic[If[x<100,ProgressIndicator[x,{0,100}],x], SynchronousUpdating->True],Initialization:>(Do[Pause[.01];x=i,{i,100}]),SynchronousInitialization->False]

Synchronicity options in Manipulate

Style[Grid[{
{Style["Manipulate options",Italic],Style["Short evaluation",Bold],Style["Long evaluation",Bold]},
{Style[SynchronousUpdating -> True,Bold],"perfect","might time out, $Aborted"},
{Style[SynchronousUpdating -> False,Bold],"excess overhead, waits in queue","perfect"},
{Style[SynchronousUpdating -> Automatic ,Bold],"sync","async"},
{Style[SynchronousInitialization -> True,Bold],"perfect","might time out, silently"},
{Style[SynchronousInitialization -> False,Bold],"excess overhead, waits in queue","perfect"}
},
Background-> {"Rows" -> {{White,GrayLevel[0.9]}}},
ItemSize -> {"Columns" -> {{Scaled[0.3]}}},
 Dividers->{Center,{False,True,False,False,True}}],
FontFamily->"Helvetica", 
TextAlignment -> Center]

SynchronousInitialization

If you have a one-time evaluation that might take longer than a few seconds, put it in the Initialization option, and set SynchronousInitilization to False.

Manipulate[x,{x,0,1},Initialization:>(Pause[10];x=1),SynchronousInitialization->False]

SynchronousUpdating

Manipulate’s first argument gets wrapped in Dynamic. That Dynamic has SynchronousUpdating -> Automatic by default.

If evaluating the first argument might take longer than that during interactive manipulation, set SynchronousUpdating -> False and possibly ContinuousAction -> False. (You should also think hard about whether such an example belongs in Manipulate to begin with.

Manipulate[(Pause[2];x),{x,0,1,ContinuousAction -> False}, SynchronousUpdating->False]

ControlActive

Another possibility is to use ControlActive. Note that ControlActive works best with the default SynchronousUpdating setting, Automatic, which switches between True and False as needed.

Manipulate[ControlActive[Row[{hz," Hz"}],Play[Sin[hz 2 Pi t],{t,0,1}]],{hz,220,880}]

ControlActive is the basis for PerformanceGoal.

Manipulate[Plot3D[Sin[n x y],{x,0,3},{y,0,3}],{{n,4},1,5}]

Note that the default SynchronousUpdating -> Automatic allows even the initial display to be shown first in preview mode, and then in full mode.

Bonus

Here' s a real - world example that combines knowledge of SynchronousUpdating and Method to create a Manipulate that gives feedback during a long running evaluation, producing a result with links to more information.

calculateResultsList[args___] :=
CheckAbort[
	(* fake call to a time-consuming thing, which occasionally sets $status. *)
	Do[Pause[.1];$status = Plot[Sin[n x],{x,0,10}],{n,20}];
	$status="";
	{args}
	,
	$status="";
	{0,0,0,0,0,0}
]

fullReport[results_] := CreateDocument[results]

briefReport[{0..}] := "No results"

briefReport[results_] :=
DynamicModule[{theResults = results},
	Dynamic[Column[{
		TabView[theResults, ImageSize -> Automatic],
		Button["Show full report", fullReport[theResults], ImageSize -> Automatic]
	}]]
]

Manipulate[
	If[TrueQ[running],
		Column[{
			Button["Abort", FrontEndExecute[FrontEnd`EvaluatorAbort[Automatic]], Evaluator->None, Method->"Queued", ImageSize -> Automatic],
			$status
		}],
		result
	],

	{mode,{"mode 1","mode 2","mode 3"}},
	PaneSelector[{
		"mode 1" -> TabView[{
			"tab 1" -> Column[{
				Control[{a,0.345}],
				Control[{b,0.123}],
				Control[{c,0.789}]}],
			"tab 2" -> Column[{
				Control[{{d,0.234},InputField[#,Number]&}],
				Control[{{e,0.678},InputField[#,Number]&}],
				Control[{{f,0.012},InputField[#,Number]&}]}]
			}],
		"mode 2" -> "to do",
		"mode 3" -> "to do"
		},
		Dynamic[mode],
		ImageSize -> Automatic
	],
	{{result, "No results"}, ControlType -> None},
	{running, {False, True}, ControlType -> None},
	Button["Run", (
		running = True;
		result = briefReport[calculateResultsList[mode,a,b,c,d,e,f]];
		running = False),
		ImageSize -> Automatic,
		Method -> "Queued",
		Enabled -> Dynamic[Not @ running]
	],
	SynchronousUpdating -> True
]

Sizing considerations: Control area

Manipulate[x,{a,0,1},{b,0,1},{c,0,1},{d,0,1},{e,0,1}]

Using annotations for control layout

Manipulate[x,TabView[{
"a"->Control[{a,0,1}],
"b"->Control[{b,0,1}],
"c"->Control[{c,0,1}],
"d"->Control[{d,0,1}],
"e"->Control[{e,0,1}]}]]

Scrolling Pane

labels = Range[10];
With[{vars = Unique[a]& /@ labels},Manipulate[vars,##]& @@ MapThread[{{#1,0,#2},0,1}&,{vars,labels}]]

labels = Range[100];
With[{vars = Unique[a]& /@ labels},Manipulate[vars,Framed[Pane[Column[#],ImageSize -> {Automatic,150},Scrollbars -> True],FrameStyle -> LightGray],ControlPlacement -> Left]& @ MapThread[Control[{{#1,0,#2},0,1}]&,{vars,labels}]]

Dynamic number of controls

Manipulate[Grid[Take[data,h,w]],
{{data,RandomInteger[{0,1},{10,20}]},ControlType->None},
{{h,5},1,10,1},
{{w,10},1,20,1},
Dynamic[Panel[Grid[Table[With[{i=i,j=j},Checkbox[Dynamic[data[[i,j]]],{0,1}]],{i,h},{j,w}]]]]]

Sizing considerations: Content area

Manipulate[Range[1000 n],{n,0,1}]

Get bigger, but not smaller

Manipulate[Range[1000 n],{n,0,1},ShrinkingDelay->1]

Fixed sizes

Manipulate[Range[1000 n],{n,0,1},ContentSize -> {400,Automatic}]

Manipulate[Range[1000 n],{n,0,1},ContentSize -> {{300,600},Automatic}]

Manipulate[Range[1000 n],{n,0,1},ContentSize -> {400,400}]

Useful to prevent controls on the right from moving around while you’re using them.

Manipulate[Range[1000 n],{n,0,1},ContentSize -> Full,ControlPlacement -> Right]

Method option: “ExtraVariables”

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

?f

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

?f

Localize the utility function

Method -> “ExtraVariables” injects the variables into the DynamicModule used internally by Manipulate.

Manipulate[g[t],{t,0,1},Initialization :> (g[x_]:=Cat[x]),Method -> {"ExtraVariables" :> {g}}]

?g

Manipulate[g[t],{t,0,1},Initialization :> (g[x_]:=Dog[x]),Method -> {"ExtraVariables" :> {g}}]

?g

Bookmarks

What if you have a very rich set of parameters, and you want to lead people to particular locations in your space?

Manipulate[ArrayPlot[CellularAutomaton[n,{{1},0},{t,All}],ColorRules->{1->color1,0->color2}],{n,0,255,1},{t,20,100,1},{color1,Black},{color2,White}]

With built-in bookmarks

Manipulate[ArrayPlot[CellularAutomaton[n,{{1},0},{t,All}],ColorRules->{1->color1,0->color2}],{n,0,255,1},{t,20,100,1},{color1,Black},{color2,White},Bookmarks->{"Rule 30":>{color1=RGBColor[0.727519645990692`,1.`,0.5000076295109483`],color2=RGBColor[0.4033875028610666`,0.`,1.`],n=30,t=79},"O Christmas Tree":>{color1=RGBColor[0.`,0.49999237048905165`,0.4806591897459373`],color2=RGBColor[0.07144274052033264`,1.`,0.07934691386282139`],n=161,t=100}}]

Bonus: “ShowControls”

Manipulate[x,{x,0,1},Method -> {"ShowControls" -> False}]

Bonus: “ControlAreaDisplayFunction”

Manipulate[x,{x,0,1},Method -> {"ControlAreaDisplayFunction"->(Panel[#]&)}]

Manipulate[{x,y,z},{x,0,1},{y,0,1},{z,0,1},{a,0,1},{b,0,1},{c,0,1},ControlPlacement -> {Top,Top,Top,Bottom,Bottom,Bottom},Method -> {"ControlAreaDisplayFunction"->(Experimental`FramedLabeled[#, #2]&)},Paneled -> False,AppearanceElements  -> {}]

Bonus: Using options in variable specs

If the specification for a particular Manipulate variable causes it to use a certain control, then you can pass options to that control as options to the variable spec. Recall:

With[{opts = Style[opts,Blue]},Style[Grid[{
{Style["Variable Specification", Bold], Style["Default Control Type", Bold]},
{{var,xmin,∞, opts}, Animator},
{{var, xmin, xmax, opts}, Manipulator},
{{var,xmin,xmax,Δx, opts},Manipulator},
{{var,{xmin,ymin},{xmax,ymax}, opts}, Slider2D},
{{var,{xmin,ymin},{xmax,ymax},{Δx,Δy}, opts}, Slider2D},
{{var,{True, False}, opts}, Checkbox},
{{var, list, opts}, "PopupMenu or SetterBar"},
{{var, color, opts}, ColorSlider},
{{var, other, opts}, InputField}
}, ItemSize -> {"Columns" -> {{Scaled[0.5]}}},Background-> {"Rows" -> {{White, GrayLevel[0.9]}}}, Dividers->{"ColumnsIndexed"->{2 -> True},"RowsIndexed"->{2 -> True}}], FontFamily->"Helvetica", TextAlignment -> Center]]

Example

For example, this Manipulate uses a Manipulator control for x.

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

ImageSize and ContinuousAction are Manipulator options, and so they can be included in x's variable spec.

Manipulate[x,{x,0,1, ImageSize -> Small, ContinuousAction -> False}]

Options can also be set to values which dynamically depend on other variables. Note that, like elsewhere in Manipulate, no explicit Dynamic is required.

Manipulate[{x,y},{x,0,1, Enabled:> y>0.5},{y,0,1}]

Bonus: Locator options

Locator variables in Manipulate let you overlay an arbitrary number of thumbs on top of a graphic or other expression, which intercepts all mouse clicks on the content area.

Manipulate[Graphics[Line[pts],PlotRange->1],{{pts,{{-.6,-.2},{.5,.6}}},{-1,-1},{1,1},Locator}]

But this control does not literally use the Locator function internally. Rather, it uses LocatorPane.

That means that the options you can use in the variable specs are LocatorPane options, like Appearance and LocatorAutoCreate.

Manipulate[Graphics[Line[pts],PlotRange->1],{{pts,{-{.6,.2},{.5,.6}}},{-1,-1},{1,1},Locator,Appearance -> Style["●",24,Red], LocatorAutoCreate->True}]

Bonus

You can have lots of single locator variables, or you can have one multi-locator variable, but you can' t mix and match.

OK:

Manipulate[..., {pt1,{-1,-1},{1,1}, Locator}, {pt2, {-1,-1},{1,1},Locator}]

OK:

Manipulate[..., {{pts,{{0,0},{.1,.2}}},{-1,-1},{1,1}, Locator}]

Not OK:

Manipulate[..., {{pts,{{0,0},{.1,.2}}},{-1,-1},{1,1}, Locator},{pt2, {-1,-1},{1,1},Locator}]

Bonus

You can specify your own dynamic tracking function for locator variables.

Manipulate[Graphics[Line[{{0,0},pt}],PlotRange->1],{{pt,{1,1}},{-1,-1},{1,1},ControlType->Locator,Experimental`TrackingFunction:>((pt=-#)&)}]

Bonus: {u, func} and {u, domain, func}

Manipulate lets you specify custom controls and controls with custom dynamic tracking functions by using {u, func} or {u, domain, func}

func must be a pure function used to produce the display of the control.

Manipulate[{x,y},{x,0,10,Slider[Dynamic[x,(x=#;y=(Sqrt[#]))&],#2]&},{y,0,(Sqrt[10])}]

Advanced tip

Variables specified using the {u, domain, func} syntax will even autorun properly, which is especially important if you are creating a Mainpulate for the Demonstrations Project.

Bonus

Two argument are passed to func by default:
• #1 refers to Dynamic[var] for the current variable var
• #2 refers to the domain specification for that variable, if one is given, wrapped in a list.

Bonus: Control[]

Any control specification can optionally be specified inside the wrapper Control.

These are equivalent:

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

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

Control can be used outside Manipulate:

{Control[{x,0,1}], Dynamic[x]}

But the real power of Control comes when it's used inside of annotations.

Bonus: Annotations

You can interleave a few different kinds of elements among variable specifications. These are intended to annotate existing controls, but they can also be used to insert other controls, or other arbitrary content.

Style[Grid[Prepend[Transpose[Partition[Prepend[Sort[Prepend[Manipulate`Dump`$validOtherArgumentHeads,String]],Delimiter],13,13,{1,1},""]],{Style["Annotations",Bold],SpanFromLeft,SpanFromLeft}],ItemSize -> {"Columns" -> {{Scaled[0.3]}}},Background-> {"Rows" -> {{White,GrayLevel[0.9]}}}, Dividers->{Center,{False,True}}],FontFamily->"Helvetica", TextAlignment -> Center]

Annotation example

Manipulate[Graphics[{Gray,Rectangle[],Black,Rotate[Rectangle[],θ,center],Red,PointSize[0.03],Point[center]}, PlotRange->2, Axes->True],
"The rotation variable runs from 0 to 2π:",
{θ,0,2π, ControlType -> Animator, ImageSize -> Small},
Delimiter,
"Rotation happens around whatever center the user specifies",
{{center,{0,0}},{0,0},{1,1}, ControlType -> Slider2D},
ControlPlacement -> Left
]

Control layout example

You can use this for arbitrary layout in the control area.

Manipulate[Plot[amp f[freq x],{x,0,6},PlotStyle->{color,Dashing[dashing],Thickness[thickness]},Axes->axes,Frame->frame,AxesOrigin->axesorigin,PlotLabel->f],
{f,{Sin,Cos,Tan}},
TabView[{
"Function Variations" -> Column[{Control[{freq,1,5}],Control[{amp,1,5}]}],"Axes and Frames" -> Column[{Control[{axes,{True,False}}],Control[{frame,{False,True}}],Control[{axesorigin,{0,0},{6,1}}]}],
"Plot Style" -> Column[{Control[{color,Blue}],Control[{dashing,0,0.1}],Control[{thickness,0.001,0.1}]}]}, ImageSize -> {All,Automatic}]]

Bonus

To change the placement of controls, you can use ControlPlacement as an option in the parameter spec.

Manipulate[Plot[f[x],{x,0,10}],{f,{Sin,Cos,Tan},ControlPlacement -> Left}]

To change the placement of annotations, use Item[expr, ControlPlacement -> place].

Manipulate[Plot[f[x],{x,0,10}],
{f,{Sin,Cos,Tan}},
Item[Row[{"Plot of the ", Dynamic[f], " function"}],ControlPlacement -> Bottom]]

Bonus

Bonus

SaveDefinitions, long an option to Manipulate, will now be an option to DynamicModule too.

Bonus

Palettes > Basic Math Assistant > Basic Commands > 2D or 3D > Manipulate

Bonus

Explore`ManipulateMaker[]

Conclusion

Manipulate at first glance is rather analogous to Table, making it trivial to create useful interfaces in a few lines of code. But there is quite a bit of depth too. We've seen some of it today.

Questions?