Skip to content

Commit

Permalink
Fixes to ensure streams are correctly mapped to plots (#6415)
Browse files Browse the repository at this point in the history
Co-authored-by: Maxime Liquet <[email protected]>
  • Loading branch information
philippjfr and maximlt authored Oct 18, 2024
1 parent 31ee32d commit 4061614
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 22 deletions.
8 changes: 5 additions & 3 deletions holoviews/plotting/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from ..core.options import Compositor, SkipRendering, Store, lookup_options
from ..core.overlay import CompositeOverlay, NdOverlay, Overlay
from ..core.spaces import DynamicMap, HoloMap
from ..core.util import isfinite, stream_parameters
from ..core.util import isfinite, stream_parameters, unique_iterator
from ..element import Graph, Table
from ..selection import NoOpSelectionDisplay
from ..streams import RangeX, RangeXY, RangeY, Stream
Expand Down Expand Up @@ -1817,8 +1817,8 @@ def _create_subplots(self, ranges):
keys, vmaps = self.hmap._split_overlays()

if isinstance(self.hmap, DynamicMap):
dmap_streams = [get_nested_streams(layer) for layer in
split_dmap_overlay(self.hmap)]
dmap_streams = [streams+get_nested_streams(layer) for layer, streams in
zip(*split_dmap_overlay(self.hmap))]
else:
dmap_streams = [None]*len(keys)

Expand All @@ -1830,6 +1830,8 @@ def _create_subplots(self, ranges):

subplots = {}
for (key, vmap, streams) in zip(keys, vmaps, dmap_streams):
if streams:
streams = list(unique_iterator(streams))
subplot = self._create_subplot(key, vmap, streams, ranges)
if subplot is None:
continue
Expand Down
17 changes: 12 additions & 5 deletions holoviews/plotting/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def isoverlay_fn(obj):
"""
Determines whether object is a DynamicMap returning (Nd)Overlay types.
"""
return isinstance(obj, DynamicMap) and (isinstance(obj.last, CompositeOverlay))
return isinstance(obj, CompositeOverlay) or (isinstance(obj, DynamicMap) and (isinstance(obj.last, CompositeOverlay)))


def overlay_depth(obj):
Expand Down Expand Up @@ -233,28 +233,35 @@ def split_dmap_overlay(obj, depth=0):
to determine if a stream update should redraw a particular
subplot.
"""
layers = []
layers, streams = [], []
if isinstance(obj, DynamicMap):
initialize_dynamic(obj)
if issubclass(obj.type, NdOverlay) and not depth:
for _ in obj.last.values():
layers.append(obj)
streams.append(obj.streams)
elif issubclass(obj.type, Overlay):
if obj.callback.inputs and is_dynamic_overlay(obj):
for inp in obj.callback.inputs:
layers += split_dmap_overlay(inp, depth+1)
split, sub_streams = split_dmap_overlay(inp, depth+1)
layers += split
streams += [s+obj.streams for s in sub_streams]
else:
for _ in obj.last.values():
layers.append(obj)
streams.append(obj.streams)
else:
layers.append(obj)
return layers
streams.append(obj.streams)
return layers, streams
if isinstance(obj, Overlay):
for _k, v in obj.items():
layers.append(v)
streams.append([])
else:
layers.append(obj)
return layers
streams.append([])
return layers, streams


def initialize_dynamic(obj):
Expand Down
35 changes: 21 additions & 14 deletions holoviews/tests/plotting/test_plotutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@ def test_dynamic_compute_overlayable_zorders_mixed_dynamic_and_non_dynamic_ndove
self.assertIn(curve, sources[2])
self.assertNotIn(ndoverlay, sources[2])

def test_dynamic_compute_overlayable_zorders_ndoverlays_as_input(self):
ndoverlay1 = NdOverlay({i: Area(range(10+i)) for i in range(2)}).apply(lambda el: el.get(0), dynamic=True)
ndoverlay2 = NdOverlay({i: Area((range(15, 25+i), range(10+i))) for i in range(2)}).apply(lambda el: el.get(0), dynamic=True)
combined = ndoverlay1*ndoverlay2
combined[()]
sources = compute_overlayable_zorders(combined)
assert len(sources) == 2

def test_dynamic_compute_overlayable_zorders_mixed_dynamic_and_dynamic_ndoverlay_with_streams(self):
ndoverlay = DynamicMap(lambda x: NdOverlay({i: Area(range(10+i)) for i in range(2)}),
Expand Down Expand Up @@ -364,61 +371,61 @@ def test_dmap_ndoverlay(self):
test = self.dmap_ndoverlay
initialize_dynamic(test)
layers = [self.dmap_ndoverlay, self.dmap_ndoverlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_overlay(self):
test = self.dmap_overlay
initialize_dynamic(test)
layers = [self.dmap_overlay, self.dmap_overlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_element_mul_dmap_overlay(self):
test = self.dmap_element * self.dmap_overlay
initialize_dynamic(test)
layers = [self.dmap_element, self.dmap_overlay, self.dmap_overlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_element_mul_dmap_ndoverlay(self):
test = self.dmap_element * self.dmap_ndoverlay
initialize_dynamic(test)
layers = [self.dmap_element, self.dmap_ndoverlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_element_mul_element(self):
test = self.dmap_element * self.element
initialize_dynamic(test)
layers = [self.dmap_element, self.element]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_element_mul_overlay(self):
test = self.dmap_element * self.overlay
initialize_dynamic(test)
layers = [self.dmap_element, self.el1, self.el2]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_element_mul_ndoverlay(self):
test = self.dmap_element * self.ndoverlay
initialize_dynamic(test)
layers = [self.dmap_element, self.ndoverlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_overlay_mul_dmap_ndoverlay(self):
test = self.dmap_overlay * self.dmap_ndoverlay
initialize_dynamic(test)
layers = [self.dmap_overlay, self.dmap_overlay, self.dmap_ndoverlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_overlay_mul_element(self):
test = self.dmap_overlay * self.element
initialize_dynamic(test)
layers = [self.dmap_overlay, self.dmap_overlay, self.element]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_overlay_mul_overlay(self):
test = self.dmap_overlay * self.overlay
initialize_dynamic(test)
layers = [self.dmap_overlay, self.dmap_overlay, self.el1, self.el2]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_all_combinations(self):
test = (self.dmap_overlay * self.element * self.dmap_ndoverlay *
Expand All @@ -427,28 +434,28 @@ def test_dmap_all_combinations(self):
layers = [self.dmap_overlay, self.dmap_overlay, self.element,
self.dmap_ndoverlay, self.el1, self.el2, self.dmap_element,
self.ndoverlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_overlay_operation_mul_dmap_ndoverlay(self):
mapped = operation(self.dmap_overlay)
test = mapped * self.dmap_ndoverlay
initialize_dynamic(test)
layers = [mapped, mapped, self.dmap_ndoverlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_overlay_linked_operation_mul_dmap_ndoverlay(self):
mapped = operation(self.dmap_overlay, link_inputs=True)
test = mapped * self.dmap_ndoverlay
initialize_dynamic(test)
layers = [mapped, mapped, self.dmap_ndoverlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)

def test_dmap_overlay_linked_operation_mul_dmap_element_ndoverlay(self):
mapped = self.dmap_overlay.map(lambda x: x.get(0), Overlay)
test = mapped * self.element * self.dmap_ndoverlay
initialize_dynamic(test)
layers = [mapped, self.element, self.dmap_ndoverlay]
self.assertEqual(split_dmap_overlay(test), layers)
self.assertEqual(split_dmap_overlay(test)[0], layers)


class TestPlotColorUtils(ComparisonTestCase):
Expand Down

0 comments on commit 4061614

Please sign in to comment.