1
$\begingroup$

In working on a simple simulation I came across the following Manipulate quirk (bug?) and I want to know how to get around it. Here is the first pass code, which acts as expected (but is incorrect):

simpleBrownianSimulation[] := Module[{vels, nPts},
    Manipulate[
        vels = Table[RandomReal[{-1, 1}, 2], {Length[pts]}];
        nPts = Table[pts[[i]] + t*vels[[i]], {i, Length[pts]}];
        Graphics[{Blue, PointSize[0.02], Point[nPts]}, 
        PlotRange -> {{-5, 5}, {-5, 5}}],
        {{pts, {{0, 0}}}, Locator, LocatorAutoCreate -> True, Appearance -> None},
        {t, 0, 10, 0.05}
]];
simpleBrownianSimulation[]

The idea is to use the slider to trigger updates to the particles (stored in pts) position. This code correctly updates only if the slider is moved, but contains an error, since the position is computed always from the initial position of the particle, and the current time value. So to fix this, I changed it to:

simpleBrownianSimulation[] := Module[{vels, nPts, isSet = False},
    Manipulate[
    If[!isSet, nPts = pts; isSet = True];
    vels = Table[RandomReal[{-1, 1}, 2], {Length[pts]}];
    nPts = Table[nPts[[i]] + vels[[i]], {i, Length[pts]}];
    Graphics[{Blue, PointSize[0.02], Point[nPts]}, PlotRange -> {{-5, 5}, {-5, 5}}],
    {{pts, {{0, 0}}}, Locator, LocatorAutoCreate -> True, Appearance -> None},
    {t, 0, 10, 0.05}
]];
simpleBrownianSimulation[]

This code is correct, but it ANIMATES! It updates on its own regardless of whether the slider is being moved or not. I know that here the value of the slider is not used, that is fine. I just want to use it as an update trigger, and NOT have maniuplate update otherwise. Why is manipulate doing this and how can I fix it? Note that this is Mathematica 9, but this occurs both on the Windows and Mac versions.

$\endgroup$
1
  • 1
    $\begingroup$ Do not have to look at this now, but an advice: do not put Manipulate inside a Module. Put Module inside Manipulate. $\endgroup$
    – Nasser
    Commented Feb 25, 2014 at 23:21

1 Answer 1

3
$\begingroup$

Your code constantly updates because nPts is local to a module enclosing the Manipulate. If the Manipulate enclosed the module, your code wouldn't work as you would like, but it wouldn't be constantly updating.

Here is a much simpler example showing the same behavior.

Module[{n = 1}, Manipulate[Row[{"n = ", n++}], {t, 0, 5}]]

constantly updates, but

Manipulate[Module[{n = 1}, Row[{"n = ", n++}]], {t, 0, 5}]

doesn't.

I would take a different approach. I wouldn't use locators to add more particles to the simulation; rather I would use a ClickPane. Nor would I use a slider to generate update events; rather I would use a Button

Manipulate[
  If[update, 
     update = False; pts = Plus @@@ Transpose[{pts, RandomReal[{-1, 1}, {Length@pts, 2}]}]];
  ClickPane[
    Framed@Graphics[{Blue, PointSize[0.02], Point[pts]}, PlotRange -> {{-5, 5}, {-5, 5}}], 
    AppendTo[pts, #] &],
  {{update, False}, ControlType -> None},
  {{pts, {{0, 0}}}, ControlType -> None},
  Button["Update", update = True]]

manipulate

This is much simpler than your code, but still performs the simulation you are trying to implement. Give it a try and see if it satisfies your needs.

$\endgroup$
3
  • $\begingroup$ Cool, thanks. I guess the problem here is that for someone who normally programs Objective-C and Java/Swing, it seems like what manipulate does is update only if a control fires an event. However, for some reason, if inside the manipulate the value of a variable is changed which is not local to the manipulate, this somehow (magically?) triggers an update of the manipulates code. I see no reason why this is good, and this seems to be really non-obvious behavior. I do agree about button vs. slider. Goal was just to give a quick&dirty way to trigger updates. $\endgroup$
    – John
    Commented Feb 28, 2014 at 4:14
  • $\begingroup$ By non-obvious I mean that the event handling which must be in the background firing an update off to the manipulate shouldn't know anything about variable assignments, and manipulate shouldn't be updating without some sort of event, otherwise it is doing lots of unnecessary processing. $\endgroup$
    – John
    Commented Feb 28, 2014 at 4:15
  • $\begingroup$ @jcb. There is quite a bit of magic in Manipulate. It is designed to let people implement some fairly fancy GUIs without getting down and dirty with Mathematica's GUI primitives. If you want to work at a level closer to what you are used to, the lower level GUI elements are available. You might find DynamicModule more to your liking than Manipulate. Personally, I like Manipulate a lot. Compare my implementation of your simulation to what it would take in Java/Swing. I did it with less than 10 line of code. In Java it would take many, many more lines. $\endgroup$
    – m_goldberg
    Commented Feb 28, 2014 at 4:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.