Skip to content

Commit

Permalink
Added support for cftime types
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed May 25, 2018
1 parent 49370f9 commit 72d71a0
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 8 deletions.
6 changes: 6 additions & 0 deletions holoviews/core/data/xarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
from .grid import GridInterface
from .interface import Interface, DataError

try:
import cftime
util.datetime_types += (cftime._cftime.DatetimeGregorian,)
except:
pass


class XArrayInterface(GridInterface):

Expand Down
4 changes: 3 additions & 1 deletion holoviews/plotting/bokeh/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from .plot import BokehPlot, TOOLS
from .util import (mpl_to_bokeh, get_tab_title, py2js_tickformatter,
rgba_tuple, recursive_model_update, glyph_order,
decode_bytes)
decode_bytes, date_to_integer)

property_prefixes = ['selection', 'nonselection', 'muted', 'hover']

Expand Down Expand Up @@ -528,6 +528,8 @@ def _update_range(self, axis_range, low, high, factors, invert, shared, log, str
if util.isfinite(high):
updates['end'] = (axis_range.end, high)
for k, (old, new) in updates.items():
if isinstance(new, util.datetime_types):
new = date_to_integer(new)
axis_range.update(**{k:new})
if streaming:
axis_range.trigger(k, old, new)
Expand Down
25 changes: 21 additions & 4 deletions holoviews/plotting/bokeh/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@
from ...core import (OrderedDict, Store, AdjointLayout, NdLayout, Layout,
Empty, GridSpace, HoloMap, Element, DynamicMap)
from ...core.options import SkipRendering
from ...core.util import basestring, wrap_tuple, unique_iterator, get_method_owner
from ...core.util import (basestring, wrap_tuple, unique_iterator,
get_method_owner, datetime_types)
from ...streams import Stream
from ..plot import (DimensionedPlot, GenericCompositePlot, GenericLayoutPlot,
GenericElementPlot, GenericOverlayPlot)
from ..util import attach_streams, displayable, collate
from .callbacks import Callback
from .util import (layout_padding, pad_plots, filter_toolboxes, make_axis,
update_shared_sources, empty_plot, decode_bytes,
bokeh_version)
bokeh_version, date_to_integer)

from bokeh.layouts import gridplot
from bokeh.plotting.helpers import _known_tools as known_tools
Expand Down Expand Up @@ -184,15 +185,31 @@ def _init_datasource(self, data):
"""
Initializes a data source to be passed into the bokeh glyph.
"""
data = {k: decode_bytes(vs) for k, vs in data.items()}
data = self._postprocess_data(data)
return ColumnDataSource(data=data)


def _postprocess_data(self, data):
"""
Applies necessary type transformation to the data before
it is set on a ColumnDataSource.
"""
new_data = {}
for k, values in data.items():
values = decode_bytes(values) # Bytes need decoding to strings

# Certain datetime types need to be converted
if len(values) and isinstance(values[0], datetime_types):
values = np.array([date_to_integer(v) for v in values])
new_data[k] = values
return new_data


def _update_datasource(self, source, data):
"""
Update datasource with data for a new frame.
"""
data = {k: decode_bytes(vs) for k, vs in data.items()}
data = self._postprocess_data(data)
empty = all(len(v) == 0 for v in data.values())
if (self.streaming and self.streaming[0].data is self.current_frame.data
and self._stream_data and not empty):
Expand Down
6 changes: 3 additions & 3 deletions holoviews/plotting/bokeh/util.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import re, time, sys
import re, time, sys, calendar
from distutils.version import LooseVersion
from collections import defaultdict
import datetime as dt
Expand Down Expand Up @@ -617,8 +617,8 @@ def date_to_integer(date):
date = dt64_to_dt(date)
elif pd and isinstance(date, pd.Timestamp):
date = date.to_pydatetime()
if isinstance(date, (dt.datetime, dt.date)):
dt_int = time.mktime(date.timetuple())*1000
if hasattr(date, 'timetuple'):
dt_int = calendar.timegm(date.timetuple())*1000
else:
raise ValueError('Datetime type not recognized')
return dt_int
Expand Down

0 comments on commit 72d71a0

Please sign in to comment.