New generic timers

Hi,

Continuing the spurt of (independent) development that's been going on
lately, I committed support for generic timers. There's a base class
TimerBase that provides the basic API for a timer (start, stop,
controlling the interval, adding callbacks, etc.), and each GUI
backend subclasses this to wrap around their toolkit's native timer
classes. I added a method to each backend's canvas object to
facilitate creating a backend-specific timer without having to know
what backend was running. So far, I'm quite happy with how it turned
out, but I'm curious to hear feedback. Specifically:

1) Anything missing in the basic TimerBase API?

2) Is adding new_timer() the canvas a good way to go? I needed a way
to get to backend-specific classes without actually knowing what
backend I'm running (and without calling _pylab_helpers or
pyplot.get_backend()). Figure.canvas seemed to be just about the only
way to go about this. It also makes some sense, because in the case
of Wx and Tk, an actual widget is required to hook up the timer.

I've added an example in:
examples/event_handling/timers.py

This just makes a plot with a title that is continually (100 ms)
updating with the current time including milliseconds. It does a good
job of showing the ease with which such interactive updates can be
done now. In fact, this could probably be used to update and simplify
the existing animation demos. However, I'm already finishing up a more
complete animation framework based on this, which should simplify some
of those even further. At that point, I'll probably update the
examples.

I still need to add some documentation to the event handling section
of the User's Guide, though this might better belong with a section on
animation's that I promise to write once the new framework is checked
in.

Also, I didn't add a TimerBase implementation for the CocoaAgg
backend. I have no idea about that toolkit, so I'd appreciate some
help there so we can have an implementation for all of the active GUI
toolkits.

Any feedback is appreciated.

Ryan

···

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Hi,

Continuing the spurt of (independent) development that's been going on
lately, I committed support for generic timers. There's a base class
TimerBase that provides the basic API for a timer (start, stop,
controlling the interval, adding callbacks, etc.), and each GUI
backend subclasses this to wrap around their toolkit's native timer
classes. I added a method to each backend's canvas object to
facilitate creating a backend-specific timer without having to know
what backend was running. So far, I'm quite happy with how it turned
out, but I'm curious to hear feedback. Specifically:

1) Anything missing in the basic TimerBase API?

You might want to pass the argument as keywords on from the
add_timerr, so you can do

  timer = fig.canvas.new_timer(interval=100, callbacks=[(update_title, ax)])

or something like that... Or support a single callback object.

Speaking of callbacks, do you know about cbook.CallbackRegistry? It
would be nice to standardize on a single interface for handling
callbacks so users and developers can manipulate it directly. We use
this elsewhere in support of mpl event handling and the toolbar so it
is fairly robust.

2) Is adding new_timer() the canvas a good way to go? I needed a way
to get to backend-specific classes without actually knowing what
backend I'm running (and without calling _pylab_helpers or
pyplot.get_backend()). Figure.canvas seemed to be just about the only
way to go about this. It also makes some sense, because in the case
of Wx and Tk, an actual widget is required to hook up the timer.

I've added an example in:
examples/event_handling/timers.py

This just makes a plot with a title that is continually (100 ms)
updating with the current time including milliseconds. It does a good
job of showing the ease with which such interactive updates can be
done now. In fact, this could probably be used to update and simplify
the existing animation demos. However, I'm already finishing up a more
complete animation framework based on this, which should simplify some
of those even further. At that point, I'll probably update the
examples.

Looking forward to seeing it -- thanks!

JDH

···

On Tue, Apr 20, 2010 at 3:26 PM, Ryan May <rmay31@...149...> wrote:

Hi,

Continuing the spurt of (independent) development that's been going on
lately, I committed support for generic timers. There's a base class
TimerBase that provides the basic API for a timer (start, stop,
controlling the interval, adding callbacks, etc.), and each GUI
backend subclasses this to wrap around their toolkit's native timer
classes. I added a method to each backend's canvas object to
facilitate creating a backend-specific timer without having to know
what backend was running. So far, I'm quite happy with how it turned
out, but I'm curious to hear feedback. Specifically:

1) Anything missing in the basic TimerBase API?

You might want to pass the argument as keywords on from the
add_timerr, so you can do

timer = fig.canvas.new_timer(interval=100, callbacks=[(update_title, ax)])

or something like that... Or support a single callback object.

I'll look at that. I had been trying to keep the constructor simple,
but those extra calls to get it fully initialized aren't in line with
the rest of the matplotlib API (been doing too much Qt!). I'll
probably make it callbacks=[(func, args, kwargs)], as I think I'm
going to go back and add **kwargs anyways.

Speaking of callbacks, do you know about cbook.CallbackRegistry? It
would be nice to standardize on a single interface for handling
callbacks so users and developers can manipulate it directly. We use
this elsewhere in support of mpl event handling and the toolbar so it
is fairly robust.

Can you further describe what you see here? I looked at this before,
and it seems more valuable if you have a variety of signals. I would
have 1. I *could* add a time_event to the list of events in the
canvas and use the canvas-level callback registry, but that would
actually seem to undo the encapsulation of the timer object. Plus
that would only allow one timer attached to a canvas. More
importantly, the CallbackRegistry, when processing signals, calls each
callback with the same arguments, so there's no way to specify per
callback information. Maybe I'm just being dense, so please correct
me if I'm missing your vision here. I'd always love to reuse existing
code and reduce my "opportunity" to contribute bugs to matplotlib. :slight_smile:

Ryan

···

On Tue, Apr 20, 2010 at 4:02 PM, John Hunter <jdh2358@...149...> wrote:

On Tue, Apr 20, 2010 at 3:26 PM, Ryan May <rmay31@...149...> wrote:

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma