I need to trigger some data processing* after the user changes the limits of a plot (e.g., via pan, zoom or the 'home' button). The code below is my proof-of-concept solution to this problem, which I offer for discussion and reference. It was a good practice in learning the events system. I would not be sad if someone were to inform me of more elegant solution.
Thanks, Eric *I'm plotting data points in three separate panels (x-y, x-z, and z-y) with shared axes. The data processing replots x-z and z-y to match the data in the x-y view. class accumulator(object): """ Provides for event callbacks for matplotlib drag/release events and axis limit changes by accumulating a series of event occurrences. Produces a single call to func after a user interacts with the plot. Sample usage: from pylab import figure, show def simple(count): print "update ", count a = accumulator(simple) f=figure() ax=f.add_subplot(111) plt=ax.plot(range(10)) f.canvas.mpl_connect('draw_event', a.draw_event) f.canvas.mpl_connect('button_release_event', a.mouse_up_event) f.canvas.mpl_connect('button_press_event', a.mouse_down_event) ax.callbacks.connect('xlim_changed', a.axis_limit_changed) ax.callbacks.connect('ylim_changed', a.axis_limit_changed) show() """ def __init__(self, func): self.func=func self.reset() self.counter = 0 self.mouse_up = False def reset(self): """ Reset flags after the update function is called. Mouse is tracked separately. """ self.limits_changed = 0 self.got_draw = False def axis_limit_changed(self, ax): self.limits_changed += 1 self.check_status() def draw_event(self, event): self.got_draw=True self.check_status() def mouse_up_event(self, event): self.mouse_up = True self.check_status() def mouse_down_event(self, event): self.mouse_up = False def both_limits_changed(self): """ Both x and y limits changed and the mouse is up (not dragging) This condition takes care of the limits being reset outside of a dragging context, such as the view-reset (home) button on the Matplotlib standard toolbar. """ return (self.limits_changed >= 2) & self.mouse_up def interaction_complete(self): """ x, y, or both limits changed, and the mouse is up (not dragging). Also checks if matplotlib has done its final redraw of the screen, which comes after the call to *both* set_xlim and set_ylim have been triggered. The check for the draw event is the crucial step in not producing two calls to self.func. """ return (self.limits_changed>0) & self.got_draw & self.mouse_up def check_status(self): if self.both_limits_changed() | self.interaction_complete(): self.func(self.counter) self.reset() self.counter += 1 ------------------------------------------------------------------------- Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08 _______________________________________________ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users