# Estimating progress on plots

When plotting a slow function, it would be nice to know how much of the work has already be done. However due to the refinement algorithm, simply monitoring the integration variable doesn't give an useful estimate unless MaxRecursion is set to 0 (and it's clear that the best I can hope for is an estimate). For example, consider

Monitor[Plot[Pause[0.01];Sin[x],{x,0,100}],x]


This goes through the interval dozens of times, although the number of points in each iteration goes down.

Therefore my question: Is there any way to get a reasonable estimate of how much of a plot is already done?

• Interesting question. The problem is that you can't predict how many points will be added in each refinement step. Here's a refinement function to experiment with, if you like. I've been using both this code as well as a 2D version of it with a very slow to compute function, and from experience: the number of points added depends very much on the function: it could increase exponentially or stay near-constant. – Szabolcs May 24 '12 at 8:39
• However, if you know your function well (as I did), you'll be able to take good guesses. – Szabolcs May 24 '12 at 8:44
• @Szabolcs: Is that the algorithm Plot uses, or is it an alternative sampling algorithm to be used instead for a self-written Plot replacement? – celtschk May 24 '12 at 9:11
• I don't know the precise details, and my memory is not great, but from what I remember I read before, Plot should use either the same or a very similar algorithm, with a threshold angle of 5 degrees. It will refine the sampling grid if the angle between tho consecutive line segments exceeds 5 degrees. (The code is mine, I didn't take it from Plot) – Szabolcs May 24 '12 at 9:17
• @Szabolcs and celtschk: the old package GraphicsSpline  featured a set of subroutines that were essentially explicit reimplementations of the algorithm used within Plot[]/ParametricPlot[]. You might wish to take a look at them. – J. M. will be back soon May 24 '12 at 10:33

If you're willing to sacrifice automaticity on MaxRecursions, you could do this

SetAttributes[celtschkPlot, HoldAll];
celtschkPlot[fun_, {v_, r1__}, mr_: 6, op : OptionsPattern[]] :=
Module[{i = 0, xant},
Monitor[
Plot[fun, {v, r1},
MaxRecursion -> mr,
EvaluationMonitor :> (If[v < xant, ++i]; xant = v), op],
ProgressIndicator[i, {0, 2^mr}]]]


So, try

celtschkPlot[Pause[0.001]; Sin[2 Pi t], {t, 0, 10}]


and play with the functions. The last argument specifies the max recursion with defaults to a hard 6

celtschkPlot[Pause[0.001]; Sin[2 Pi t], {t, 0, 10}, 6]


This would be an upper bound. You could get the happy surprise that the plot finishes early

• As an alternative you could use EvaluationMonitor :> (If[v<ant, i++]; xant = v). – Heike May 24 '12 at 10:01
• @Heike, thank god I have an alternative. My code is disgusting – Rojo May 24 '12 at 10:04
• @Heike, there we go, thanks – Rojo May 24 '12 at 10:14
• I wanted to give a counterexample or the computation steps growing exponentially, but it turned out that even in my example they do exactly that ... ListPlot[Reverse@ Table[Part[ Reap@Plot[1/(1 + Exp[-10 x]), {x, -3, 3}, Mesh -> All, EvaluationMonitor :> Sow[x], MaxRecursion -> k], 2, 1], {k, 0, 3}], PlotRange -> All] – Szabolcs May 24 '12 at 10:19
• @Szabolcs, in any case, if it works for most cases, even when you don't know in which, it's probably good enough to be useful as an "estimate" I think – Rojo May 24 '12 at 10:24