[matplotlib-devel] margins, locator_params, formatter offset

2010-04-20 Thread Eric Firing
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

2010-04-20 Thread Ryan May
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

2010-04-20 Thread Ryan May
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

2010-04-20 Thread John Hunter
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

2010-04-20 Thread Ryan May
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