When plotting with DateTime on the x axis, it would be useful to show both the date and time in the cursor position. Currently only the date or time is shown, depending on zoom level.
Example: only the date is shown in bottom left (x=2016-10-16)
Current master installed using pip, Linux, python 3.5.2
The value shown the bar is by default pulled from the axis Formaterr via the format_data_short method. The default implementation is just the delegate to fomat_data which in turn delegates to __call__ (for historical reasons).
To trace through the call path here, in backend_bases.NavigationToolbar2.mouse_move (which is hooked up to the mouse move callback) calls Axes.format_coord and puts the result in the GUI msg area. format_coord (in axes/_base.py) calls format_xdata / format_ydata which in turn check if there is a user supplied fmt_xdata or fmt_ydata attributes on the Axes object and if not calls the axis's major formatters format_data_short method.
The specific work here is:
add a format_data_short method to the auto data formatter that uses the next more precise format from what __call__ uses.
I don't think there's a way to make this work for everyone, in the sense that most of the time I'd think you'd only want to use the date OR the time? Probably a doc recipe (which could be, in an ideal world, as simple as ax.xaxis.get_major_formatter().format_data_short = lambda pos: lambda pos: mdates.num2date(pos).strftime("%Y-%m-%d; %H:%M:%S") would be better?
Anyways, while trying to come up with such a recipe, I found a bunch of issues with datetime and ticker handling.
matplotlib.dates should probably export its own strftime function which transparently handles matplotlib timestamps (avoiding the need to call num2date explicitly).
The fact that formatters are callable, which I argued against in New Formatter API #5804, makes it possible to write ax.format_xdata = Formatter(...) (e.g. examples/api/date_demo.py), which is a mess as the axes' formatter instance is not correctly set, so format_data_short confusingly doesn't work -- that example really needs to be changed to something like
or alternatively we should just make Axes.format_xdata a property that redirects to Axes.xaxis.major.formatter, so that one can assign to format_xdata and then to format_xdata.format_data_short. (Actually the second solution isn't bad...)
In other words the pile of redirections going on is really hard to keep track of. (Unlabeling as "easy" and "new-contributor-friendly" for this reason.)
examples/api/date_index_formatter.py makes no sense, especially its docstring? Neither plot is labelling or plotting week-ends.
The two use cases I currently frequently encounter are:
Looking at a large scale overview (as above), but wanting to know the time of an obvious feature
Zooming into data (e.g. the data above) to look at precisely where a feature is, but then loosing information about the date. This means having to zoom back out again to try and find the feature in 'date zoomlevel'.
Even if you want to know one or the other, showing both doesn't (as far as I can see) impact on this.
My point was that showing too much info could be slightly annoying when the timescale is obviously either very large or very small, but I guess that's not a big cost (and erring on the side of too much info is probably better). In that case I'd suggest always showing cursor data either with the %c (locale) strftime format, or with isoformat().
Perhaps this feature needs a complete overhaul? Perhaps supporting a format
string with named components? That way, the user can easily customize the
output. The hard part will be trying to automatically generate a good
default format string.
Activity
tacaswell commented on Dec 7, 2016
The value shown the bar is by default pulled from the axis Formaterr via the format_data_short method. The default implementation is just the delegate to fomat_data which in turn delegates to __call__ (for historical reasons).
To trace through the call path here, in backend_bases.NavigationToolbar2.mouse_move (which is hooked up to the mouse move callback) calls Axes.format_coord and puts the result in the GUI msg area. format_coord (in axes/_base.py) calls format_xdata / format_ydata which in turn check if there is a user supplied fmt_xdata or fmt_ydata attributes on the Axes object and if not calls the axis's major formatters format_data_short method.
The specific work here is:
attn @anntzer
anntzer commented on Dec 7, 2016
I don't think there's a way to make this work for everyone, in the sense that most of the time I'd think you'd only want to use the date OR the time? Probably a doc recipe (which could be, in an ideal world, as simple as ax.xaxis.get_major_formatter().format_data_short = lambda pos: lambda pos: mdates.num2date(pos).strftime("%Y-%m-%d; %H:%M:%S") would be better?
Anyways, while trying to come up with such a recipe, I found a bunch of issues with datetime and ticker handling.
matplotlib.dates should probably export its own strftime function which transparently handles matplotlib timestamps (avoiding the need to call num2date explicitly).
The fact that formatters are callable, which I argued against in New Formatter API #5804, makes it possible to write ax.format_xdata = Formatter(...) (e.g. examples/api/date_demo.py), which is a mess as the axes' formatter instance is not correctly set, so format_data_short confusingly doesn't work -- that example really needs to be changed to something like
import time _fmt = mdates.DateFormatter('%Y-%m-%d') _fmt.format_data_short = lambda pos: mdates.num2date(pos).strftime("%Y-%m-%d; %H:%M:%S") ax.xaxis.set_major_formatter(_fmt)or alternatively we should just make Axes.format_xdata a property that redirects to Axes.xaxis.major.formatter, so that one can assign to format_xdata and then to format_xdata.format_data_short. (Actually the second solution isn't bad...)
In other words the pile of redirections going on is really hard to keep track of. (Unlabeling as "easy" and "new-contributor-friendly" for this reason.)
dstansby commented on Dec 7, 2016
The two use cases I currently frequently encounter are:
Even if you want to know one or the other, showing both doesn't (as far as I can see) impact on this.
anntzer commented on Dec 7, 2016
My point was that showing too much info could be slightly annoying when the timescale is obviously either very large or very small, but I guess that's not a big cost (and erring on the side of too much info is probably better). In that case I'd suggest always showing cursor data either with the %c (locale) strftime format, or with isoformat().
jklymak commented on Mar 24, 2018
#10084 does the annoying thing of the big label. Its actually not that annoying.
WeatherGod commented on Mar 24, 2018
jklymak commented on Mar 24, 2018
there is a method to change that display, but I forget what its called.
jklymak commented on Mar 24, 2018
Ax.format_cursor
dstansby commented on Apr 8, 2018
I think this has improved enough for me to close the original issue now.