Skip to content

Commit

Permalink
Simplified Layout/Overlay path resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Feb 11, 2017
1 parent 6dfc903 commit 084ce85
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 42 deletions.
57 changes: 27 additions & 30 deletions holoviews/core/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from functools import reduce
from itertools import chain
from collections import defaultdict
from collections import defaultdict, Counter

import numpy as np

Expand Down Expand Up @@ -333,41 +333,18 @@ def collate(cls, data, kdims=None, key_dimensions=None):
def new_path(cls, path, item, paths, counts):
sanitizers = [sanitize_identifier, group_sanitizer, label_sanitizer]
path = tuple(fn(p) for (p, fn) in zip(path, sanitizers))
while any(path[:i] in paths or path in [p[:i] for p in paths]
for i in range(1,len(path)+1)):
while path in paths:
path = path[:2]
pl = len(path)
count = counts[path[:-1]]
counts[path[:-1]] += 1
if (pl == 1 and not item.label) or (pl == 2 and item.label):
new_path = path + (int_to_roman(count-1),)
if path in paths:
paths[paths.index(path)] = new_path
path = path + (int_to_roman(count),)
path = path + (int_to_roman(count-1),)
else:
path = path[:-1] + (int_to_roman(count),)
return path


@classmethod
def relabel_item_paths(cls, items):
"""
Given a list of path items (list of tuples where each element
is a (path, element) pair), generate a new set of path items that
guarantees that no paths clash. This uses the element labels as
appropriate and automatically generates roman numeral
identifiers if necessary.
"""
paths, path_items = [], []
counts = defaultdict(lambda: 2)
for path, item in items:
new_path = cls.new_path(path, item, paths, counts)
new_path = tuple(''.join((p[0].upper(), p[1:])) for p in new_path)
path_items.append(item)
paths.append(new_path)
return list(zip(paths, path_items))


@classmethod
def _unpack_paths(cls, objs, paths, items, counts):
"""
Expand All @@ -389,6 +366,25 @@ def _unpack_paths(cls, objs, paths, items, counts):
paths.append(new_path)
items.append((new_path, v))

@classmethod
def _initial_paths(cls, vals, paths=None):
if paths is None:
paths = []

for v in vals:
if type(v) is cls:
cls._initial_paths(v.values(), paths)
continue
group = group_sanitizer(v.group)
group = ''.join([group[0].upper(), group[1:]])
if v.label:
label = label_sanitizer(v.label)
label = ''.join([label[0].upper(), label[1:]])
path = (group, label)
else:
path = (group,)
paths.append(path)
return paths

@classmethod
def from_values(cls, val):
Expand All @@ -401,7 +397,10 @@ def from_values(cls, val):
return val
elif not collection:
val = [val]
paths, items = [], []
paths = cls._initial_paths(val)
path_counter = Counter(paths)
paths = [k for k, v in path_counter.items() if v > 1]
items = []
counts = defaultdict(lambda: 2)
cls._unpack_paths(val, paths, items, counts)
return cls(items=items)
Expand Down Expand Up @@ -518,9 +517,7 @@ def __len__(self):


def __add__(self, other):
other = self.from_values(other)
items = list(self.data.items()) + list(other.data.items())
return Layout(items=self.relabel_item_paths(items)).display('all')
return Layout.from_values([self, other]).display('all')



Expand Down
15 changes: 3 additions & 12 deletions holoviews/core/overlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ def dynamic_mul(*args, **kwargs):
items = [(k, self * v) for (k, v) in other.items()]
return other.clone(items)

self_item = [((self.group, self.label if self.label else 'I'), self)]
other_items = (other.items() if isinstance(other, Overlay)
else [((other.group, other.label if other.label else 'I'), other)])
return Overlay(items=Overlay.relabel_item_paths(list(self_item) + list(other_items)))
return Overlay.from_values([self, other])



Expand Down Expand Up @@ -142,15 +139,9 @@ def __add__(self, other):


def __mul__(self, other):
if isinstance(other, Overlay):
items = list(self.data.items()) + list(other.data.items())
elif isinstance(other, ViewableElement):
label = other.label if other.label else 'I'
items = list(self.data.items()) + [((other.group, label), other)]
elif isinstance(other, UniformNdMapping):
if isinstance(other, UniformNdMapping):
raise NotImplementedError

return Overlay(items=self.relabel_item_paths(items)).display('all')
return Overlay.from_values([self, other])


def collate(self):
Expand Down

0 comments on commit 084ce85

Please sign in to comment.