4
$\begingroup$

I'm writing a demonstration that has complicated inter-dependencies among controls that can be time-consuming to evaluate. It's working well, except that it breaks when I try to use autorun. I think the problem is that when a variable is changed by autorun, the TrackingFunction for controls associated with that variable isn't called. Is there some way to trap changes to a variable without copying all my tracking functions into the body of the manipulate?

In this MWE, I'd like the variable a to be updated by autorun, as if the slider itself were being moved, without adding "a=m+1" to the body of the Manipulate.

Manipulate[
{m, a},
 {{a, 2}, None},
 {{m, 2, Dynamic[m]}, 2, 10, 1,
   TrackingFunction -> (m = #; a = m + 1; & )},
 TrackedSymbols -> {m}, AutorunSequencing -> {2}]

(I'm not sure "animation" is a good tag for this, but I'm new and can't create "animate" or "autorun")

$\endgroup$
  • 2
    $\begingroup$ The normal autorun runs through the range of one variable but sets all the other variables to their initial values, and then moves on to the next variable in the autorun sequence. Since no control is activated (and a variable can have multiple controls with multiple tracking functions), you're right that the TrackingFunction is not called. Autorun is of limited sophistication. $\endgroup$ – Michael E2 Jan 18 at 1:25
  • $\begingroup$ Is there anything comparable to ControlActive that would tell me a variable has been changed by autorun? Or is there a way to provide autorun functionality in a demonstration using Animate? $\endgroup$ – Stephen Eubank Jan 18 at 2:13
  • $\begingroup$ $ControlActiveSetting is true while autorun is running, and ControlActive works as if a control is active. Is that what you mean? (By "demonstration," do you mean the Wolfram Demonstrations Project, which has its own special requirements?) $\endgroup$ – Michael E2 Jan 18 at 2:47
0
$\begingroup$

Michael E2 inspired me to bite the bullet and move stuff out of the tracking functions into manipulate's first argument and instead use additional variables to allow testing whether the state of each has changed. I also added a new variable ("monkeyLives" in the code below) that can only be changed by Autorun and test that to see where the change is coming from. Finally, I built a mapping from values of the new variable to entire parameter sets, e.g., "tab" in the code below. (Something like animating bookmarks, I suspect.)

But I still had a problem making the Dynamic displays in the control area update. The example below has a slider controlling the variable "a", which is used to plot a line with slope "a". When monkeyLives changes, "a" is also changed. The plot and values of both variables are updated as expected, but the only way I could make the slider update while Autorun is happening was to add a call to FinishDynamic[]. Without it, the Slider did not update until Autorun was paused. Also, you have to be very careful with initializations, since Autorun re-initializes all the variables often.

Because I'm trying to make a demo for the Wolfram Demonstrations Project, I think I'm constrained to use Manipulate and Autorun. I'm sure this could be managed more easily using DynamicModule and Animate, but I also suspect there's unnecessary crud in the code below that's just left over from my haphazard attempts to make this work. I would appreciate any tips on how to make this work more cleanly and efficiently, because my goal is to apply this pattern to a much more complicated Manipulate.

    tab = Table[2 i, {i, 1, 4}];
Manipulate[
 If[ControlActive[monkeyLives, oldLives] != oldLives,
  a = tab[[monkeyLives]];
  olda = a;
  oldLives = monkeyLives;
  FinishDynamic[];
  ];
 If[ControlActive[a, olda] != olda,
  olda = a;
  ];
 olda = Dynamic[a];
 oldLives = Dynamic[monkeyLives];
 plot = Plot[a x, {x, 0, 1}, PlotRange -> {0, 10}];
 {a, olda, Dynamic[Show[plot]], monkeyLives, oldLives, 
  ControlActive[monkeyLives, "Off"]}
 ,
 {{monkeyLives, 0}, 1, Length[tab], 1, 
  None}, {{oldLives, monkeyLives}, None},
 {{a, olda}, 1, 10, 1, None}, {{olda, olda}, 1, 10, 1, None},
 Row[{Dynamic[a], Slider[Dynamic[a], {1, 10, 1}]}],
 {{plot, plot}, None},

 Initialization :> (
   a = olda = 1;
   plot = Plot[a x, {x, 0, 1}, PlotRange -> {0, 10}]
   ), TrackedSymbols -> {a, monkeyLives}, 
 AutorunSequencing -> {{1, 10}}]
| improve this answer | |
$\endgroup$

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.