Skip to content

Commit

Permalink
Fixed bug datashading NdOverlay with datetime axis
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Jun 26, 2018
1 parent 579e350 commit 46316b4
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
18 changes: 15 additions & 3 deletions holoviews/operation/datashader.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,14 @@ def _aggregate_ndoverlay(self, element, agg_fn):
x, y = element.last.dimensions()[0:2]
info = self._get_sampling(element, x, y)
(x_range, y_range), (xs, ys), (width, height), (xtype, ytype) = info
if xtype == 'datetime':
x_range = tuple((np.array(x_range)/10e5).astype('datetime64[us]'))
if ytype == 'datetime':
y_range = tuple((np.array(y_range)/10e5).astype('datetime64[us]'))
agg_params = dict({k: v for k, v in dict(self.get_param_values(), **self.p).items()
if k in aggregate.params()},
x_range=x_range, y_range=y_range)
bbox = BoundingBox(points=[(x_range[0], y_range[0]), (x_range[1], y_range[1])])

# Optimize categorical counts by aggregating them individually
if isinstance(agg_fn, ds.count_cat):
Expand All @@ -359,7 +364,11 @@ def _aggregate_ndoverlay(self, element, agg_fn):
else:
grouped = element.groupby([agg_fn.column], container_type=NdOverlay,
group_type=NdOverlay)
return grouped.clone({k: agg_fn1(v) for k, v in grouped.items()})
groups = []
for k, v in grouped.items():
agg = agg_fn1(v)
groups.append((k, agg.clone(agg.data, bounds=bbox)))
return grouped.clone(groups)

# Create aggregate instance for sum, count operations, breaking mean
# into two aggregates
Expand Down Expand Up @@ -402,22 +411,25 @@ def _aggregate_ndoverlay(self, element, agg_fn):
# Fill masked with with NaNs
if is_sum:
agg.data[column].values[mask] = np.NaN
return agg

return agg.clone(bounds=bbox)


def _process(self, element, key=None):
agg_fn = self._get_aggregator(element)
category = agg_fn.column if isinstance(agg_fn, ds.count_cat) else None

if (isinstance(element, NdOverlay) and
((isinstance(agg_fn, (ds.count, ds.sum, ds.mean)) and agg_fn.column not in element.kdims) or
((isinstance(agg_fn, (ds.count, ds.sum, ds.mean)) and
(agg_fn.column is None or agg_fn.column not in element.kdims)) or
(isinstance(agg_fn, ds.count_cat) and agg_fn.column in element.kdims))):
return self._aggregate_ndoverlay(element, agg_fn)

if element._plot_id in self._precomputed:
x, y, data, glyph = self._precomputed[element._plot_id]
else:
x, y, data, glyph = self.get_agg_data(element, category)

if self.p.precompute:
self._precomputed[element._plot_id] = x, y, data, glyph
(x_range, y_range), (xs, ys), (width, height), (xtype, ytype) = self._get_sampling(element, x, y)
Expand Down
20 changes: 20 additions & 0 deletions tests/operation/testdatashader.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,26 @@ def test_aggregate_curve_datetimes_microsecond_timebase(self):
datatype=['xarray'], bounds=bounds, vdims='Count')
self.assertEqual(img, expected)

def test_aggregate_ndoverlay_count_cat_datetimes_microsecond_timebase(self):
dates = pd.date_range(start="2016-01-01", end="2016-01-03", freq='1D')
xstart = np.datetime64('2015-12-31T23:59:59.723518000', 'us')
xend = np.datetime64('2016-01-03T00:00:00.276482000', 'us')
curve = Curve((dates, [1, 2, 3]))
curve2 = Curve((dates, [3, 2, 1]))
ndoverlay = NdOverlay({0: curve, 1: curve2}, 'Cat')
imgs = aggregate(ndoverlay, aggregator=ds.count_cat('Cat'), width=2, height=2,
x_range=(xstart, xend), dynamic=False)
bounds = (np.datetime64('2015-12-31T23:59:59.723518'), 1.0,
np.datetime64('2016-01-03T00:00:00.276482'), 3.0)
dates = [np.datetime64('2016-01-01T11:59:59.861759000',),
np.datetime64('2016-01-02T12:00:00.138241000')]
expected = Image((dates, [1.5, 2.5], [[1, 0], [0, 2]]),
datatype=['xarray'], bounds=bounds, vdims='Count')
expected2 = Image((dates, [1.5, 2.5], [[0, 1], [1, 1]]),
datatype=['xarray'], bounds=bounds, vdims='Count')
self.assertEqual(imgs[0], expected)
self.assertEqual(imgs[1], expected2)

def test_aggregate_ndoverlay(self):
ds = Dataset([(0.2, 0.3, 0), (0.4, 0.7, 1), (0, 0.99, 2)], kdims=['x', 'y', 'z'])
ndoverlay = ds.to(Points, ['x', 'y'], [], 'z').overlay()
Expand Down

0 comments on commit 46316b4

Please sign in to comment.