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