14
$\begingroup$

How to track Initialization step by step? Any tricky solution is ok. One condition, x should be DynamicModule variable.

DynamicModule[{x}, 
   Dynamic[x], 
   Initialization :> ( 
      x = 1; 
      Pause@1; 
      x = 2; 
      Pause@1; 
      x = 3; 
   )]

I want the progress to be reflected in Dynamic[x].

$\endgroup$
7
  • 1
    $\begingroup$ You can always use Print :) DynamicModule[{x}, Dynamic[x], Initialization :> (x = 1; Print["x=2"]; x = 2; Print["x=3"]; x = 3) ] $\endgroup$
    – Nasser
    Commented Sep 17, 2014 at 21:14
  • $\begingroup$ @Nasser Well, right, I should stress out that I want this tracking to be reflected in Dynamic updating :) Moreover, if you riffle your code with Pause you can see that it isn't working like one could expect. $\endgroup$
    – Kuba
    Commented Sep 17, 2014 at 21:15
  • $\begingroup$ I am not sure I understand what you mean by this tracking to be reflected in Dynamic updating Since Initialization is processed once from top down. (to generate the initial expression). Once this is done, Initialization basically goes away. $\endgroup$
    – Nasser
    Commented Sep 17, 2014 at 21:29
  • $\begingroup$ @Nasser Not 100% true, Initialization evaluates every time you open a cdf/nb with visible related DynamicModule. I would like to see x switching values while Initilization is running. The Dynamic cell is already there, it's just waiting for Init to complete, even if you use SynchronousInitialization->False. I need it to behave like I've described :) $\endgroup$
    – Kuba
    Commented Sep 17, 2014 at 21:37
  • $\begingroup$ I do not think what I said is different from what you are saying. Initialization is evaluated to generate the dynamic expression first time it is needed to be displayed on the screen. $\endgroup$
    – Nasser
    Commented Sep 18, 2014 at 0:21

2 Answers 2

12
$\begingroup$

By default, DynamicModule uses SynchronousInitialization -> True. This causes the initialization to be performed on the preemptive link, disabling any updates to the front-end. In particular, print statements, cell creation and dynamic box updates will all be deferred until the initialization completes.

If we wish to monitor that initialization within the notebook itself, we must turn off synchronous initialization. If we do so, then any of a number of strategies are possible, such as...

... using Monitor to watch x change within a temporary cell:

DynamicModule[{x}
, Dynamic[x]
, SynchronousInitialization -> False
, Initialization :> Monitor[x = 1; Pause@1; x = 2; Pause@1; x = 3, x]
]

... or CellPrint to watch x change within a permanent cell:

DynamicModule[{x}
, Dynamic[x]
, SynchronousInitialization -> False
, Initialization :>
    (CellPrint@Dynamic@x; x = 1; Pause@2; x = 2; Pause@2; x = 3)
]

... or even simply using Print to print out some intermediate information:

DynamicModule[{x}
, Dynamic[x]
, SynchronousInitialization -> False
, Initialization :>
    (x = 1; Print@"1st"; Pause@2; x = 2; Print@"2nd"; Pause@2; x = 3)
]

We can even monitor the initialization of x from within the DynamicModule by overriding the default UpdateInterval -> Infinity on Dynamic:

DynamicModule[{x}
, Dynamic[x, UpdateInterval -> 0]
, SynchronousInitialization -> False
, Initialization :> (x = 1; Pause@1; x = 2; Pause@1; x = 3)
, UnsavedVariables :> {x}
]

It is necessary to add x to the list of UnsavedVariables because without it the value of x will not be seen to change dynamically when the output cell is re-initialized in a new front-end session.

For Debugging Purposes

If debugging messages are our goal, and if it is not acceptable to perform asynchronous initialization for some reason, then a simple solution would be to write logging messages to an external file. That file could then be monitored in real-time using an external utility like tail.

It is possible, if ambitious, to use Mathlink to send debugging messages to a second front-end. See, for example, the chat application in this this question. Personally, I think this is overkill. I would probably spend the time getting the DynamicModule to work with asynchronous initialization instead.

$\endgroup$
2
  • $\begingroup$ Yes, but is there a way to such tracking to be reflected inside the DynamicModule in bahaviour of it`s variables? $\endgroup$
    – Kuba
    Commented Sep 18, 2014 at 9:56
  • 1
    $\begingroup$ @Kuba Yes. Please see the new variation using UpdateInterval. $\endgroup$
    – WReach
    Commented Sep 18, 2014 at 12:41
6
$\begingroup$

tl;dr;

Use SynchronousInitialization -> False and, in case of simple Dynamic[x], add TrackedSymbols: Dynamic[x, TrackedSymbols :> {x}] due to the bug mentioned below.


Finally I'm able to answer my question with understanding. Two years, no big deal :)

So I want Dynamic[x] to reflect the state of the initialization. The last example in WReach's answer does what I need but in a way I don't like. Dynamic with UpdateInterval->0 is a flood of unnecessary calls. Which will still be performed till that Dynamic is visible.

My understanding and solution to the problem

According to my explanation in:

all we need is to make Initialization code to be evaluated through the MainLink. SynchronousInitialization -> False serves that purpose.

Yet that fix is not working, we still see the initial value and then only the very last at the end.

DynamicModule[{x = 0},
 
 Dynamic[x],
 SynchronousInitialization -> False,
 Initialization :> (
   x = 1; Pause@1;  x = 2; Pause@1;   x = 3
  )
 ]

At this point, a beginner's morale will drop. This should work. Why isn't it? The answer is, come to StackExchange more often. There is a which interferes:

So my minimal example was too minimal:

DynamicModule[{x = 0},
 
 Dynamic[ x, TrackedSymbols :> {x}], 
 SynchronousInitialization -> False,
 Initialization :> (
   x = 1; Pause@1;
   x = 2; Pause@1;
   x = 3
   )
 ]

Probably the most verbose solution is Dynamic[x, TrackedSymbols :> {x}] which appears to be superfluous but at least it is clear.

Use whatever you want but there is usually something more than x so that bug can be missed.

Uff, works and fits my understanding of Kernel-FrontEnd communication.


Real life example

DynamicModule[{x = 0, init = False},
 Dynamic[
  If[
    init,
    Overlay[{
      Dynamic@ProgressIndicator[Appearance -> "Indeterminate"], 
      Dynamic[x, TrackedSymbols :> {x}]
      }, All, 1, Alignment -> Center,  BaseStyle -> 18
    ],
    x
  ],
  TrackedSymbols :> {init, x}
 ],
 SynchronousInitialization -> False,
 Initialization :> (
   init = True;
   x = 1; Pause@1;
   x = 2; Pause@1;
   x = 3; Pause[1];
   init = False;
   )]

enter image description here

$\endgroup$

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.