[matplotlib-devel] margins, locator_params, formatter offset
During the last few days I have added some convenience methods and pyplot functions. Please review them to see whether names, APIs, or functionality should be changed. The general motivation is that formatters and locators are a bit obscure and hidden in the object hierarchy, so I wanted to make it easier for people to make simple changes. In addition, in autoscaling, one might want an option that is almost "tight" but leaves a little margin, so symbols at the edge don't get sliced off, for example. At the Axes and pyplot levels, the changes made so far include expanding ticklabel_format() and adding two new methods/functions, locator_params() and margins(). The change to ticklabel_format is the addition of a new kwarg: *useOffset*[True | False | offset]; if True, the offset will be calculated as needed; if False, no offset will be used; if a numeric offset is specified, it will be used. This involved changing the underlying ScalarFormatter to accept a numeric offset as an alternative to calculating it automatically. The docstrings for the new methods are: def locator_params(self, axis='both', tight=False, **kwargs): """ Convenience method for controlling tick locators. Keyword arguments: *axis* ['x' | 'y' | 'both'] Axis on which to operate; default is 'both'. *tight* [True | False] Parameter passed to :meth:`autoscale_view`. Remaining keyword arguments are passed to directly to the :meth:`~matplotlib.ticker.MaxNLocator.set_params` method. Typically one might want to reduce the maximum number of ticks and use tight bounds when plotting small subplots, for example:: ax.locator_params(tight=True, nbins=4) Because the locator is involved in autoscaling, :meth:`autoscale_view` is called automatically after the parameters are changed. This presently works only for the :class:`~matplotlib.ticker.MaxNLocator` used by default on linear axes, but it may be generalized. """ and def margins(self, *args, **kw): """ Convenience method to set or retrieve autoscaling margins. signatures:: margins() returns xmargin, ymargin :: margins(margin, tight=True) margins(xmargin, ymargin, tight=True) margins(x=xmargin, y=ymargin, tight=True) All three forms above set the xmargin and ymargin parameters. All keyword parameters are optional. A single argument specifies both xmargin and ymargin. The *tight* parameter is passed to :meth:`autoscale_view`, which is executed after a margin is changed. Specifying any margin changes only the autoscaling; for example, if *xmargin* is not zero, then *xmargin* times the X data interval will be added to each end of that interval before it is used in autoscaling. """ Eric -- ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] margins, locator_params, formatter offset
On Tue, Apr 20, 2010 at 2:46 PM, Eric Firing wrote: > During the last few days I have added some convenience methods and > pyplot functions. Please review them to see whether names, APIs, or > functionality should be changed. The general motivation is that > formatters and locators are a bit obscure and hidden in the object > hierarchy, so I wanted to make it easier for people to make simple > changes. In addition, in autoscaling, one might want an option that is > almost "tight" but leaves a little margin, so symbols at the edge don't > get sliced off, for example. No comments other than these seem like really good changes to reduce the barrier for the users. Nice work! Ryan -- Ryan May Graduate Research Assistant School of Meteorology University of Oklahoma -- ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
[matplotlib-devel] 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 -- ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] New generic timers
On Tue, Apr 20, 2010 at 3:26 PM, Ryan May 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. 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 -- ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] New generic timers
On Tue, Apr 20, 2010 at 4:02 PM, John Hunter wrote: > On Tue, Apr 20, 2010 at 3:26 PM, Ryan May 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. :) Ryan -- Ryan May Graduate Research Assistant School of Meteorology University of Oklahoma -- ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel