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.

So for example I have this code:

points = {}; k = 0;
Dynamic@k
Dynamic@Graphics[Point@points]

x = .1; y = .3; K = .9;
While[True,
  k++;
  {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.

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

1 Answer 1

up vote 9 down vote accepted

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;
Do[
 {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;
Do[
 {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

share|improve this answer
    
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. –  swish Oct 1 '12 at 10:14
    
@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. –  István Zachar Oct 1 '12 at 10:32
    
How about keeping a rasterized pre-image, and adding a point at a time. It's slow, but O(1) –  belisarius Oct 1 '12 at 12:33
    
Thanks for the tip @belisarius. See edit. –  István Zachar Oct 1 '12 at 13:39
    
Thank you all, it is really fast now. I was playing with ArrayPlot too. –  swish Oct 1 '12 at 14:25
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.