From: John H. <jdh...@ac...> - 2004-07-15 14:15:45
|
>>>>> "MWallis" == MWallis <mw...@sw...> writes: MWallis> This has been my first time using matplotlib and it has MWallis> not been entirely successful . I was asked to develop a MWallis> GUI using Python and omniORB to connect as a client to a MWallis> server and request a data stream which they wanted me to MWallis> display. There is a considerable amount of data that is MWallis> generated and I am not sure that Python was going to be MWallis> able to handle it. I developed the app in Python and was MWallis> able to connect to the server using omniORB and register MWallis> a callback and receive the data. This worked fine. I MWallis> then created the GUI using matplotlib and pygtk. The MWallis> display included 2 spectrograms a pan display and 2 bar MWallis> charts. After data of the appropriate type was received MWallis> they wanted the displays to be updated dynamically. I MWallis> used threading but it still seemed that after awhile the MWallis> GUI would lock up. Are there any examples available that MWallis> embed multiple dynamically updated figures using gtk? I'm MWallis> afraid that if I can't get this fixed they will write MWallis> python and matplotlib off and refuse to use it again. Hi Melissa, I have little experience with threads and try to avoid using them directly - I'll leave that to the pros. I suggest another approach - a useful pygtk trick is to use the idle manager to avoid calls when gtk is busy. In the script below, new axes images are created and drawn only when gtk is idle. It doesn't do you any good to force feed gtk data it can't handle, so only make calls through the idle handler. I simulate a data event generator that calls one of two image axes. On my system, I get about 10 frames per second with the script below using gtkagg (gtkagg will probably be a little faster than gtk, which uses string methods to render image data). As for your clients giving up on us, remind them that image handling in matplotlib has gotten an order of magnitude faster in the last 5 months and that further enhancements for dynamic updating are in the works. One important one will be the ability to render only selective parts of the canvas (eg, just redraw the axes image portion rather than the entire canvas). My guess is that this change alone would roughly double the performance of gtkagg for dynamic images. Other optimizations specifically for updating image data would provide further performance enhancements, since this is a simple agg->agg rendering buffer transfer. Also, although matplotlib-0.60.2 was just released, a bug that affects image data with data extent set (eg specgram data) was recently fixed in CVS. You may want to work with http://nitace.bsd.uchicago.edu:8080/files/share/matplotlib-0.60.3a.tar.gz. It's not a critical update as the bug is only exposed in the following combination: 1) image data with extent set, 2) image.origin = 'lower' and 3) you have changed the axes limits from their defaults. May seem arcane, but nonetheless, Andrew Straw managed to find it within about 6 minutes of my CVS checkin. Let me know if this helps, JDH #!/usr/bin/env python """ An animated image """ import sys, time, os, gc from matplotlib import rcParams from matplotlib.matlab import * import gtk # if hold is on the axes images will accumulate and your performance # will tank! rc('axes', hold=False) class HandleDraws: drawing_idle_id = 0 shape = 100,100 # image size cnt = 0 def __init__(self): self.fig = figure(1) self.a1 = subplot(211) self.a2 = subplot(212) def idle_update(self, *args): 'only call a draw if gtk is idle' if self.cnt==0: self.tstart = time.time() draw() self.drawing_idle_id = 0 self.cnt += 1 if self.cnt>=50: print 'FPS', self.cnt/(time.time() - self.tstart) sys.exit() return False def update1(self, data): if self.drawing_idle_id == 0: self.a1.imshow(data, interpolation='nearest') self.drawing_idle_id = gtk.idle_add(self.idle_update) else: print 'dropping frame for axes 1' def update2(self, data): if self.drawing_idle_id == 0: self.a2.imshow(data, interpolation='nearest') self.drawing_idle_id = gtk.idle_add(self.idle_update) else: print 'dropping frame for axes 2' handler = HandleDraws() def generate_events(*args): data = rand(100,100) # randomly pick which axes to update if rand()>0.5: handler.update1(data) else: handler.update2(data) return True cnt = 0 gtk.timeout_add(10, generate_events) show() |