3
$\begingroup$

I am using Manipulate for a rather intricate front end for data visualization. I was getting very sluggish performance and was able to boil the problem down to a very similar question (Why does Manipulate execute the expression twice?). The suggestions of using ContinuousAction->False and TrackedSymbols does not seem to work in this case.

Let's simplify the problem by producing a simple array of numbers and mapping a simple function through them. The array of numbers needs to change dynamically, here we just change the length based on a manipulation parameter, i:

manipulateSlow[] := Module[{data, updated},
  Manipulate[
    Print[i];
    data = RandomReal[{0, 1}, 100*i];
    updated = Map[Sin, data];
  , {i, {1, 2, 3}}]]

manipulateFast[] := Module[{updated},
  Manipulate[
    Print[i];
    updated = Map[Sin, RandomReal[{0, 1}, 100*i]];
  , {i, {1, 2, 3}}]]

When one plays with the parameter i in manipulateSlow

manipulateSlow[]

the code internal to Manipulate is called multiple times. This is in contrast to manipulateFast

manipulateFast[]

where when fiddling with the parameter i the code internal to Manipulate is only called once per manipulation.

This example is, of course, just a toy. In my real application the process of RamdomReal is replaced by a much slower data reading function. Calling it multiple times is not an option.

EDIT:

I lied when previously saying that TrackedSymbols does not work. The follow fixes the issue of multiple Print evaluations.

manipulateFixed[] := Module[{data, updated},
  Manipulate[
    Print[i];
    data = RandomReal[{0, 1}, 100*i];
    updated = Map[Sin, data];
  , {i, {1, 2, 3}},TrackedSymbols :> {i}]]

I must be confused about how TrackedSymbols changes the evaluation process. What is happening inside of manipulateFast that does not cause the evaluation to occur twice?

$\endgroup$
3
  • 1
    $\begingroup$ Please expand on what you mean by "TrackedSymbols does not seem to work". Here if I add TrackedSymbols :> {i} then there is only one Print per change of i. $\endgroup$ Sep 6, 2013 at 20:13
  • $\begingroup$ Simon, thanks for the quick response. Your suggestion does work. I must have been confused as to how TrackedSymbols worked. I'll look into this more. $\endgroup$
    – leibs
    Sep 6, 2013 at 21:58
  • $\begingroup$ Off-topic: I would use something like Button or ActionMenu for triggering actions. SetterBar is rather intended to be variable's values setter, ofc it does not mean only for that purpose. Also, I strongly recommend using DynamicModule to have more control of what's happening. $\endgroup$
    – Kuba
    Sep 7, 2013 at 8:12

1 Answer 1

5
$\begingroup$

The reason Manipulate evaluate its expression twice vs. one time can be easily seen by simplifying the problem. It is due to data dependency of the variables used.

Let look at the case where Manipulate updates only one time first.

Manipulate[
 Print[i];
 x = i;
 , {i, {1, 2, 3}}
 ]

Here, when clicking on the button to change i, Manipulate updates its expression as expected. Inside the expression, x was also changed. However, you'll see that the expression is only evaluated once (print only prints once).

Lets compare the above, to the following case, where the only difference is that now x after being modified, it also appears in the right hand side of an assignment to a different variable y (make sure to restart the kernel again, so we are starting from fresh state, just to be safe)

Manipulate[
 Print[i];
 x = i;
 y = x;
 , {i, {1, 2, 3}}
 ]

Now clicking on the button, you'll see the print twice.

Why you ask? It is because now Manipulate saw that the change of x is not a superficial change, but a change that is used for a computation in the next step. So, there is a data dependency on this change. Mathematica actually keep track of data dependency between variables in dynamic expressions to minimize and optimise the updates needed.

Hence this is an actual state change. This has the effect of needing an expression refresh again. So that is why you see the print show up again. This is as if you had a hidden slider that represent the x above, and someone moved the slider after clicking the button.

When you add Tracking, you are telling Manipulate which variables to actually track. So now Manipulate does not care about any other changes, and only will track the variables listed

Manipulate[
 Print[i];
 x = i;
 y = x;
 , {i, {1, 2, 3}},
 TrackedSymbols :> {i}
 ]

The bottom line in all of this? do NOT use global variables inside Manipulate.

$\endgroup$
2
  • $\begingroup$ Thanks, very succinct. It seems to me that, in most cases, TrackedSymbols should always match the list of manipulated variables used inside Manipulate. Can we come up with an example where we wouldn't want this behavior? Sorry for so much follow up, just trying to really nail this issue down. $\endgroup$
    – leibs
    Sep 6, 2013 at 23:27
  • $\begingroup$ @leibs the default is Full for tracking for Manipulate. And from help on TrackedSymbols it says on this option: symbols that appear explicitly in the input expression (notice the word appear explicitly). In the example above, x and y are these. They are global variables, but appeared in the expression also, hence they were tracked automatically. $\endgroup$
    – Nasser
    Sep 6, 2013 at 23:32

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.