3
$\begingroup$

Suppose I have a time-consuming function fun[x]. I would like to see the plot between, say {x, 0, 1}. I would like to watch each individual points being plotted as the recursion goes on.

I will use a sin function with a pause to emulate a slow function. In reality, suppose we are plotting a function which is very cost-expensive, thus we want to minimize the total points where the function is evaluated on.

Dynamic2DPlot[fun_, recursion_] := 
  Block[{},
    plt = {};
    list = {{}};
    Do[
      list = Flatten[{Append[#, 0] & /@ list, Append[#, 1] & /@ list}, 1], 
      {recursion}];
    samples = FromDigits[{#, 0}, 2] & /@ list;
    For[j = 1, j <= Length[samples], j++,
      coord = samples[[j]];
      z = fun[coord];
      Pause[0.1];
      plt = Append[plt, {coord, z}];];]

samples is just a list of coordinates in the executing order.

{0, 1/2, 1/4, 3/4, 1/8, 5/8, 3/8, 7/8, 1/16, 9/16, 5/16, 13/16, 3/16, 11/16, 7/16, 15/16, ...}

Now this works perfectly, as plt is a global variable

Dynamic[ListLinePlot[SortBy[plt, First], Mesh -> All, PlotRange -> {0, 1}]]
Dynamic2DPlot[Sin[4*#] &, 4]

However, putting these two lines in Block or Module will not work, as the Dynamic part ceases to show up. Ideally I'm looking for a way to create a package, where I can call in another notebook like this:

Dynamic2DPlot[fun[x], {x,0,1}, recursion->5]

And it will behave just like a normal ListLinePlot but will update the graph once a new datapoint is calculated.

$\endgroup$
6
$\begingroup$

This might not be an answer because I'm not sure what you're after exactly. It might be CellPrint and CellExpression as shown in the proof-of-concept example below.

slow[x_] := (Pause[0.1]; x (1 - x));
Module[{pts = {}, y, f},
 f[x_?NumericQ] := y = slow[x];
 CellPrint@ExpressionCell[
   Dynamic@ListLinePlot[pts, PlotRange -> {{0, 1}, {0, 1/4}}],
   "Output"];
 Plot[f[x], {x, 0, 1}, PlotPoints -> 5, 
  EvaluationMonitor :> (pts = Sort@Append[pts, {x, y}])];
 ]

enter image description here

In this case the plotting is driven by Plot, which has automatic recursive subdivision.

$\endgroup$
  • $\begingroup$ Thanks a lot! This is very helpful. $\endgroup$ – Peter Zhang Nov 21 '16 at 19:25
2
$\begingroup$

I admit I am not sure about what you trying to do, but the following much simpler code does the same thing as your code does only in a more robust way.

Dynamic2DPlot[fun_, steps_] :=
  Do[
    plot =
      ListLinePlot[{#, fun[#]} & /@ Range[0, 1, 1/2^j],
        Mesh -> All, PlotRange -> {-1, 1}];
    Pause[.5],
    {j, steps}]

plot = Null; Dynamic[plot]
Dynamic2DPlot[Sin[4 #] &, 4];

plot

Whether or not this can serve as the basis of something you can make into a package would more information on how you plan to use the package to decide. However, I believe this to be a far better basis for further exploration of the problem than the code you have posted.

$\endgroup$
  • $\begingroup$ Thank you, Goldberg. I'm sorry that I didn't make it clear. My goal was to visualize the subdivision as the plot is going on. The pause function is just to emulate a slow function, not just for an animation purpose. So it would be better to reuse the value of a calculated point. Thank you for your help anyway! $\endgroup$ – Peter Zhang Nov 21 '16 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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