So for example I have this code:

points = {}; k = 0;

x = .1; y = .3; K = .9;
  {x, y} = {FractionalPart[x + K y], FractionalPart[x]};
  AppendTo[points, {x, y}];

The problem is that the list of points is growing and it slows down with time. What I want is to be able to add a point (or another primitive) directly on the dynamic graph without storing unnecessary chunks of data.

  • $\begingroup$ AppendTo[] is notoriously slow... $\endgroup$ Oct 1 '12 at 9:08
  • 1
    $\begingroup$ @J.M. And increasing the number of points to plot ad infinitum doesn't help $\endgroup$ Oct 1 '12 at 9:18
  • $\begingroup$ For systems like Matlab this works because it uses a more PostScript-like approach to rendering (just adding on top)... $\endgroup$
    – Yves Klett
    Oct 1 '12 at 12:55

As it was mentioned in the comments: your loop is infinite, which eventually will cause the slowdown of any computation that accumulates data in the memory. The important rule of thumb for Dynamic updating is: only update when necessary and only update what is necessary. Accordingly, you can speed up the performance of the dynamic drawing by wrapping only points and k in Dynamic. By this way, only the list of points is updated (and the label) and Mathematica does not have to redraw the whole Graphics object again and again (which involves a lot of extra computation).

points = {};
Graphics[Point@Dynamic@points, PlotLabel -> Dynamic@k]

x = .1; y = .3; K = .9;
 {x, y} = {FractionalPart[x + K y], FractionalPart[x]};
 points = Append[points, {x, y}];
 , {k, 20000}]

Starting from @belisarius' comment, I came up with a more economic version (time scales linearly with k). If one does not have to keep all the points we can apply a reasonable resolution to bin the ranges and saving new datapoints in a matrix, overwriting previous data.

resolution = 256;  (* divide the (0,1) range into 256 bins *)
array = Array[0 &, {resolution, resolution}];

Dynamic@ArrayPlot[array, PlotLabel -> Dynamic@k]

x = .1; y = .3; K = .9;
 {x, y} = {FractionalPart[x + K y], FractionalPart[x]};
 array = ReplacePart[array, (Min[#, resolution] & /@ (Round[{x, y}*resolution] + 1)) -> 1],
 {k, 1000000}]

enter image description here

  • $\begingroup$ Yes it's much faster but execution still slows down with time. The goal is to get rid off list and just add primitives directly to the existing graph. $\endgroup$
    – swish
    Oct 1 '12 at 10:14
  • $\begingroup$ @swish: I think that in any case a list must be maintained to store points if you want to build up your graphics by successively introducing points. $\endgroup$ Oct 1 '12 at 10:32
  • $\begingroup$ How about keeping a rasterized pre-image, and adding a point at a time. It's slow, but O(1) $\endgroup$ Oct 1 '12 at 12:33
  • $\begingroup$ Thanks for the tip @belisarius. See edit. $\endgroup$ Oct 1 '12 at 13:39
  • $\begingroup$ Thank you all, it is really fast now. I was playing with ArrayPlot too. $\endgroup$
    – swish
    Oct 1 '12 at 14:25

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.