4
$\begingroup$

I have the toy Manipulate.

Manipulate[
 Graphics[{Red, PointSize[0.05], Point[{a, -1}]}, Frame -> True, 
  ImageSize -> Small, PlotRange -> {{4, 6}, {-2, 0}}], 
 Style["Some parameters", Bold], 
 {{a, 5}, 4, 6, Appearance -> "Labeled"}, 
 Button["Shifts", a = RandomReal[{4, 6}]], 
 Button["Experiment", tmp = {}; Do[{a = RandomReal[{4, 6}];
    tmp = Append[tmp, a]; 
    Print[tmp]; 
    Pause[0.5]}, {5}], 
  Method -> "Queued"], TrackedSymbols :> {a}, 
 ControlPlacement -> Left, SynchronousUpdating -> True]

All I need is to make "Experiment" button to work as if I click "Shifts" button 5 times in a run (slider with a should update each cycle, 5 times). Now it stays unchanged during experiment and only undates in the end, during last iteration of the loop.

To keep Do is not important but I need something that would emulate Append cycle.

PS. Why do I need that? I want to show students one effect on the market and it is important that they see in real time that a changes as a is the reason of that shifts (I could click it myself but it seems a bit unprofessional and boaring :).

$\endgroup$
3
  • $\begingroup$ Button["Experiment", Do[{a = RandomReal[{4, 6}]; Pause[0.5]}, {5}], Method -> "Queued"] You forgot the curly braces around the 5 $\endgroup$ Feb 13 '16 at 22:36
  • 1
    $\begingroup$ @Dr.belisarius. The { } aren't required in versions sufficiently later than yours, which I believe to be V9. $\endgroup$
    – m_goldberg
    Feb 14 '16 at 2:11
  • $\begingroup$ @Dr.belisarius, I'm on version 10.3, but I've made a change that you suggested and updated post. Any further ideas? $\endgroup$
    – garej
    Feb 14 '16 at 6:34
2
$\begingroup$

DynamicWrapper can help.

Manipulate[
 DynamicWrapper[            (* allows for the iteration step below to be updated *)
  Dynamic@                  (* this Dynamic causes Graphics to depend on its variables *)
   Graphics[{Red, PointSize[0.05], Point[{a, -1}]}, Frame -> True, 
    ImageSize -> Small, PlotRange -> {{4, 6}, {-2, 0}}],
  Refresh[                  (* iteration step *)
   If[iterate > 0,             (* update  a *)
    iterate--;
    a = RandomReal[{4, 6}]
    ],
   UpdateInterval -> 0.5,      (* update every half second... *)
   TrackedSymbols -> {}]       (* and NOT when  iterate  or  a  is changed *)
  ],
 Style["Some parameters", Bold],
 {{a, 5}, 4, 6, Appearance -> "Labeled"},
 {{iterate, 0}, ControlType -> None},
 Button["Shifts", a = RandomReal[{4, 6}]],
 Button["Experiment",
  iterate = 5,                           (* set number of iterations *)
  Enabled -> Dynamic[iterate == 0]],     (* turn off button while experimenting *)
 TrackedSymbols :> {},                   (* so the whole is not reevaluated; see note *)
 ControlPlacement -> Left, SynchronousUpdating -> True]

The iteration step is run every 0.5 seconds, but a is updated only when iterate > 0. Between experiments, it is basically a no-op. If you use another variable wait, use UpdateInterval -> wait, and toggle wait between 0.5 and Infinity, the continual updating may be stopped between experiments. The 0.5 sec. updating does not affect the performance of this specific demonstration. I mention this alternative in case it is a problem in other use-cases.

Note: Why TrackedSymbols :> {} -- The trick used here is to have to separate (or parallel) pieces of code in the body of Manipulate. These are created by

DynamicWrapper[Dynamic[code1], code2]

The first argument of DynamicWrapper is not dynamically updated by default*, so code1 needs to be wrapped in Dynamic for it to respond independently to changes in a. We do not want the whole DynamicWrapper to be re-evaluated whenever a or iterate changes, because it would cause the iteration step to be evaluated again, too. Thus a and iterate would be updated, without the 0.5 second wait, and their change would trigger another immediate update, and so on. In short, the experiment would be short, with the five iterations happening as fast as possible.

*The documentation is a little confusing about this: "When used to display e in a notebook, DynamicWrapper[e,expr] is effectively equivalent to Dynamic[expr;Refresh[e,None]]." But this is not literally true, at least in all cases (including this one), as can be easily checked.

$\endgroup$
2
  • $\begingroup$ I would never find that sort of solution: that is impressive! $\endgroup$
    – garej
    Feb 14 '16 at 22:12
  • $\begingroup$ @garej Thank you! $\endgroup$
    – Michael E2
    Feb 15 '16 at 0:32
2
$\begingroup$

Update

OK, I think I understand now. It can sort of be done by faking the manipulator current value label. The slider still won't move in real time, but the value displayed on the right will update as it should.

I don't know how to get the slider to update as you want. The slider movement seems to be controlled too deeply for me get at. Maybe abandoning Manipulate and going down to the DynamicModule level might work, but I don't have time to try that at the moment.

Manipulate[
  Graphics[{Red, PointSize[0.05], Point[{a, -1}]},
    Frame -> True, ImageSize -> Small, PlotRange -> {{4, 6}, {-2, 0}}],
  Style["Some parameters", 12, Bold],
  Dynamic @ Row[{Control[{{a, 5}, 4, 6}], "  ", a}],
  Button["Shifts", a = RandomReal[{4, 6}]],
  Button["Experiment",
    Do[a = RandomReal[{4, 6}]; Pause[.5], 5],
    Method -> "Queued"],
  ControlPlacement -> Left,
  SynchronousUpdating -> True]

demo

$\endgroup$
1
  • $\begingroup$ I've noticed your edit. Let me try again to explain ;) If we click Shifts, the point shifts and slider a value shifts. Ok? If we click Experiment, the point shifts 5 times but slider a value shifts only once - during last iteration. Is there a way to make slider a value to shift 5 times - each time when the point shifts? Or there is not allowed in Manipulate? $\endgroup$
    – garej
    Feb 14 '16 at 15:43

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.