Skip to content

Commit c8436ef

Browse files
committed
This is an incomplete fix, but a reasonable one for now.
Basically, mpl has its own datetime system, where it uses floating point versions of the Gregorian calendar days. My attempt to use ISO formatted date-time strings failed. Therefore, I'm actually manually formatting the time-string based on epoch time after converting from mpl_date -> epoch time. Whew!
1 parent 1f5edc9 commit c8436ef

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

plotly/matplotlylib/mpltools.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import math
99
import warnings
10+
import datetime
11+
import matplotlib.dates
1012

1113
def check_bar_match(old_bar, new_bar):
1214
"""Check if two bars belong in the same collection (bar chart).
@@ -416,6 +418,17 @@ def prep_ticks(ax, index, ax_type, props):
416418
return dict()
417419
# get tick label formatting information
418420
formatter = axis.get_major_formatter().__class__.__name__
421+
if ax_type == 'x' and formatter == 'DateFormatter':
422+
axis_dict['type'] = 'date'
423+
try:
424+
axis_dict['tick0'] = mpl_dates_to_datestrings(axis_dict['tick0'])
425+
except KeyError:
426+
pass
427+
finally:
428+
axis_dict.pop('dtick', None)
429+
axis_dict.pop('autotick', None)
430+
axis_dict['range'] = mpl_dates_to_datestrings(props['xlim'])
431+
419432
if formatter == 'LogFormatterMathtext':
420433
axis_dict['exponentformat'] = 'e'
421434
return axis_dict
@@ -442,6 +455,22 @@ def prep_xy_axis(ax, props, x_bounds, y_bounds):
442455
yaxis.update(prep_ticks(ax, 1, 'y', props))
443456
return xaxis, yaxis
444457

458+
def mpl_dates_to_datestrings(mpl_dates, format_string="%Y-%m-%d %H:%M:%S"):
459+
try:
460+
# make sure we have a list
461+
mpl_date_list = list(mpl_dates)
462+
epoch_times = matplotlib.dates.num2epoch(mpl_date_list)
463+
date_times = [datetime.datetime.fromtimestamp(epoch_time)
464+
for epoch_time in epoch_times]
465+
time_strings = [date_time.strftime(format_string)
466+
for date_time in date_times]
467+
if len(time_strings) > 1:
468+
return time_strings
469+
else:
470+
return time_strings[0]
471+
except TypeError:
472+
return mpl_dates
473+
445474

446475
DASH_MAP = {
447476
'10,0': 'solid',

plotly/matplotlylib/renderer.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def __init__(self):
5454
self.bar_containers = None
5555
self.current_bars = []
5656
self.axis_ct = 0
57+
self.x_is_mpl_date = False
5758
self.mpl_x_bounds = (0, 1)
5859
self.mpl_y_bounds = (0, 1)
5960
self.msg = "Initialized PlotlyRenderer\n"
@@ -176,6 +177,10 @@ def open_axes(self, ax, props):
176177
self.plotly_fig['layout']['xaxis{0}'.format(self.axis_ct)] = xaxis
177178
self.plotly_fig['layout']['yaxis{0}'.format(self.axis_ct)] = yaxis
178179

180+
# let all subsequent dates be handled properly if required
181+
if xaxis.get('type') == 'date':
182+
self.x_is_mpl_date = True
183+
179184
def close_axes(self, ax):
180185
"""Close the axes object and clean up.
181186
@@ -190,6 +195,7 @@ def close_axes(self, ax):
190195
"""
191196
self.draw_bars(self.current_bars)
192197
self.msg += " Closing axes\n"
198+
self.x_is_mpl_date = False
193199

194200
def draw_bars(self, bars):
195201

@@ -357,6 +363,10 @@ def draw_marked_line(self, **props):
357363
yaxis='y{0}'.format(self.axis_ct),
358364
line=line,
359365
marker=marker)
366+
if self.x_is_mpl_date:
367+
marked_line['x'] = mpltools.mpl_dates_to_datestrings(
368+
marked_line['x']
369+
)
360370
self.plotly_fig['data'] += marked_line,
361371
self.msg += " Heck yeah, I drew that line\n"
362372
else:

0 commit comments

Comments
 (0)