Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

When trying to make an optimized version of my plotRange fonction I faced a problem of catching the "Preemptive" evaluations generated by the FrontEnd from withing the main evaluation loop.

Consider the following:

ClearAll["Global`*"]
xr[r__] := (xRange = {r}; None);
yr[r__] := (yRange = {r}; None);
nb = CreateDocument[{Plot[Sin[x], {x, 0, 6 Pi}, Ticks -> {xr, yr}]}];
{xRange, yRange}
Pause[1];
{xRange, yRange}
NotebookClose[nb]

{xRange, yRange}

{{-0.392699, 19.2423}, {-1.04167, 1.04167}}

One can see that the first evaluation of {xRange, yRange} returns undefined symbols because at the moment of its evaluation the functions xr and yr are still not evaluated via a "Preemptive" link by the FrontEnd. But after waiting one second these functions are already evaluated and xRange, yRange are defined. Because I need these values for further evaluations I need to delay the main loop until the "Preemptive" evaluations will be done. (An alternative solution would be to force the FrontEnd to perform its evaluations in the main loop.)

One possible way to solve the problem is to initiate a Dialog which will wait for the Return generated by the FrontEnd. But "Preemptive" evaluations go past the Dialog and do not allow the return from it (the following code freezes the kernel):

Dialog[xr[r__] := (xRange = {r}; None);
 yr[r__] := (yRange = {r}; None; NotebookClose[nb]; 
   Return[{xRange, yRange}]);
 nb = CreateDocument[{Plot[Sin[x], {x, 0, 6 Pi}, 
     Ticks -> {xr, yr}]}];]

Is it possible to catch the "Preemptive" evaluations from the main loop in some way?

UPDATE

Here is a comparison of my original Rasterize-based version and the new FinishDynamic-based:

gr = Plot[Sin[x], {x, 0, 6 Pi}];
plotRange[plot : (_Graphics | _Graphics3D)] := 
 Quiet@Last@
   Last@Reap[
     Rasterize[
      Show[plot, PlotRangePadding -> None, Axes -> True, 
       Ticks -> (Sow[{##}] &), DisplayFunction -> Identity], 
      ImageResolution -> 1]]
Table[plotRange[gr], {100}]; // AbsoluteTiming

plotRange[plot : (_Graphics | _Graphics3D)] := 
 Quiet@Last@
   Last@Reap[(nb = 
       CreateDocument[{Show[plot, Axes -> True, 
          Ticks -> (Sow[{##}] &), PlotRangePadding -> None, 
          DisplayFunction -> Identity]}, ShowCellBracket -> False, 
        WindowFrame -> "Frameless", WindowElements -> {}, 
        WindowSize -> 1, Antialiasing -> False, Editable -> False, 
        Magnification -> 1, Saveable -> False, 
        WindowClickSelect -> False, WindowFloating -> False, 
        WindowFrameElements -> {}, WindowMovable -> False, 
        WindowSelected -> False, WindowTitle -> ""];
      FinishDynamic[]; NotebookClose[nb])]
Table[plotRange[gr], {100}]; // AbsoluteTiming

{2.828125, Null}

{8.406250, Null}

The original Rasterize-based version is 3 times faster.

share|improve this question
    
I got {{-0.392699, 19.2423}, {-1.04167, 1.04167}} from both of the two evaluations. My system: v9 on win7 64bit. –  Silvia Jan 24 '13 at 0:17
1  
I reproduced it in v9 on Windows, but failed to reproduce it on my Macbook Air. But this behavior depends upon the ordering of Dynamic evaluations. Those orderings are specifically not guaranteed by Mathematica. –  John Fultz Jan 24 '13 at 11:21
    
@JohnFultz Does it mean that the code Reap[Rasterize[Show[plot, Ticks -> (Sow[{##}] &)]]][[2, 1]] do not guarantee that the ordering of ranges will always be standard: {xRange, yRange} and sometimes one can get {yRange, xRange}? –  Alexey Popkov Jan 25 '13 at 13:29
1  
@AlexeyPopkov No, I mean that the evaluation of the Ticks function, which is acting like a Dynamic in this case (even though no Dynamic was specified, it's resolved in a similar fashion), might be evaluated at any time relative to the ordering of the Shift+Enter evaluations. It might happen before the CreateDocument has finished evaluation, or shortly thereafter, or a very long time thereafter. That's why it behaves differently on different machines...because there is no guarantee...it's just evaluating when it can. –  John Fultz Jan 31 '13 at 8:31
add comment

1 Answer

up vote 14 down vote accepted

After the dynamic evaluation (in this case, your plot) has been displayed to the screen but before you wish to access the variables, evaluate:

FinishDynamic[];

Note that this function isn't selective. It will force every Dynamic in the entire system to update before it continues.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.