-
-
Notifications
You must be signed in to change notification settings - Fork 8k
Description
When given an object to plot, should matplotlib attempt to use a registered units.ConversionInterface
for that object's type (and mro) before falling back to other built-in defaults?
This question/suggestion prompted by the following example:
Say one has a class
class DateTimeNano(np.ndarray):
...
subclassing np.ndarray
with the convention that DateTimeNano
stores nano-seconds since epoch. When plotting a DateTimeNano
, one may want to make use of the built in utilities for date tick location/formatting. If one writes a units.ConversionInterface
like
class DateTimeNanoConverter(units.ConversionInterface):
NANOS_PER_DAY = 86_400*1_000_000_000
@staticmethod
def convert(value, unit, axis):
# Values should be in floating point days since epoch to play nice with mpl
day_floats = value / DateTimeNanoConverter.NANOS_PER_DAY
return day_floats
@staticmethod
def axisinfo(unit, axis):
majloc = dates.AutoDateLocator()
majfmt = dates.AutoDateFormatter(majloc)
return AxisInfo(majloc=majloc, majfmt=majfmt, label='date time')
@staticmethod
def default_units(x, axis):
return 'date_time'
registers it with
units.registry[DateTimeNano] = DateTimeNanoConverter
and then calls
plt.plot(my_date_time_nano, my_y_values)
only DateTimeNanoConverter.default_units
and DateTimeNanoConverter.axisinfo
are used. DateTimeNanoConverter.convert
is skipped entirely as units._is_natively_supported
recognizes that it is an iterable and so a converter for the type DateTimeNano
is never searched for (it also appears that this would be short circuited in units.Registry.get_converter
).
If the step of searching for a converter by iterating over the type's mro were moved up in the order of trying to get values out of an object, this problem would not occur. It also seems like an overall preferred behavior as searching for a way to get an array of values out (using a converter or built-in code paths) should always start with the most specific implementation and work out.
This does not currently happen if types happen to have a particular inheritance structure or set of attributes.