plotting directly using the renderer

Hello everyone,

I have a question concerning a common task, to dynamically plot the results
of some (usually pretty fast) computation.

Approach 1: (Routine `do_it_point_by_point` below)
            just call `plot` successively.

            Here the update frequency gets slower and
            slower the more points are added.

Approach 2: (Routine `do_it_point_by_point`)

            Here one obtains a speed improvement, however the code is
            more complicated (in particular for beginners!).

To get some speed improvements I figured out that it is better to open just
one plot and then append new data to this one. For large numbers of points
to draw this makes the plot faster.

Then I wondered 'Why is this so?' and figured out that the plot()-command
(in interactive mode) plots the previous points all over again with each new
point.
Therefore using setp(line, data=('old data + new point')) made everything
faster because now was only one object to handle (which of course is getting
complexer and complexer). Up to this point it is exactly the same as
described in 'anim.py'.

My question is now: Is there a way just to add points to a plot? Because
even in the append-method MPL draws everything again with each draw(). Only
this time MPL has to plot one thing - a circular arc instead of many many
points and is therefore faster.
Remarks:
- Of course this is only reasonable if autoscale_on=False.
- in this situation the z-ordering could not be obeyed
   (which would be perfectly ok for this particular usage)
- No previous points have to be replotted (this is what I would want)

To play around with this idea I tried to use a modified plot routine,
which should just plot the newly added points/lines/...:

···

#------------------------------------------------------------------
def fastplot(*args, **kwargs):
    b = ishold()
    h = popd(kwargs, 'hold', None)
    if h is not None:
        hold(h)
    try:
        ret = gca().plot(*args, **kwargs)
        renderer = gca().get_renderer_cache()
        gc = renderer.new_gc() # new graphics context
        for line in ret:
            renderer.draw_line(gc, args[0][1],
                               args[0][1],args[1][0], args[1][1])
    except:
        hold(b)
        raise

    hold(b)
    return ret

#------------------------------------------------------------------

However, this (mainly a copy of plot()) does not work (nothing appears on
the screen).

So what do you think:
Is there any possibilty to turn the 'draw everything again
with each plot()-command' off?

My suggestion is that propably the usage of the Renderer (like above)
directly (as described in user's manual) could help. But I'm not really able
to understand what MPL is doing there.
Is it possible to use the commands described there with existing axis to get
output on the screen? I.e. using something like
  ax = gca()
  renderer = ax.get_renderer_cache()
if some other thing has already been plotted? I tried to go on with the code
from
the user's manual:
  gc = o.new_gc()
  rec = o.draw_rectangle(gc,face,100,100,200,200)
You can see the rectangle, if interactive-mode is off. This is a drawback
because the issue mentioned at the beginning needs ion().

If something like this would be possible it would make things to new
students learning python and mpl much easier.

Thanks for your
help,

Martin

#---------------------------------------------------------------------------------
from pylab import *
import time # for profiling

def do_it_point_by_point(x1,y1):
    print " plot every point seperately ..."
    n = len(x1)
    axis([-1,1,-1,1])
    axis('scaled')
    for i in xrange(n): # plot all data step by step
        plot( [x1[i] ],[y1[i] ],'bo')

def do_it_by_append(x1,y1):
    print " append data to existing plot ..."
    n = len(x1)
    points = plot(x1[0]*ones(2),y1[0]*ones(2),'ro')# draw the first point
    axis([-1,1,-1,1])
    axis('scaled')
    if n>1:
        x_help = list()
        x_help.append(x1[0])
        y_help = list()
        y_help.append(y1[0])
        for i in xrange(1,n-1):
            x_help.append(x1[i])
            y_help.append(y1[i]) # append the rest and ...
            setp(points,data=(array(x_help),array(y_help))) # update data

n=80 # setting n=300 makes the
phi=2.0*pi*arange(n)/n # difference quite
obvious
x=cos(phi)
y=sin(phi)

ion()
print ""

figure(1)
subplot(111, autoscale_on=False)
tstart = time.time()
do_it_point_by_point(x,y)
tend = time.time()
t_old = tend - tstart
close(1)

figure(1)
tstart = time.time()
do_it_by_append(x,y)
tend = time.time()
t_new = tend - tstart
close(1)
ioff()

print ""
print " It took %6.2f s the point-by-point way,"%(t_old)
print " %6.2f s the append way."%(t_new)

--
5 GB Mailbox, 50 FreeSMS http://www.gmx.net/de/go/promail
+++ GMX - die erste Adresse f�r Mail, Message, More +++