6
$\begingroup$

I have asked this question before (here) and I thought that the issue is only when moving the Notebook window.

It appears that Manipulate is working in weird manner.

data = RandomReal[100, {10000, 10}];
Manipulate[
 Grid[{{RandomReal[100]}, {ListPlot[data[[;; , i]], 
     PlotLabel -> RandomReal[100], ImageSize -> 400, 
     PlotStyle -> Hue[RandomReal[1]]]}}], {i, 1, 10, 1}]

Manipulate updates its argument twice even if the window is static without moving.

enter image description here

This is really creates a big problem for me and all codes done in V9 are very slow running in V10.

Any help will be highly appreciated.

Update:

the suggested solution by Sjoerd C. de Vries works in this case but not in general as shown in this example:

Manipulate[
 a = Log[i];
 Grid[{{RandomReal[100]}, {ListPlot[a data[[;; , i]], 
     PlotLabel -> RandomReal[100], ImageSize -> 400, 
     PlotStyle -> Hue[RandomReal[1]], 
     PerformanceGoal -> "Quality"]}}], {i, 2, 10, 1}]

Thank you

$\endgroup$
  • $\begingroup$ Could you check to see whether the links below and the answer to this question solve your problem? $\endgroup$ – Sjoerd C. de Vries Feb 19 '15 at 6:58
  • $\begingroup$ @SjoerdC.deVries it does for this particulate example. I have a long Manipualte argument with a lot of computations. please check the update. $\endgroup$ – Algohi Feb 19 '15 at 7:41
  • 2
    $\begingroup$ For me, the same problem occurs in both V9 and V10 with OSX(10.9.5). Bug ?? $\endgroup$ – SquareOne Feb 19 '15 at 17:20
  • $\begingroup$ Related: (8072), (8373) $\endgroup$ – Mr.Wizard Feb 19 '15 at 17:54
5
$\begingroup$

It seems to me that this double evaluation is simply part of the mechanism of Manipulate. When the slider is dragged one expression is displayed, and when it is released another is displayed. I described this a bit in PolarPlot render oddities but here is another example. I use ControlActive to make the behavior explicit but same action is implicit without it.

Manipulate[ControlActive["foo", RandomReal[{0, i}]], {i, 2, 10, 1}]

Observe that while the slider is being dragged "foo" is displayed rather than a random number. When the slider is released the second expression is evaluated and displayed as a random number. If you wish to avoid the second evaluation you can store a copy of the result of the first evaluation and display it at that time:

DynamicModule[{x},
  Manipulate[a = Log[i];
    ControlActive[
      x = Grid[{{RandomReal[100]},
           {ListPlot[a data[[;; , i]], PlotLabel -> RandomReal[100], 
            ImageSize -> 400, PlotStyle -> Hue[RandomReal[1]]]}}],
      x
    ],
    {i, 2, 10, 1},
    TrackedSymbols :> {i}
  ]
]

Edit: added TrackedSymbols :> {i} to improve evaluation behavior.
See Michael's comment below for caveats.


Update

The method above has problems with quick clicks on the slider. This seems to solve the problem but I have only tested it briefly:

Manipulate[
  Block[{$ControlActiveSetting = False},
    a = Log[i];
    Grid[{{RandomReal[100]}, {ListPlot[a data[[;; , i]], PlotLabel -> RandomReal[100], 
      ImageSize -> 400, PlotStyle -> Hue[RandomReal[1]]]}}]
  ],
  {i, 2, 10, 1}, 
  TrackedSymbols :> {i}
]
$\endgroup$
  • 1
    $\begingroup$ The assignment to x usually causes a subsequent update. Hitting the + button of the animator causes two updates. If the + button is hit several times quickly, the subsequent increments to i cause only one update. If one waits the 3 sec. for $ControlActiveSetting to be set to False, then hitting the + button causes two updates. A quick click on the slider causes no recalculation of the ListPlot because $ControlActiveSetting never changes to True. Dragging the slider works as (I) expected. TrackedSymbols does not seem to solve all these issues. [I don't have a suggestion yet.] $\endgroup$ – Michael E2 Feb 20 '15 at 1:47
  • $\begingroup$ @MichaelE2 Thanks for the notes and corrections. TrackedSymbols :> {i} at least seems to help so I added it. $\endgroup$ – Mr.Wizard Feb 20 '15 at 15:11
  • 2
    $\begingroup$ @MichaelE2 With TrackedSymbols edit, two problems remain : 1/no recalculation of ListPlot when you quick click the slider (but dragging works), 2/ when you click on + or - button, the plot is now recalculated only once (as it should) but I notice that the bracket cell shows it evaluates once more (with no effect). $\endgroup$ – SquareOne Feb 24 '15 at 9:27
  • 1
    $\begingroup$ @SquareOne Yes, I knew that. That's what I meant that "TrackedSymbols does not seem to solve all these issues," but comments don't really give enough space for full explanations. I thought eventually I would solve the problem (or someone else would) but I failed to. It may be that $ControlActiveSetting is tracked by the FE instead of the kernel, and in any case, it is tracked no matter the setting of TrackedSymbols. (This is the reason for your second point.) $\endgroup$ – Michael E2 Feb 24 '15 at 12:26
  • $\begingroup$ @MichaelE2 Could you check my Update, please? $\endgroup$ – Mr.Wizard Feb 24 '15 at 22:16
3
$\begingroup$

Edit

This is the workaround I've found :

data = RandomReal[100, {10000, 10}];

Manipulate[
 Block[{$PerformanceGoal = "Quality", a}, a = Log[i];
  Grid[{{RandomReal[100]}, {ListPlot[a data[[;; , i]], 
      PlotLabel -> RandomReal[100], ImageSize -> 400, 
      PlotStyle -> Hue[RandomReal[1]], 
      PerformanceGoal -> "Quality"]}}]], {i, 2, 10, 1}]

a (which is a function of i) must be defined as a local value inside the Block and then set to its value.

It seems everything works as it should be (click and dragging the slider, click on buttons +/-)


Previous

As indicated the problem can be solved with the option $PerformanceGoal, but as the OP showed it is not enough here just to set the option inside ListPlot.

Let's take a simpler example :

Manipulate[i + 1; 
 ListPlot[RandomReal[10, 100], PlotStyle -> {Hue[RandomReal[]]}, 
  PlotLabel -> $PerformanceGoal, PerformanceGoal -> "Quality"], {i, 1, 10, 1}]

As a label, i just display the $PerformanceGoal and it is clear that when you click the + button, the plot is displayed : the first time with $PerformanceGoal set to "Speed" and the second time set to "Quality". Setting the option inside ListPlot seems to have no effect.

enter image description here

The problem is solved if you set $PerformanceGoal inside a Block. Here:

Manipulate[i + 1; 
 Block[{$PerformanceGoal = "Quality"}, 
  ListPlot[RandomReal[10, 100], PlotStyle -> {Hue[RandomReal[]]}, 
   PlotLabel -> $PerformanceGoal]], {i, 1, 10, 1}]

enter image description here

Update

HOWEVER, this is not the end of the story, because as commented the OP, the previous solution won't work for the particular case at the end of his post. My example was too simple : there is no variable i inside the ListPlot.

Let's make something more complicated, just multiply the RandomReal list by i (inside ListPlot):

Manipulate[i + 1;
 Block[{$PerformanceGoal = "Quality"}, 
  ListPlot[i*RandomReal[10, 10000], PlotStyle -> {Hue[RandomReal[]]}, 
   PlotLabel -> $PerformanceGoal]], {i, 1, 10, 1}]

You can check that will work too.

BUT if you set a=i then multiply RandomReal by a, now it won't work:
(note that I added a Pause inside the Block in order to see better the evaluations, it does not modify the problem)

Manipulate[i + 1; a = i;
 Block[{$PerformanceGoal = "Quality"}, Pause[0.5];
  ListPlot[a*RandomReal[10, 20000], PlotStyle -> {Hue[RandomReal[]]}, 
   PlotLabel -> $PerformanceGoal]], {i, 1, 10, 1}]

enter image description here

Note also that, though the $PerformanceGoal changes no more, you can clearly see that the code is evaluated twice, whether the slide is moved by clicking (not dragging), or the + or - buttons are clicked.

unless you do:

Manipulate[i + 1;
 Block[{$PerformanceGoal = "Quality", a}, Pause[0.5];
  a = i; ListPlot[a*RandomReal[10, 20000], 
   PlotStyle -> {Hue[RandomReal[]]}, 
   PlotLabel -> $PerformanceGoal]], {i, 1, 10, 1}]

enter image description here

Other strange behaviours

I have played a little bit with all this, and I also observed some other strange behaviours :

You can even have three evaluations if you do that :

Manipulate[a = i; Pause[0.5]; 
 Grid[{{RandomReal[100]}, {ListPlot[a*RandomReal[10, 100], 
     PlotLabel -> RandomReal[100], ImageSize -> 400, 
     PlotStyle -> Hue[RandomReal[1]]]}}], {i, 1, 10, 1}]

enter image description here

or if you put the same code into two separate cells, just one beneath the over, and then if you change the position of one slider, this is what happens :

Manipulate[i + 1; a = i;
 ListPlot[a*RandomReal[10, 100], PlotStyle -> {Hue[RandomReal[]]}, 
  PlotLabel -> $PerformanceGoal, PerformanceGoal -> "Quality"], {i, 1,
   10, 1}]

and the same

Manipulate[i + 1; a = i;
 ListPlot[a*RandomReal[10, 100], PlotStyle -> {Hue[RandomReal[]]}, 
  PlotLabel -> $PerformanceGoal, PerformanceGoal -> "Quality"], {i, 1,
   10, 1}]

gives

enter image description here

$\endgroup$
  • $\begingroup$ I tried to fit your solution to the second case in the question but it did not work. $\endgroup$ – Algohi Feb 19 '15 at 18:54
  • $\begingroup$ @Algohi You are right ! :( I did not test your specific problem, and the Block does not help ! I'll edit my post to mention that, and will do some other tests ... $\endgroup$ – SquareOne Feb 19 '15 at 22:04
  • $\begingroup$ @Algohi Did my workaround helped you to solve the different problems you had ? Are there any other problems you noticed ? $\endgroup$ – SquareOne Feb 24 '15 at 9:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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