From 2e801dabdc730f969734026f7dbccf664cad6c5f Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 26 Oct 2016 00:07:42 +0100 Subject: [PATCH 1/3] Reimplemented Layout.from_values --- holoviews/core/layout.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/holoviews/core/layout.py b/holoviews/core/layout.py index 828ab0f3c5..f994b72471 100644 --- a/holoviews/core/layout.py +++ b/holoviews/core/layout.py @@ -366,10 +366,6 @@ def relabel_item_paths(cls, items): return list(zip(paths, path_items)) - @classmethod - def _from_values(cls, val): - return reduce(lambda x,y: x+y, val).display('auto') - @classmethod def from_values(cls, val): """ @@ -379,15 +375,20 @@ def from_values(cls, val): collection = isinstance(val, (list, tuple)) if type(val) is cls: return val - elif collection and len(val)>1: - return cls._from_values(val) - elif collection: - val = val[0] - group = group_sanitizer(val.group) - group = ''.join([group[0].upper(), group[1:]]) - label = label_sanitizer(val.label if val.label else 'I') - label = ''.join([label[0].upper(), label[1:]]) - return cls(items=[((group, label), val)]) + elif not collection: + val = [val] + paths, items = [], [] + count = 2 + for v in val: + group = group_sanitizer(v.group) + group = ''.join([group[0].upper(), group[1:]]) + label = label_sanitizer(v.label if v.label else 'I') + label = ''.join([label[0].upper(), label[1:]]) + new_path, count = cls.new_path((group, label), v, paths, count) + new_path = tuple(''.join((p[0].upper(), p[1:])) for p in new_path) + paths.append(new_path) + items.append((new_path, v)) + return cls(items=items) def __init__(self, items=None, identifier=None, parent=None, **kwargs): From 84b0a9a0dd621a9990064290327d2a12b8cfaa4a Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 26 Oct 2016 00:08:26 +0100 Subject: [PATCH 2/3] Added collate method on Overlay --- holoviews/core/overlay.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/holoviews/core/overlay.py b/holoviews/core/overlay.py index 0a611da9ca..cf162b1597 100644 --- a/holoviews/core/overlay.py +++ b/holoviews/core/overlay.py @@ -149,6 +149,14 @@ def __mul__(self, other): return Overlay(items=self.relabel_item_paths(items)).display('all') + def collate(self): + """ + Collates any objects in the Overlay resolving any issues + the recommended nesting structure. + """ + return reduce(lambda x,y: x*y, self.values()) + + def collapse(self, function): """ Collapses all the Elements in the Overlay using the From f5c9e2f6756f2772d6c3e90bff56dc09389e605b Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 26 Oct 2016 00:10:32 +0100 Subject: [PATCH 3/3] Overlays containing GridSpaces/HoloMaps auto-collate --- holoviews/plotting/util.py | 15 ++++++++++++++- tests/testcollation.py | 17 +++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/holoviews/plotting/util.py b/holoviews/plotting/util.py index f272018594..26aaaa5d14 100644 --- a/holoviews/plotting/util.py +++ b/holoviews/plotting/util.py @@ -4,7 +4,7 @@ import param from ..core import (HoloMap, DynamicMap, CompositeOverlay, Layout, - GridSpace, NdLayout, Store) + GridSpace, NdLayout, Store, Overlay) from ..core.util import (match_spec, is_number, wrap_tuple, basestring, get_overlay_spec, unique_iterator, safe_unicode) @@ -14,6 +14,9 @@ def displayable(obj): Predicate that returns whether the object is displayable or not (i.e whether the object obeys the nesting hierarchy """ + if isinstance(obj, Overlay) and any(isinstance(o, (HoloMap, GridSpace)) + for o in obj): + return False if isinstance(obj, HoloMap): return not (obj.type in [Layout, GridSpace, NdLayout]) if isinstance(obj, (GridSpace, Layout, NdLayout)): @@ -28,6 +31,16 @@ class Warning(param.Parameterized): pass display_warning = Warning(name='Warning') def collate(obj): + if isinstance(obj, Overlay): + nested_type = [type(o).__name__ for o in obj + if isinstance(o, (HoloMap, GridSpace))][0] + display_warning.warning("Nesting %ss within an Overlay makes it difficult " + "to access your data or control how it appears; " + "we recommend calling .collate() on the Overlay " + "in order to follow the recommended nesting " + "structure shown in the Composing Data tutorial" + "(http://git.io/vtIQh)" % nested_type) + return obj.collate() if isinstance(obj, HoloMap): display_warning.warning("Nesting %ss within a HoloMap makes it difficult " "to access your data or control how it appears; " diff --git a/tests/testcollation.py b/tests/testcollation.py index 51d035e50c..479843c464 100644 --- a/tests/testcollation.py +++ b/tests/testcollation.py @@ -7,10 +7,12 @@ import numpy as np -from holoviews.core import Collator, HoloMap, NdOverlay +from holoviews.core import Collator, HoloMap, NdOverlay, Overlay, GridSpace from holoviews.element import Curve +from holoviews.element.comparison import ComparisonTestCase -class TestCollation(unittest.TestCase): + +class TestCollation(ComparisonTestCase): def setUp(self): alphas, betas, deltas = 2, 2, 2 Bs = list(range(100)) @@ -67,3 +69,14 @@ def test_collate_layout_hmap(self): collated = collated() self.assertEqual(repr(collated), repr(layout)) self.assertEqual(collated.dimensions(), layout.dimensions()) + + def test_overlay_hmap_collate(self): + hmap = HoloMap({i: Curve(np.arange(10)*i) for i in range(3)}) + overlaid = Overlay([hmap, hmap, hmap]).collate() + self.assertEqual(overlaid, hmap*hmap*hmap) + + def test_overlay_gridspace_collate(self): + grid = GridSpace({(i,j): Curve(np.arange(10)*i) for i in range(3) + for j in range(3)}) + overlaid = Overlay([grid, grid, grid]).collate() + self.assertEqual(overlaid, grid*grid*grid)