WLJS LogoWLJS Notebook

Manipulate

Wolfram Kernel
Manipulate[expr_, {u_Symbol, min_, max_}..]
Manipulate[expr_, {{u_Symbol, initial_}, min_, max_}..]
Manipulate[expr_, {{u_Symbol, initial_}, min_, max_, step_}..]
Manipulate[expr_, {{u_Symbol, initial_, label_String}, min_, max_, step_}..]
Manipulate[expr_, {{u_Symbol}, values_List}..]
Manipulate[expr_, {{u_Symbol, initial_}, values_List}..]
Manipulate[expr_, {{u_Symbol, initial_, label_String}, values_List}..]

generates a version of expr with controls added to allow interactive reevaluation.

Manipulate can be used on any Wolfram expression. Graphics or images passed as expr or part of it will be automatically optimized using JIT transpiler if possible. This provides an immediate mode for a user to construct interactive widgets.

By its nature, all interactivity in WLJS Notebooks is implemented in retained mode, while Manipulate is a wrapper over low-level building blocks such as Offload, InputRange, etc., with a diff algorithm used to optimize evaluation of changes. For frequently changing data or complex visuals, we still recommend using these low-level building blocks.

Consider also ManipulatePlot and ManipulateParametricPlot for basic interactive curve plotting.

Examples

Here is a basic example involving symbolics:

Manipulate[Series[Sinc[x], {x, 0, n}], {n, 1, 5, 1}]

Here are a few examples with Plot expressions that effectively use JIT:

Manipulate[
 Plot[Sin[a x + b], {x, 0, 6}], {{a, 2, "Multiplier"}, 1, 
  4}, {{b, 0, "Phase Parameter"}, 0, 10}, ContinuousAction->True]
Manipulate[Plot[1.0 + Sin[w] Sin[x + w],{x,0,5Pi}, Epilog->{
  Red, Point[{8.0, 1.0 + Sin[w] Sin[8.0 + w]}]
}], {w,0,Pi}, ContinuousAction->True]

Another example that solves an ODE on the fly:

Manipulate[
 Plot[Evaluate[
   y[t] /. First[
     NDSolve[ {y''[x] == -x y[x], y[0] == a, y'[0] == b}, 
      y, {x, 0, 4}]]], {t, 0, 4}, 
  Epilog -> {Point[{4, 1/2}], Green, Arrow[{{0, a}, {1, b + a}}], Red,
     Point[{0, a}]},  PlotRange -> 3],
 {{a, 1}, -3, 3},
 {{b, 0}, -3, 3}]

3D plot example:

Manipulate[Plot3D[Sin[n x] Cos[n y], {x,-1,1}, {y,-1,1}], {n, 1, 5, 0.3}, ContinuousAction->True]

Images:

img = ImageResize[ExampleData[ExampleData["TestImage"] // Last], 350];
Manipulate[
  ImageAdjust[img, {c,a}], 
  
  {{c, 0},0,5,0.1}, 
  {{a, 0},0,5,0.1},
  ContinuousAction->True
]

Here is an example with mixed symbolics and graphics:

Manipulate[ Row[{ "m", "==", MatrixForm[m], StreamPlot[Evaluate[m . {x, y}], {x, -1, 1}, {y, -1, 1}, StreamScale -> Large, ImageSize -> Small ] }], {{m, ((*GB[*){{1(*|*),(*|*)0}(*||*),(*||*){0(*|*),(*|*)2}}(*]GB*))}, { ((*GB[*){{1(*|*),(*|*)0}(*||*),(*||*){0(*|*),(*|*)2}}(*]GB*)) -> "Nodal source", ((*GB[*){{1(*|*),(*|*)1}(*||*),(*||*){0(*|*),(*|*)1}}(*]GB*)) -> "Degenerate source", ((*GB[*){{0(*|*),(*|*)1}(*||*),(*||*){-1(*|*),(*|*)1}}(*]GB*)) -> "Spiral source", ((*GB[*){{-1(*|*),(*|*)0}(*||*),(*||*){0(*|*),(*|*)-2}}(*]GB*)) -> "Nodal sink", ((*GB[*){{-1(*|*),(*|*)1}(*||*),(*||*){0(*|*),(*|*)-1}}(*]GB*)) -> "Degenerate sink", ((*GB[*){{0(*|*),(*|*)1}(*||*),(*||*){-1(*|*),(*|*)-1}}(*]GB*)) -> "Spiral sink", ((*GB[*){{0(*|*),(*|*)1}(*||*),(*||*){-1(*|*),(*|*)0}}(*]GB*)) -> "Center", ((*GB[*){{1(*|*),(*|*)0}(*||*),(*||*){0(*|*),(*|*)-2}}(*]GB*)) -> "Saddle"}}]

Options

ContinuousAction

By default, this is False, which means that any update happens after the user's action, not before.

"ControlsLayout"

By default, this is "Vertical". Another possible value is "Horizontal".

PerformanceGoal

By default, this is "Speed", which involves the JIT Transpiler. Change it to any other value to disable it completely.

"JITFeature"

By default, this is True, which involves the JIT Transpiler. If either PerformanceGoal or "JITFeature" is set to a non-default value, the JIT transpiler will be disabled.

Appearance

By default, this is "Default". Set it to None to remove the frame and info boxes.

"UpdateFunction"

Allows to alter the expression, prevent default actions or cause side-effects upon update. The following return values are expected

Function[input,
	(* side effects *)
	(* RETURN *)
	True <- accept change
	False <- prevent default
	_String <- will be written instead
]

One can completely bypass the default reevaluation and use side-effects only

Module[{r},
  Manipulate[Graphics[Disk[{0,0}, r//Offload]],
    {{radius, 1}, 0,1},
    "UpdateFunction" -> Function[value,
      r = value;
      False (* always reject *)
    ]
  ]
]

However, we do recommend to use InputRange directly instead of Manipulate for such cases.

JIT Transpiler

Manipulate, as well as Animate, uses a diff algorithm that detects and tries to convert manipulated expressions to more optimized ones that utilize granular updates. If the diff algorithm fails, it will use full reevaluation and update the shown expression accordingly.

Our transpiler does not cover all symbols and is limited to the following for now:

  • Line, Point, Polygon, Tube, Arrow, Disk, Circle, Sphere, Cuboid, Rectangle, Text
  • GraphicsComplex in the context of Graphics3D
  • Image
  • PlotLabel in the context of Graphics
  • LineLegend, PointLegend, SwatchLegend

which is a good subset to cover the output produced by Plot, Plot3D and many others standard functions. What will not be supported in the near future:

  • PlotRange mutations are ignored
  • adding/removing Line, Point and etc primitives at runtime leads to deoptimization
  • changing color or opacity leads to full reevaluation

Tips for better performance

If you still want to use Manipulate on some complex expressions, there are some tricks to avoid JIT engine failures:

  • Try to keep the number of curves/traces/polygons expressions the same if possible. Try not to add new entities to your graphs.
  • PerformanceGoal->"Speed" is also a good option for 3D plots.
  • Mesh->None might also help.
  • PlotRange->Full or set it manually, it can help to avoid fragmentation of line segments
  • Avoid changing colors, opacity

Debugging

To see the latest message of JIT failure - evaluate the symbol:

CoffeeLiqueur`Extensions`Manipulate`Diff`$lastJITFailure

Portability

Same as for Animate, Manipulate widgets can be shared as MDX or HTML in automatic mode.

Keep the number of possible states determined by all your sliders and selection boxes below 500-600.

MMAView

MMAView wrapper allows to use native Wolfram Engine rendering engine for manipulated expressions. It uses a parallel kernel to rasterize the provided expression and stream updates to the frontend.

Manipulate[Plot3D[Sin[n x] Cos[n y], {x,-1,1}, {y,-1,1}], {n, 1, 5, 1}] // MMAView

It literally streams uncompressed raster images in real-time. Please do not overuse it

Supported output forms

On this page