5
$\begingroup$

I'm looking for some construction of progress indicator, with chars, numbers, etc... but without use of any Dynamic functions (Monitor and etc...). The Any ergonomic tools for the command line kernel? looks pretty, but this is for command line. I'm looking something to use in notebook.

$\endgroup$
2
  • $\begingroup$ Why do you need to avoid Dynamic? $\endgroup$
    – C. E.
    Commented Dec 1, 2019 at 11:20
  • $\begingroup$ @C.E., because of crashing of dynamic updating of notebook, and then I don't know is the process crashed also or only dynamic updating crashed, or both, I have no any feedback. I'm looking for some conservative and robust progress indicator. $\endgroup$
    – Dragutin
    Commented Dec 1, 2019 at 11:35

2 Answers 2

6
$\begingroup$

Here is one approach, based on @b3m2a1's excellent answer here:

Attributes[StaticMonitor] = {HoldAll};
UpdateMonitor[] := Null;
StaticMonitor[expr_, mon_] :=
 Block[
  {UpdateMonitor, boxID = ToString@Unique[]},
  PrintTemporary[RawBoxes@TagBox[ToBoxes@mon, boxID, BoxID -> boxID]];
  UpdateMonitor[] := FrontEndExecute@FrontEnd`BoxReferenceReplace[
     FE`BoxReference[
      FE`Evaluate@FrontEnd`EvaluationNotebook[],
      {{boxID}},
      FE`BoxOffset -> {FE`BoxChild[1]}
      ],
     ToBoxes@mon
     ];
  expr
  ]

Since we can't rely on Dynamic to automatically trigger updates, we need to call UpdateMonitor[] to force the update. The actual updating is done by replacing the contents on the cell created by PrintTemporary using the BoxReference* utilities explained in this answer. One could also replace the entire cell created by PrintTempoary, but that leads to undesirable flashing of the scrollbar.

Here is how it looks like in action:

StaticMonitor[
 Table[
  [email protected];
  UpdateMonitor[];
  i,
  {i, 10}
  ],
 ProgressIndicator[i, {0, 10}]
 ]

enter image description here

$\endgroup$
2
  • $\begingroup$ where is FrontEnd package gone in M12 ? $\endgroup$
    – Dragutin
    Commented Dec 4, 2020 at 20:04
  • $\begingroup$ @Dragutin What exactly do you mean? For me, the code works as expected in Mathematica 12.1. (The functions in FrontEnd` and FE` are built-in functions/symbols and not really part of any package, so I don't think they can ever be missing, unless they are completely removed at some point) $\endgroup$
    – Lukas Lang
    Commented Dec 5, 2020 at 10:47
2
$\begingroup$

The folllowing solution is based on some functionalities of https://github.com/Ludwiggle/JWLS_2

In particular, we borrow the webListenerF function, the refresh function and the refresh.wl file from the JWLS_2 project. refresh.wl is a StringTemplate that the refresh function uses to create a dynamic HTML page; such HTML page will serve as our monitor/progress indicator.

What you need:

  1. Download the template from https://github.com/Ludwiggle/JWLS_2/blob/master/JWLS_2_kernel/refresh.wl and put it in your working directory.
  2. Copy the webListenerF function definition from line 55 to line 77 of https://github.com/Ludwiggle/JWLS_2/blob/master/JWLS_2.sh
  3. Copy the refresh function definition from line 139 to 144 of the same JWLS_2.sh script above

Usage Example

Let's say you have some computation in a loop and you want to monitor the value of a variable g:

First of all, activate the socket with SocketListen[5859, webListenerF] . Then create and open the HTML page that monitors the value of g with refresh[HoldForm @ g] // SystemOpen .

Now you can start your loop process where g gets updated, something like

Clear[g,k]     
k = {RandomReal[]};

While[True,
      AppendTo[k, RandomReal[]];
      g = ListLinePlot[k, PlotMarkers -> {Automatic, 10}];
      [email protected]]

Check your browser and enjoy.

enter image description here

Cons: It works outside the notebook interface.

Pros: It works without the notebook interface.

Notes:

The refresh function takes the page refresh interval in milliseconds as a second argument.

For smoother animations, modify the webListenerF to export rasters instead of vector graphics. Then add the proper HTML tags in the template.

For maximum efficiency and smoothness, define the whole computation inside refresh, so that the kernel executes your code while synchronously serving the javascript client.

If something goes wrong try to close and reopen the socket.

$\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.