|
From: Arnd B. <arn...@we...> - 2004-12-17 18:37:20
|
Dear John,
thank you very much for your helpful answer!
On Thu, 16 Dec 2004, John Hunter wrote:
> >>>>> "imaginee1" == imaginee1 <ima...@gm...> writes:
[... 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 :-)
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
|