On Wed, May 20, 2009 at 4:02 PM, Christopher Barker
<chris.bar...@noaa.gov> wrote:
> John Hunter wrote:
>> The use case (and we can debate whether this is worth the extra overhead)
>>
>>   ax.plot(inches)
>>   ax.set_xlim(cms)
>
> I'll put my two cents into that debate:
>
> My first thought is: wow! that is putting WAY too much into a plotting
> routine!
>
> My second thought is: on the other hand, that is very cool.
>
> If it's going to be done, I think it really shouldn't be too MPL
> specific -- it should be built on a good (and hopefully eventually
> widely used) unit-array system, perhaps like Darren Dale's Quantities
> package (there are quite a few other that should be looked at also).

This is not how it works -- we will not be assuming any units package.
 Rather, we  provide an interface where any units package can be used
with mpl.  The original use case is that the JPL has an internal units
package and they want to pass their objects directly to mpl -- they
get handed these objects by custom internal C++ libs with python
wrappers over which they have no control maintained by another group.
So they cannot modify that package.  What they can do is access the
matplotlib units registry and register an entry there that maps type
-> a converter class that exposes a certain interface we require.  The
converter class not only knows how to convert the units to floats, but
also how to set tick locators, formatters and labels.  When we get
passed in a type, eg a datetime, a Quantiles instance, or whatever, we
ask the registry if there is a converter, and if so act appropriately
(though not always, hence the current thread).

One nice thing about this is we were able to extend support to native
datetime objects (which we cannot modify obviously) to mpl, so this
facility works with both proper unit types as well as arbitrary types.
 This feature was not part of the original design spec, but fell
naturally out of it, which suggests to me that we are onto something.
 So Darren's or anyone else package can be made to work with mpl with
little work (the harder part is getting all of mpl to respect the unit
conversion interface everywhere, which is what we are discussing).  To
give you a better idea what this looks like, the *entire* support in
mpl for handling native datetime objects looks like this::

    class DateConverter(units.ConversionInterface):
        """The units are equivalent to the timezone."""

        @staticmethod
        def axisinfo(unit, axis):
            'return the unit AxisInfo'
            # make sure that the axis does not start at 0
            if axis:
                ax = axis.axes

                if axis is ax.get_xaxis():
                    xmin, xmax = ax.dataLim.intervalx
                    if xmin==0.:
                        # no data has been added - let's set the
default datalim.
                        # We should probably use a better proxy for the datalim
                        # have been updated than the ignore setting
                        dmax = today = datetime.date.today()
                        dmin = today-datetime.timedelta(days=10)

                        ax._process_unit_info(xdata=(dmin, dmax))
                        dmin, dmax = ax.convert_xunits([dmin, dmax])

                        ax.viewLim.intervalx = dmin, dmax
                        ax.dataLim.intervalx = dmin, dmax
                elif axis is ax.get_yaxis():
                    ymin, ymax = ax.dataLim.intervaly
                    if ymin==0.:
                        # no data has been added - let's set the
default datalim.
                        # We should probably use a better proxy for the datalim
                        # have been updated than the ignore setting
                        dmax = today = datetime.date.today()
                        dmin = today-datetime.timedelta(days=10)

                        ax._process_unit_info(ydata=(dmin, dmax))
                        dmin, dmax = ax.convert_yunits([dmin, dmax])

                        ax.viewLim.intervaly = dmin, dmax
                        ax.dataLim.intervaly = dmin, dmax

            majloc = AutoDateLocator(tz=unit)
            majfmt = AutoDateFormatter(majloc, tz=unit)
            return units.AxisInfo( majloc=majloc, majfmt=majfmt, label='' )

        @staticmethod
        def convert(value, unit, axis):
            if units.ConversionInterface.is_numlike(value): return value
            return date2num(value)

        @staticmethod
        def default_units(x, axis):
            'Return the default unit for *x* or None'
            return None


    units.registry[datetime.date] = DateConverter()
    units.registry[datetime.datetime] = DateConverter()

See the matplotlib.units module for more info.

> ax.plot(values.rescale('cm')
> ax.set_xlim(limits.rescale('cm'))
>
> a bit klunkier, but very clear. Explicit is better than implicit...

I'm open to the idea of not supporting post-facto conversions after
data is added, but am mostly minus one on it, and I'd like to hear
from the JPL who requested the ability initially.  I think their users
are working with complex plots and might have arrays in different
distance units, and would like to be able to pass in any distance
units as long as conversion is possible.  I think having proper units
support kind of implies that you should be able to handle conversion
between compatible units seamlessly.  Else we are basically in the
date2num world -- just make all the users convert to floats before
working with mpl, since there is little difference between the code
you suggest::

  ax.plot(values.rescale('cm'))
  ax.set_xlim(limits.rescale('cm'))


and::

  ax.plot(values.rescale('cm').tofloat())
  ax.set_xlim(limits.rescale('cm').tofloat())

where the latter means we have no units or custom type support.

JDH

------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
is a gathering of tech-side developers & brand creativity professionals. Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, & 
iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian
Group, R/GA, & Big Spaceship. http://www.creativitycat.com 
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to