From 311e5728db7e2e2988a59b87365c447f00f33861 Mon Sep 17 00:00:00 2001 From: arabidopsis Date: Sun, 28 Apr 2019 16:25:49 +0800 Subject: [PATCH] add dimensioned streams to DynamicMap clone (#3658) --- holoviews/core/overlay.py | 6 ++-- holoviews/core/spaces.py | 4 ++- .../tests/plotting/bokeh/testlayoutplot.py | 28 ++++++++++++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/holoviews/core/overlay.py b/holoviews/core/overlay.py index af49d06654..b34a026387 100644 --- a/holoviews/core/overlay.py +++ b/holoviews/core/overlay.py @@ -14,7 +14,7 @@ from .dimension import Dimension, Dimensioned, ViewableElement, ViewableTree from .ndmapping import UniformNdMapping from .layout import Composable, Layout, AdjointLayout -from .util import config, sanitize_identifier, unique_array +from .util import config, sanitize_identifier, unique_array, dimensioned_streams class Overlayable(object): @@ -33,7 +33,7 @@ def dynamic_mul(*args, **kwargs): callback = Callable(dynamic_mul, inputs=[self, other]) callback._is_overlay = True return other.clone(shared_data=False, callback=callback, - streams=[]) + streams=dimensioned_streams(other)) if isinstance(other, UniformNdMapping) and not isinstance(other, CompositeOverlay): items = [(k, self * v) for (k, v) in other.items()] return other.clone(items) @@ -187,7 +187,7 @@ def dynamic_mul(*args, **kwargs): callback = Callable(dynamic_mul, inputs=[self, other]) callback._is_overlay = True return other.clone(shared_data=False, callback=callback, - streams=[]) + streams=dimensioned_streams(other)) elif not isinstance(other, ViewableElement): return NotImplemented return Overlay([self, other]) diff --git a/holoviews/core/spaces.py b/holoviews/core/spaces.py index af105b32fb..6a07f02752 100644 --- a/holoviews/core/spaces.py +++ b/holoviews/core/spaces.py @@ -296,7 +296,7 @@ def dynamic_mul(*args, **kwargs): callback = Callable(dynamic_mul, inputs=[self, other]) callback._is_overlay = True return self.clone(shared_data=False, callback=callback, - streams=[]) + streams=util.dimensioned_streams(self)) items = [(k, other * v) if reverse else (k, v * other) for (k, v) in self.data.items()] return self.clone(items, label=self._label, group=self._group) @@ -1527,6 +1527,7 @@ def collate(self): # Get stream mapping from callback remapped_streams = [] + self_dstreams = util.dimensioned_streams(self) streams = self.callback.stream_mapping for i, (k, v) in enumerate(initialized.last.data.items()): vstreams = streams.get(i, []) @@ -1576,6 +1577,7 @@ def collation_cb(*args, **kwargs): selection_index=type_counter[type(v)], selection_type=type(v)), inputs=[self]) + vstreams = list(util.unique_iterator(self_dstreams + vstreams)) vdmap = self.clone(callback=callback, shared_data=False, streams=vstreams) type_counter[type(v)] += 1 diff --git a/holoviews/tests/plotting/bokeh/testlayoutplot.py b/holoviews/tests/plotting/bokeh/testlayoutplot.py index a2e2b4de63..d7d1116349 100644 --- a/holoviews/tests/plotting/bokeh/testlayoutplot.py +++ b/holoviews/tests/plotting/bokeh/testlayoutplot.py @@ -2,7 +2,7 @@ from holoviews.core import (HoloMap, GridSpace, Layout, Empty, Dataset, NdOverlay, DynamicMap, Dimension) -from holoviews.element import Curve, Image, Points +from holoviews.element import Curve, Image, Points, HLine, VLine, Path, Histogram from holoviews.streams import Stream from .testplot import TestBokehPlot, bokeh_renderer @@ -271,3 +271,29 @@ def test_layout_axis_not_linked_mismatching_unit(self): plot = bokeh_renderer.get_plot(layout) p1, p2 = (sp.subplots['main'] for sp in plot.subplots.values()) self.assertIsNot(p1.handles['y_range'], p2.handles['y_range']) + + def test_dimensioned_streams_with_dynamic_map_overlay_clone(self): + time = Stream.define('Time', time=-3.0)() + def crosshair(time): + return VLine(time) * HLine(time) + crosshair = DynamicMap(crosshair, kdims='time', streams=[time]) + path = Path([]) + t = crosshair * path + html, _ = bokeh_renderer(t) + self.assertIn('Bokeh Application', html) + + def test_dimensioned_streams_with_dynamic_callback_returns_layout(self): + stream = Stream.define('aname', aname='a')() + def cb(aname): + x = np.linspace(0, 1, 10) + y = np.random.randn(10) + curve = Curve((x, y), group=aname) + hist = Histogram(y) + return (curve + hist).opts(shared_axes=False) + m = DynamicMap(cb, kdims=['aname'], streams=[stream]) + p = bokeh_renderer.get_plot(m) + T = 'XYZT' + stream.event(aname=T) + self.assertIn('aname: ' + T, p.handles['title'].text, p.handles['title'].text) + p.cleanup() + self.assertEqual(stream._subscribers, []) \ No newline at end of file