dynamic plots

imaginee1> Hi, we are trying to change from scipy.xplt to
    imaginee1> matplotlib and need advice on dynamic plots. With the
    imaginee1> examples at the end of this e-mail we get the following
    imaginee1> frame rates (PIV, 2.8 GHz, debian sarge, python 2.3,
    imaginee1> matplotlib 0.64)

    imaginee1> FPS xplt 1000 (mov_sin_xplt.py) TkAgg 20
    imaginee1> (mov_sin_mpl_tkagg.py) TkAgg2 5 (mov_sin_mpl_tkagg2.py)
    imaginee1> gtk 60 (mov_sin_mpl_gtk.py) gtkAgg 37
    imaginee1> (mov_sin_mpl_gtk.py)

1000 frames per second?? A typical top of the line monitor refreshes
at 75-100 FPS. How can you get 1000 frames per second? I'll humbly
suggest that you're not accurately measuring the true refresh rate of
xplt, while graciously acknowledging that xplt is much faster than
matplotlib.

Also, what refresh rate do you really need? DVD refreshes at 30FPS
and monitors typically around 75FPS. I suspect Andrew can tell us the
limits of the human visual system in terms of the maximal refresh rate
that is perceptible. I'm assuming you want to display these
animations to humans and not flies, which of course would be a
different story :slight_smile:

I certainly agree that there are things matplotlib can, should and
will do to make this process faster. The first problem is that the
entire figure is updated with every frame. It would be much more
efficient in animated mode to designate certain elements only for
update. These elements could store the background image of their
bounding box, and on each update erase themselves (restore the
background) and redraw themselves with the new data. By limiting
redraws to only sections of the canvas, and only certain plot
elements, we should be able to get at least a 2x speedup, I'm
guessing.

    imaginee1> More generally, our impression is that with matplotlib
    imaginee1> the code tends to be more complicated (timers, classes
    imaginee1> etc.) than the scipy.xplt version. Maybe there are
    imaginee1> better ways to achieve what we want (but we haven't
    imaginee1> found them yet ;-).

All this complication arises in attempting to deal with the mainloop.
You should be able to skip all this cruft, as you did for your tkagg
example, by running in interactive mode

    import matplotlib
    matplotlib.use('GTKAgg')
    matplotlib.interactive(True)
    from matplotlib.matlab import *
    import time

    x = arange(0,2*pi,0.01) # x-array
    axis([0.0,2*pi,-1.0,1.0]) # setup axis
    tstart = time.time()

    line, = plot(x,sin(x))
    for i in arange(1,200):
        line.set_ydata(sin(x+i/10.0))
        draw()

    print 'FPS:' , 200/(time.time()-tstart)

Basically what matplotlib needs is a method like

    for i in arange(1,200):
        line.set_ydata(sin(x+i/10.0))
        fig.update(line)

in place of the call to draw which redraws the entire figure.

    imaginee1> We also have a wx version, but the code is really
    imaginee1> complicated (any pointers on how to code our example
    imaginee1> most simply with the wx backend
    imaginee1> would be also very much appreciated).

Well, you'd have to post your code, but the interactive trick above
works for WX and WXAgg as well. But I doubt you'll beat GTK/GTKAgg
performance wise with WX*. With the example above, I get

  TkAgg 20 FPS
  GTK 50 FPS
  GTKAgg 36 FPS
  GTKCairo 15 FPS
  WX 11 FPS
  WXAgg 27 FPS

The performance problem with Tk animation is well known and w/o
resorting to platform dependent extension code, we don't have a good
way to solve it.

Note in matplotlib's defense, the fact that I can run the same
animated code across platforms and 4 GUIs (FLTK not profiled here) w/o
changing a single line of code says something about why it's slower
that xplt, which targets a single windowing system and thus can make
low level calls.

JDH

Hello!

Why is GTKAgg is slower than GTK, but WXAgg is faster than WX?

Alexey

···

On Thu, 16 Dec 2004 10:23:26 -0600, John Hunter <jdhunter@...4...> wrote:

    import matplotlib
    matplotlib.use('GTKAgg')
    matplotlib.interactive(True)
    from matplotlib.matlab import *
    import time

    x = arange(0,2*pi,0.01) # x-array
    axis([0.0,2*pi,-1.0,1.0]) # setup axis
    tstart = time.time()

    line, = plot(x,sin(x))
    for i in arange(1,200):
        line.set_ydata(sin(x+i/10.0))
        draw()

    print 'FPS:' , 200/(time.time()-tstart)

  TkAgg 20 FPS
  GTK 50 FPS
  GTKAgg 36 FPS
  GTKCairo 15 FPS
  WX 11 FPS
  WXAgg 27 FPS

Alexey Shamrin wrote:

Why is GTKAgg is slower than GTK, but WXAgg is faster than WX?

My question exactly. It's unlikely that that Wx has to be slower than WxAgg. In theory, at least, wx can take advantage of hardware accelerated drawing. On the other hand, wx does not know about NumPy arrays of either flavor, so if the Agg wrappers do, they could have an advantage there. Also, wx is known to be much slower with numarray arrays than Numeric arrays. I'd would certainly recommend that wx users stick with Numeric if they don't have a compelling reason to use numarray.

Another issue is font caching. Is the wx back-end doing font caching? this made a huge difference in the wxPyPlot code.

By the way, timing drawing on X is difficult, because the drawing calls return after the app has told X what to draw, not when it has been drawn. I suspect this might have something to do with the 1000 fps that was measured.

I hope I'll get a chance to do some work on the wx backend someday....

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@...259...

Were you thinking that GTKAgg should be as fast or faster than GTK?

In the past I think GTKAgg and GTK would do dynamic plots at about the
same speed. GTK used to allocate a new gtk.gdk.Pixmap and a new
RendererGTK for every figure draw operation, which was inefficient. I
updated the code so GTK now creates just one RendererGTK and just one
Pixmap (as long as its size does not increase). This should have made
GTK dynamic plotting faster (I didn't benchmark the changes so I don't
know for sure).

Its possible that similar changes for GTKAgg (or TkAgg or WX) would
speed up their dynamic plotting.

Steve

···

On Thu, 2004-12-16 at 20:21 +0300, Alexey Shamrin wrote:

Why is GTKAgg is slower than GTK, but WXAgg is faster than WX?

Dear John,

thank you very much for your helpful answer!

[... snip frame rates ...]

1000 frames per second?? A typical top of the line monitor refreshes
at 75-100 FPS. How can you get 1000 frames per second? I'll humbly
suggest that you're not accurately measuring the true refresh rate of
xplt, while graciously acknowledging that xplt is much faster than
matplotlib.

Also, what refresh rate do you really need? DVD refreshes at 30FPS
and monitors typically around 75FPS. I suspect Andrew can tell us the
limits of the human visual system in terms of the maximal refresh rate
that is perceptible. I'm assuming you want to display these
animations to humans and not flies, which of course would be a
different story :slight_smile:

That would be an interesting research project, but
makes grant applications more complicated due to animal experiments ;-).

The FPS numbers give us an estimate on the speed of
the drawing process (see also below).

I certainly agree that there are things matplotlib can, should and
will do to make this process faster. The first problem is that the
entire figure is updated with every frame. It would be much more
efficient in animated mode to designate certain elements only for
update. These elements could store the background image of their
bounding box, and on each update erase themselves (restore the
background) and redraw themselves with the new data. By limiting
redraws to only sections of the canvas, and only certain plot
elements, we should be able to get at least a 2x speedup, I'm
guessing.

We have a question here concerning the example you gave: is
the whole screen updated with every `draw()`,
including the axes and labels?
If so there might be another (simpler) possibility
by just updating the white plot-area.
A problem might be the inward pointing tics.
((For the PlottingCanvas we solved this by having
ticks pointing outward and using a separate frame
for the inside of the plot)).

    imaginee1> More generally, our impression is that with matplotlib
    imaginee1> the code tends to be more complicated (timers, classes
    imaginee1> etc.) than the scipy.xplt version. Maybe there are
    imaginee1> better ways to achieve what we want (but we haven't
    imaginee1> found them yet ;-).

All this complication arises in attempting to deal with the mainloop.
You should be able to skip all this cruft, as you did for your tkagg
example, by running in interactive mode

    import matplotlib
    matplotlib.use('GTKAgg')
    matplotlib.interactive(True)
    from matplotlib.matlab import *
    import time

    x = arange(0,2*pi,0.01) # x-array
    axis([0.0,2*pi,-1.0,1.0]) # setup axis
    tstart = time.time()

    line, = plot(x,sin(x))
    for i in arange(1,200):
        line.set_ydata(sin(x+i/10.0))
        draw()

    print 'FPS:' , 200/(time.time()-tstart)

This is indeed very nice and works (basically) the same for all backends.
For this particular example we get:

          Double buffered Resizable
xplt no no
tkagg yes yes
gtk yes (but: frameshift) no
gtkagg no no
wx no no
wxagg no no

Interestingly, in this dynamics example
tkagg and gtk seem to have double buffering,
i.e. at the end of the dynamics a damaged area gets repainted.
With tkagg one can even resize the window at the end of the
dynamics.
(Actually, in the examples we posted double-buffering and resizing
worked).

Just a remark: For the gtk backend the double-buffer for
the repaint is one frame behind.

Basically what matplotlib needs is a method like

    for i in arange(1,200):
        line.set_ydata(sin(x+i/10.0))
        fig.update(line)

in place of the call to draw which redraws the entire figure.

That could indeed give an substantial speed-up.

    imaginee1> We also have a wx version, but the code is really
    imaginee1> complicated (any pointers on how to code our example
    imaginee1> most simply with the wx backend
    imaginee1> would be also very much appreciated).

Well, you'd have to post your code, but the interactive trick above
works for WX and WXAgg as well. But I doubt you'll beat GTK/GTKAgg
performance wise with WX*.

We will either need Tk or WX for our Windows using students.
For Linux GTKAgg should do the job.

With the example above, I get

  TkAgg 20 FPS
  GTK 50 FPS
  GTKAgg 36 FPS
  GTKCairo 15 FPS
  WX 11 FPS
  WXAgg 27 FPS

The performance problem with Tk animation is well known and w/o
resorting to platform dependent extension code, we don't have a good
way to solve it.

I re-ran the tests on my laptop (PIII, 1.2 GHz)

            John laptop
  xplt 196
  TkAgg 20 FPS 9
  GTK 50 FPS 25
  GTKAgg 36 FPS 18
  WX 11 FPS 8
  WXAgg 27 FPS 11

(Unfortunately, some of the students have even slower machines ;-(.

To provide even more data (now a PIV, 2.8 GHz, debian sarge,
but a different X driver, factor 3 slower for xplt!)

            1000 pts 10000 pts 100000 pts
xplt 330 FPS 159 FPS 43 FPS
tkagg 23 FPS 16 FPS 4 FPS
gtk 40 FPS 19 FPS 5 FPS
gtkagg 31 FPS 24 FPS 4 FPS
wx 12 FPS 3 FPS 0 FPS
wxagg 24 FPS 16 FPS 4 FPS

This shows the FPS when the number of points being plotted
is increased.
To answer your question from above:
Something like 40 FPS for plotting 10000 points
would be optimal. On slower machines (like
my laptop) this might not be realizable.

Note in matplotlib's defense, the fact that I can run the same
animated code across platforms and 4 GUIs (FLTK not profiled here) w/o
changing a single line of code says something about why it's slower
that xplt, which targets a single windowing system and thus can make
low level calls.

There is really no need to defend matplotlib
(and we better don't post matplotlib's feature list here
to emphasize the points we like!).

Best,

Nikolai and Arnd

···

On Thu, 16 Dec 2004, John Hunter wrote: