4
$\begingroup$

Normally, when using Manipulate[expr, controls, options], the graphics updating should be carried out at the very end of expr.

But now I encounter a situation where the graphics result is evaluated at each step inside a double-Fold-iteration. Yes I can still adopt the method mentioned above and write following code,

DynamicModule[{g},
 Manipulate[
  Module[{a},
   Fold[(
      k = #2;
      Fold[(a = #2; g = v[a, k]; Pause[.05]) &, {}, Range[5]]
     ) &, {}, Range[15]];
   Dynamic@g
  ],
 {{k, 1}, ControlType -> None},
 TrackedSymbols :> {},
 SynchronousUpdating -> Automatic,
 Initialization :> (v[a_, k_] := Plot[Sin[x (a + k x)], {x, 0, 6}])]
]

But the problem is that I will have to first wait for the double-Fold-evaluation to complete and only after this can I see the updates in a queued sequence. The code I used here is but an over-simplified example and the actual code will take much longer time for computation. I wonder if it is possible to do the graphics updating at every iteration step when v[a, k] is evaluated?

$\endgroup$

3 Answers 3

2
$\begingroup$

Here's a possible way. The question is how one wants to trigger the double-Fold calculation to begin. In this example, I used a Button with Method -> "Queued".

Manipulate[
 Dynamic@g,

 {{k, 1}, ControlType -> None},
 {{g, Graphics[{}, AspectRatio -> 1/GoldenRatio]}, ControlType -> None},
 {{v, v}, ControlType -> None},
 Button["go",
   Module[{a},
    Fold[(k = #2; Fold[(a = #2; g = v[a, k]; Pause[.05]) &, {}, Range[5]]) &, {}, Range[15]]],
   Method -> "Queued"],
 TrackedSymbols :> {}, SynchronousUpdating -> Automatic, 
 Initialization :> (v[a_, k_] := Plot[Sin[x (a + k x)], {x, 0, 6}])]

Edit

Here a simulation of the Fold. Unfortunately, nesting the Dynamics interferes with a clean modeling of Fold. One is better off using UpdateInterval than Pause. Pause happens in the kernel and can cause synchronization issues.

Manipulate[
 Dynamic[
  k = First@k0;
  a0 = Range[5];
  Dynamic[Refresh[
    a = First @ a0;
    If[Length@a0 > 1,
     a0 = Rest @ a0,
     k = First @ k0; If[Length@k0 > 1, k0 = Rest @ k0]];
    v[a, k],
    TrackedSymbols :> {}, UpdateInterval -> 0.05]]
  ],

 {{k, 1}, ControlType -> None}, {{a, 1}, ControlType -> None},
 {{k0, Range[15]}, ControlType -> None}, {{a0, Range[5]}, ControlType -> None},
 {{v, v}, ControlType -> None},
 TrackedSymbols :> {}, 
 Initialization :> (v[a_, k_] := Plot[Sin[x (a + k x)], {x, 0, 6}, PlotLabel -> {k, a}];)]

N.B. The Fold example in the OP just models a nested Do loop. To model a full fledged fold, a fuller is needed to work with.

$\endgroup$
6
  • $\begingroup$ Your solution exactly solves my problem, thank you Micheal E2! $\endgroup$
    – saturasl
    Commented Jun 18, 2013 at 23:53
  • $\begingroup$ @saturasl Thanks. I just added another solution, but the Button one is cleaner and less likely to cause problems as features are added to the demonstration. $\endgroup$
    – Michael E2
    Commented Jun 19, 2013 at 0:00
  • $\begingroup$ @Micheal E2 I just got a trival question: In your Button solution, the current value of k can not be shown even with {Dynamic[k], Dynamic[g]}, because the evaluation is done outside the main body. I wonder if we could show both k and g simultaneously? $\endgroup$
    – saturasl
    Commented Jun 19, 2013 at 0:18
  • 1
    $\begingroup$ @saturasl Try Dynamic[k, TrackedSymbols :> {k}] instead of just Dynamic[k]. Or Dynamic@Refresh[k, TrackedSymbols :> {k}]. $\endgroup$
    – Michael E2
    Commented Jun 19, 2013 at 2:04
  • 1
    $\begingroup$ It works, thanks! I also figured out the meaning of {{v, v}, ControlType -> None}: Because controls format are executed in advance to the Initialization options. So when firstly executing control, a undefined symbol v is asigned to the variable v; then while executing initialization, the symbol v is defined to be a function name, therefore the variable v now will be automatically recognized by the local master kernel as a function name. $\endgroup$
    – saturasl
    Commented Jun 19, 2013 at 5:37
2
$\begingroup$

You need to render g in FrontEnd before your Fold (or anything that changes g) is evaluated, thus you can monitor all changes happened to g in real-time. Also, you do not need Manipulate here. Something like this would be sufficient:

Dynamic[g]
Module[{a, k, v},
  v[a_, k_] := Plot[Sin[x (a + k x)], {x, 0, 6}];
  Fold[(k = #2;
     Fold[(a = #2; g = v[a, k]; Pause[.05]) &, {}, Range[5]]
     ) &, {}, Range[15]]
  ];

Or if you want to keep g local:

DynamicModule[{g},
  Cell[BoxData[MakeBoxes[Dynamic[g]]], "Output"] // CellPrint;
  Module[{a, k, v},
   v[a_, k_] := Plot[Sin[x (a + k x)], {x, 0, 6}];
   Fold[(k = #2;
      Fold[(a = #2; g = v[a, k]; Pause[.05]) &, {}, Range[5]]
      ) &, {}, Range[15]]
   ]
  ];
$\endgroup$
1
  • $\begingroup$ Yes you are right. Actually me current code is just in the first form you provided. However I want to submit my FEM code to WolframDemonstrationProject, so I will have to convert it using Manipulate. Still, thanks for your second code, there is something new to me. $\endgroup$
    – saturasl
    Commented Jun 18, 2013 at 20:25
0
$\begingroup$

I figured out a solution, using nested Refresh to simulate the two Folds in my previous code. In this way the graphics updating can still be put at the end of the innermost Refresh,

DynamicModule[{a = 1, k = 1, kprev = 1},
 Manipulate[
  Refresh[
   Refresh[
    Pause[.05];
    If[k != kprev, kprev = k; a = 1];
    g = v[a, k];
    Row[{Dynamic[a], Dynamic[k], Dynamic[g]}, ", "],

    If[run && a <= 5, a++];
    UpdateInterval -> If[run, If[a <= 5, 0, Infinity], Infinity]
   ],
   If[run && a > 5 && k <= 10, k++];
   UpdateInterval -> If[run, If[k <= 10, 0, Infinity], Infinity]
  ],

 {{run, False}, {True, False}, ControlType -> Checkbox},
 TrackedSymbols :> {run, a, k},
 SynchronousUpdating -> Automatic,
 Initialization :> (v[a_, k_] := 
 Plot[Sin[x (a + k x)], {x, 0, 6}, ImageSize -> 200])
]]

The remaining problem is, in this way the nested folds are destroyed and so is the efficiency advantage of using Fold...

$\endgroup$
1
  • $\begingroup$ I managed to come up with a possible solution, but this one may have efficiency issue. Hope someone can help to improve it. $\endgroup$
    – saturasl
    Commented Jun 18, 2013 at 22:19

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.