From 55de02dedc9f4d8f263007d24b4df4e5c9373b19 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Sun, 1 Oct 2017 11:31:25 +0100
Subject: [PATCH 1/8] Standardized constructor signature with dimensions as
positional args
---
holoviews/core/data/__init__.py | 22 +++++++------
holoviews/core/dimension.py | 43 +++++++++-----------------
holoviews/core/element.py | 2 +-
holoviews/core/layout.py | 5 +--
holoviews/core/ndmapping.py | 10 +++---
holoviews/core/overlay.py | 4 +--
holoviews/core/spaces.py | 4 +--
holoviews/element/chart.py | 8 +++--
holoviews/element/chart3d.py | 4 +--
holoviews/element/graphs.py | 4 +--
holoviews/element/path.py | 12 +++----
holoviews/element/raster.py | 17 +++++-----
holoviews/operation/element.py | 10 +++---
holoviews/plotting/widgets/__init__.py | 2 +-
tests/testcomparisonraster.py | 10 +++---
15 files changed, 77 insertions(+), 80 deletions(-)
diff --git a/holoviews/core/data/__init__.py b/holoviews/core/data/__init__.py
index 53f37b8c82..2b93905813 100644
--- a/holoviews/core/data/__init__.py
+++ b/holoviews/core/data/__init__.py
@@ -9,7 +9,7 @@
import param
from ..dimension import redim
-from ..util import dimension_range
+from ..util import dimension_range, basestring
from .interface import Interface, iloc, ndloc
from .array import ArrayInterface
from .dictionary import DictInterface
@@ -170,19 +170,23 @@ class Dataset(Element):
_vdim_reductions = {}
_kdim_reductions = {}
- def __init__(self, data, **kwargs):
+ def __init__(self, data, kdims=None, vdims=None, **kwargs):
if isinstance(data, Element):
pvals = util.get_param_values(data)
kwargs.update([(l, pvals[l]) for l in ['group', 'label']
if l in pvals and l not in kwargs])
- kdims, vdims = None, None
- if 'kdims' in kwargs:
- kdims = [kd if isinstance(kd, Dimension) else Dimension(kd)
- for kd in kwargs['kdims']]
- if 'vdims' in kwargs:
- vdims = [kd if isinstance(kd, Dimension) else Dimension(kd)
- for kd in kwargs['vdims']]
+ for group, dims in [('kdims', kdims), ('vdims', vdims)]:
+ if dims is None:
+ continue
+ elif isinstance(dims, (tuple, basestring, Dimension)):
+ dims = [dims]
+ elif not isinstance(dims, list):
+ raise ValueError("%s must be a Dimension or list of dimensions, "
+ "specified as tuples, string or Dimension instances.")
+ kwargs[group] = [d if isinstance(d, Dimension) else Dimension(d)
+ for d in dims]
+ kdims, vdims = kwargs.get('kdims'), kwargs.get('vdims')
initialized = Interface.initialize(type(self), data, kdims, vdims,
datatype=kwargs.get('datatype'))
diff --git a/holoviews/core/dimension.py b/holoviews/core/dimension.py
index 43223f6841..06ccb45203 100644
--- a/holoviews/core/dimension.py
+++ b/holoviews/core/dimension.py
@@ -783,35 +783,20 @@ class to be associated with dimensions. The contents associated
_dim_aliases = dict(key_dimensions='kdims', value_dimensions='vdims',
constant_dimensions='cdims', deep_dimensions='ddims')
-
- # Long-name aliases
-
- @property
- def key_dimensions(self): return self.kdims
-
- @property
- def value_dimensions(self): return self.vdims
-
- @property
- def constant_dimensions(self): return self.cdims
-
- @property
- def deep_dimensions(self): return self.ddims
-
- def __init__(self, data, **params):
- for group in self._dim_groups+list(self._dim_aliases.keys()):
- if group in ['deep_dimensions', 'ddims']: continue
- if group in params:
- if group in self._dim_aliases:
- params[self._dim_aliases[group]] = params.pop(group)
- group = self._dim_aliases[group]
- if group == 'cdims':
- dimensions = {d if isinstance(d, Dimension) else Dimension(d): val
- for d, val in params.pop(group).items()}
- else:
- dimensions = [d if isinstance(d, Dimension) else Dimension(d)
- for d in params.pop(group)]
- params[group] = dimensions
+ def __init__(self, data, kdims=None, vdims=None, **params):
+ for group, dims in [('kdims', kdims), ('vdims', vdims)]:
+ if dims is None:
+ continue
+ elif isinstance(dims, (tuple, basestring, Dimension)):
+ dims = [dims]
+ elif not isinstance(dims, list):
+ raise ValueError("%s must be a Dimension or list of dimensions, "
+ "specified as tuples, string or Dimension instances.")
+ params[group] = [d if isinstance(d, Dimension) else Dimension(d)
+ for d in dims]
+ if 'cdims' in params:
+ params['cdims'] = {d if isinstance(d, Dimension) else Dimension(d): val
+ for d, val in params['cdims'].items()}
super(Dimensioned, self).__init__(data, **params)
self.ndims = len(self.kdims)
cdims = [(d.name, val) for d, val in self.cdims.items()]
diff --git a/holoviews/core/element.py b/holoviews/core/element.py
index 211027e25c..b613619df5 100644
--- a/holoviews/core/element.py
+++ b/holoviews/core/element.py
@@ -390,7 +390,7 @@ def _add_dimensions(self, item, dims, constant_keys):
elif isinstance(item, self._nest_order[self.merge_type]):
if len(dim_vals):
dimensions, key = zip(*dim_vals)
- new_item = self.merge_type({key: item}, kdims=dimensions,
+ new_item = self.merge_type({key: item}, kdims=list(dimensions),
cdims=constant_keys)
else:
new_item = item
diff --git a/holoviews/core/layout.py b/holoviews/core/layout.py
index 7afa715780..d9271adebb 100644
--- a/holoviews/core/layout.py
+++ b/holoviews/core/layout.py
@@ -280,10 +280,11 @@ class NdLayout(UniformNdMapping):
data_type = (ViewableElement, AdjointLayout, UniformNdMapping)
- def __init__(self, initial_items=None, **params):
+ def __init__(self, initial_items=None, kdims=None, **params):
self._max_cols = 4
self._style = None
- super(NdLayout, self).__init__(initial_items=initial_items, **params)
+ super(NdLayout, self).__init__(initial_items=initial_items, kdims=kdims,
+ **params)
@property
diff --git a/holoviews/core/ndmapping.py b/holoviews/core/ndmapping.py
index 7365f84d5a..1d0e579d06 100644
--- a/holoviews/core/ndmapping.py
+++ b/holoviews/core/ndmapping.py
@@ -95,11 +95,13 @@ class MultiDimensionalMapping(Dimensioned):
_deep_indexable = False
_check_items = True
- def __init__(self, initial_items=None, **params):
+ def __init__(self, initial_items=None, kdims=None, **params):
if isinstance(initial_items, MultiDimensionalMapping):
params = dict(util.get_param_values(initial_items),
**dict({'sort': self.sort}, **params))
- super(MultiDimensionalMapping, self).__init__(OrderedDict(), **params)
+ if kdims is not None:
+ params['kdims'] = kdims
+ super(MultiDimensionalMapping, self).__init__(OrderedDict(), **dict(params))
if type(initial_items) is dict and not self.sort:
raise ValueError('If sort=False the data must define a fixed '
'ordering, please supply a list of items or '
@@ -733,11 +735,11 @@ class UniformNdMapping(NdMapping):
_deep_indexable = True
_auxiliary_component = False
- def __init__(self, initial_items=None, group=None, label=None, **params):
+ def __init__(self, initial_items=None, kdims=None, group=None, label=None, **params):
self._type = None
self._group_check, self.group = None, group
self._label_check, self.label = None, label
- super(UniformNdMapping, self).__init__(initial_items, **params)
+ super(UniformNdMapping, self).__init__(initial_items, kdims=kdims, **params)
def clone(self, data=None, shared_data=True, new_type=None, *args, **overrides):
diff --git a/holoviews/core/overlay.py b/holoviews/core/overlay.py
index b99ba1357a..b1853f2a56 100644
--- a/holoviews/core/overlay.py
+++ b/holoviews/core/overlay.py
@@ -245,8 +245,8 @@ class NdOverlay(UniformNdMapping, CompositeOverlay, Overlayable):
_deep_indexable = True
- def __init__(self, overlays=None, **params):
- super(NdOverlay, self).__init__(overlays, **params)
+ def __init__(self, overlays=None, kdims=None, **params):
+ super(NdOverlay, self).__init__(overlays, kdims=kdims, **params)
__all__ = list(set([_k for _k, _v in locals().items()
diff --git a/holoviews/core/spaces.py b/holoviews/core/spaces.py
index bbd1e43b7e..3f0cf59c6d 100644
--- a/holoviews/core/spaces.py
+++ b/holoviews/core/spaces.py
@@ -1341,8 +1341,8 @@ class GridSpace(UniformNdMapping):
kdims = param.List(default=[Dimension("X"), Dimension("Y")], bounds=(1,2))
- def __init__(self, initial_items=None, **params):
- super(GridSpace, self).__init__(initial_items, **params)
+ def __init__(self, initial_items=None, kdims=None, **params):
+ super(GridSpace, self).__init__(initial_items, kdims=kdims, **params)
if self.ndims > 2:
raise Exception('Grids can have no more than two dimensions.')
diff --git a/holoviews/element/chart.py b/holoviews/element/chart.py
index 893c8692fe..f8e082cf36 100644
--- a/holoviews/element/chart.py
+++ b/holoviews/element/chart.py
@@ -165,6 +165,10 @@ class Histogram(Element2D):
vdims = param.List(default=[Dimension('Frequency')], bounds=(1,1))
def __init__(self, values, edges=None, **params):
+ if edges is not None:
+ self.warning("Histogram edges should be supplied as a tuple "
+ "along with the values, passing the edges will "
+ "be deprecated in holoviews 2.0.")
self.values, self.edges, settings = self._process_data(values, edges)
settings.update(params)
super(Histogram, self).__init__((self.values, self.edges), **settings)
@@ -340,10 +344,10 @@ class VectorField(Points):
_null_value = np.array([[], [], [], []]).T # For when data is None
_min_dims = 3 # Minimum number of columns
- def __init__(self, data, **params):
+ def __init__(self, data, kdims=None, vdims=None, **params):
if isinstance(data, list) and all(isinstance(d, np.ndarray) for d in data):
data = np.column_stack([d.flat if d.ndim > 1 else d for d in data])
- super(VectorField, self).__init__(data, **params)
+ super(VectorField, self).__init__(data, kdims=kdims, vdims=vdims, **params)
diff --git a/holoviews/element/chart3d.py b/holoviews/element/chart3d.py
index 243203ead1..dd938c89a0 100644
--- a/holoviews/element/chart3d.py
+++ b/holoviews/element/chart3d.py
@@ -27,9 +27,9 @@ class Surface(Image, Element3D):
group = param.String(default='Surface', constant=True)
- def __init__(self, data, extents=None, **params):
+ def __init__(self, data, kdims=None, vdims=None, extents=None, **params):
extents = extents if extents else (None, None, None, None, None, None)
- Image.__init__(self, data, extents=extents, **params)
+ Image.__init__(self, data, kdims=kdims, vdims=vdims, extents=extents, **params)
diff --git a/holoviews/element/graphs.py b/holoviews/element/graphs.py
index f7a4bce81a..ab31ddb7e0 100644
--- a/holoviews/element/graphs.py
+++ b/holoviews/element/graphs.py
@@ -101,7 +101,7 @@ class Graph(Dataset, Element2D):
kdims = param.List(default=[Dimension('start'), Dimension('end')],
bounds=(2, 2))
- def __init__(self, data, **params):
+ def __init__(self, data, kdims=None, vdims=None, **params):
if isinstance(data, tuple):
data = data + (None,)* (3-len(data))
edges, nodes, edgepaths = data
@@ -122,7 +122,7 @@ def __init__(self, data, **params):
edgepaths = EdgePaths(edgepaths)
self._nodes = nodes
self._edgepaths = edgepaths
- super(Graph, self).__init__(edges, **params)
+ super(Graph, self).__init__(edges, kdims=kdims, vdims=vdims, **params)
if self._nodes is None and node_info:
nodes = self.nodes.clone(datatype=['pandas', 'dictionary'])
for d in node_info.dimensions():
diff --git a/holoviews/element/path.py b/holoviews/element/path.py
index 8874eec20b..0dcac6bb78 100644
--- a/holoviews/element/path.py
+++ b/holoviews/element/path.py
@@ -44,7 +44,7 @@ class Path(Dataset, Element2D):
datatype = param.ObjectSelector(default=['multitabular'])
- def __init__(self, data, **params):
+ def __init__(self, data, kdims=None, vdims=None, **params):
if isinstance(data, tuple):
x, y = map(np.asarray, data)
if y.ndim == 1:
@@ -54,7 +54,7 @@ def __init__(self, data, **params):
data = [np.column_stack((x, y[:, i])) for i in range(y.shape[1])]
elif isinstance(data, list) and all(isinstance(path, tuple) for path in data):
data = [np.column_stack(path) for path in data]
- super(Path, self).__init__(data, **params)
+ super(Path, self).__init__(data, kdims=kdims, vdims=vdims, **params)
def __setstate__(self, state):
@@ -127,13 +127,13 @@ class Contours(Path):
_level_vdim = Dimension('Level') # For backward compatibility
- def __init__(self, data, **params):
+ def __init__(self, data, kdims=None, vdims=None, **params):
data = [] if data is None else data
- if 'level' in params:
- vdims = params.get('vdims', [self._level_vdim])
+ if params.get('level') is not None:
+ vdims = vdims or [self._level_vdim]
params['vdims'] = []
super(Contours, self).__init__(data, **params)
- if 'level' in params:
+ if params.get('level') is not None:
self.vdims = [d if isinstance(d, Dimension) else Dimension(d)
for d in vdims]
diff --git a/holoviews/element/raster.py b/holoviews/element/raster.py
index 2af09c38a6..57ffe1bb52 100644
--- a/holoviews/element/raster.py
+++ b/holoviews/element/raster.py
@@ -227,10 +227,11 @@ class Image(Dataset, Raster, SheetCoordinateSystem):
bounds=(1, 1), doc="""
The dimension description of the data held in the matrix.""")
- def __init__(self, data, bounds=None, extents=None, xdensity=None, ydensity=None, **params):
+ def __init__(self, data, kdims=None, vdims=None, bounds=None, extents=None,
+ xdensity=None, ydensity=None, **params):
extents = extents if extents else (None, None, None, None)
if data is None: data = np.array([[0]])
- Dataset.__init__(self, data, extents=extents, **params)
+ Dataset.__init__(self, data, kdims=kdims, vdims=vdims, extents=extents, **params)
dim2, dim1 = self.interface.shape(self, gridded=True)[:2]
if bounds is None:
@@ -525,7 +526,7 @@ def load_image(cls, filename, height=1, array=False, bounds=None, bare=False, **
return rgb
- def __init__(self, data, **params):
+ def __init__(self, data, kdims=None, vdims=None, **params):
if isinstance(data, Overlay):
images = data.values()
if not all(isinstance(im, Image) for im in images):
@@ -538,12 +539,12 @@ def __init__(self, data, **params):
raise ValueError("Ranges must be defined on all the value dimensions of all the Images")
arrays = [(im.data - r[0]) / (r[1] - r[0]) for r,im in zip(ranges, images)]
data = np.dstack(arrays)
- vdims = list(params.get('vdims', self.vdims))
+ vdims = list(vdims or self.vdims)
if isinstance(data, np.ndarray):
if data.shape[-1] == 4 and len(vdims) == 3:
vdims.append(self.alpha_dimension)
params['vdims'] = vdims
- super(RGB, self).__init__(data, **params)
+ super(RGB, self).__init__(data, kdims=kdims, vdims=vdims, **params)
@@ -610,9 +611,9 @@ class QuadMesh(Raster):
vdims = param.List(default=[Dimension('z')], bounds=(1,1))
- def __init__(self, data, **params):
+ def __init__(self, data, kdims=None, vdims=None, **params):
data = self._process_data(data)
- Element2D.__init__(self, data, **params)
+ Element2D.__init__(self, data, kdims=kdims, vdims=vdims, **params)
self.data = self._validate_data(self.data)
self._grid = self.data[0].ndim == 1
@@ -772,7 +773,7 @@ class HeatMap(Dataset, Element2D):
vdims = param.List(default=[Dimension('z')])
- def __init__(self, data, **params):
+ def __init__(self, data, kdims=kdims, vdims=vdims, **params):
super(HeatMap, self).__init__(data, **params)
self.gridded = categorical_aggregate2d(self)
diff --git a/holoviews/operation/element.py b/holoviews/operation/element.py
index 9b80344c4a..694fb0f24e 100644
--- a/holoviews/operation/element.py
+++ b/holoviews/operation/element.py
@@ -154,10 +154,10 @@ class transform(Operation):
Image to the data in the output Image. By default, acts as
the identity function such that the output matches the input.""")
- def _process(self, matrix, key=None):
- processed = (matrix.data if not self.p.operator
- else self.p.operator(matrix.data))
- return Image(processed, matrix.bounds, group=self.p.group)
+ def _process(self, img, key=None):
+ processed = (img.data if not self.p.operator
+ else self.p.operator(img.data))
+ return img.clone(processed, group=self.p.group)
@@ -347,7 +347,7 @@ def _process(self, matrix, key=None):
dx = np.where(np.abs(dx_negatives)
Date: Thu, 5 Oct 2017 15:25:24 +0100
Subject: [PATCH 2/8] Improved dimension exception handling
---
holoviews/core/data/__init__.py | 3 ++-
holoviews/core/dimension.py | 6 +++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/holoviews/core/data/__init__.py b/holoviews/core/data/__init__.py
index 2b93905813..3a0b9b4476 100644
--- a/holoviews/core/data/__init__.py
+++ b/holoviews/core/data/__init__.py
@@ -183,7 +183,8 @@ def __init__(self, data, kdims=None, vdims=None, **kwargs):
dims = [dims]
elif not isinstance(dims, list):
raise ValueError("%s must be a Dimension or list of dimensions, "
- "specified as tuples, string or Dimension instances.")
+ "specified as tuples, string or Dimension instances, "
+ "not %s." % (group, dims))
kwargs[group] = [d if isinstance(d, Dimension) else Dimension(d)
for d in dims]
kdims, vdims = kwargs.get('kdims'), kwargs.get('vdims')
diff --git a/holoviews/core/dimension.py b/holoviews/core/dimension.py
index 06ccb45203..c1e38550d2 100644
--- a/holoviews/core/dimension.py
+++ b/holoviews/core/dimension.py
@@ -301,6 +301,9 @@ def __init__(self, spec, **params):
all_params = dict(existing_params, **params)
if isinstance(spec, tuple):
+ if not all(isinstance(s, basestring) for s in spec) or len(spec) != 2:
+ raise ValueError("Dimensions specified as a tuple must be a tuple "
+ "consisting of the name and label not: %s" % spec)
name, label = spec
all_params['name'] = name
all_params['label'] = label
@@ -791,7 +794,8 @@ def __init__(self, data, kdims=None, vdims=None, **params):
dims = [dims]
elif not isinstance(dims, list):
raise ValueError("%s must be a Dimension or list of dimensions, "
- "specified as tuples, string or Dimension instances.")
+ "specified as tuples, string or Dimension instances, "
+ "not %s." % (group, dims))
params[group] = [d if isinstance(d, Dimension) else Dimension(d)
for d in dims]
if 'cdims' in params:
From 41cb175bae7671eb535ba9079905b7c0460e9d17 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Thu, 5 Oct 2017 16:20:31 +0100
Subject: [PATCH 3/8] Small fixes for Raster, RGB and HeatMap constructors
---
holoviews/element/raster.py | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/holoviews/element/raster.py b/holoviews/element/raster.py
index 57ffe1bb52..2fc476078a 100644
--- a/holoviews/element/raster.py
+++ b/holoviews/element/raster.py
@@ -39,11 +39,11 @@ class Raster(Element2D):
bounds=(1, 1), doc="""
The dimension description of the data held in the matrix.""")
- def __init__(self, data, extents=None, **params):
+ def __init__(self, data, kdims=None, vdims=None, extents=None, **params):
if extents is None:
(d1, d2) = data.shape[:2]
extents = (0, 0, d2, d1)
- super(Raster, self).__init__(data, extents=extents, **params)
+ super(Raster, self).__init__(data, kdims=kdims, vdims=vdims, extents=extents, **params)
def __getitem__(self, slices):
@@ -539,11 +539,13 @@ def __init__(self, data, kdims=None, vdims=None, **params):
raise ValueError("Ranges must be defined on all the value dimensions of all the Images")
arrays = [(im.data - r[0]) / (r[1] - r[0]) for r,im in zip(ranges, images)]
data = np.dstack(arrays)
- vdims = list(vdims or self.vdims)
+ if vdims is None:
+ vdims = list(self.vdims)
+ else:
+ vdims = list(vdims) if isinstance(vdims, list) else [vdims]
if isinstance(data, np.ndarray):
if data.shape[-1] == 4 and len(vdims) == 3:
vdims.append(self.alpha_dimension)
- params['vdims'] = vdims
super(RGB, self).__init__(data, kdims=kdims, vdims=vdims, **params)
@@ -773,8 +775,8 @@ class HeatMap(Dataset, Element2D):
vdims = param.List(default=[Dimension('z')])
- def __init__(self, data, kdims=kdims, vdims=vdims, **params):
- super(HeatMap, self).__init__(data, **params)
+ def __init__(self, data, kdims=None, vdims=None, **params):
+ super(HeatMap, self).__init__(data, kdims=kdims, vdims=vdims, **params)
self.gridded = categorical_aggregate2d(self)
@property
From 13130d298ef01a5fc4c5ffbc7652aef09546a537 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Thu, 5 Oct 2017 16:41:02 +0100
Subject: [PATCH 4/8] Eliminated all references to key_dimensions
---
doc/Tutorials/Columnar_Data.ipynb | 4 ++--
doc/Tutorials/Sampling_Data.ipynb | 4 ++--
examples/topics/simulation/sri_model.ipynb | 12 ++++++------
examples/user_guide/07-Tabular_Datasets.ipynb | 4 ++--
.../09-Indexing_and_Selecting_Data.ipynb | 4 ++--
holoviews/core/layout.py | 14 --------------
6 files changed, 14 insertions(+), 28 deletions(-)
diff --git a/doc/Tutorials/Columnar_Data.ipynb b/doc/Tutorials/Columnar_Data.ipynb
index 1ab556a05c..548ced5c0f 100644
--- a/doc/Tutorials/Columnar_Data.ipynb
+++ b/doc/Tutorials/Columnar_Data.ipynb
@@ -377,7 +377,7 @@
"outputs": [],
"source": [
"obs_hmap = hv.HoloMap({i: hv.Image(np.random.randn(10, 10), bounds=(0,0,3,3))\n",
- " for i in range(3)}, key_dimensions=['Observation'])\n",
+ " for i in range(3)}, kdims=['Observation'])\n",
"obs_hmap"
]
},
@@ -415,7 +415,7 @@
"extents = (0,0,3,3)\n",
"error_hmap = hv.HoloMap({(i, j): hv.Image(j*np.random.randn(3, 3), bounds=extents)\n",
" for i, j in product(range(3), np.linspace(0, 1, 3))},\n",
- " key_dimensions=['Observation', 'noise'])\n",
+ " kdims=['Observation', 'noise'])\n",
"noise_layout = error_hmap.layout('noise')\n",
"noise_layout"
]
diff --git a/doc/Tutorials/Sampling_Data.ipynb b/doc/Tutorials/Sampling_Data.ipynb
index 1de381f0d4..e7b9fbc6b1 100644
--- a/doc/Tutorials/Sampling_Data.ipynb
+++ b/doc/Tutorials/Sampling_Data.ipynb
@@ -322,7 +322,7 @@
"outputs": [],
"source": [
"obs_hmap = hv.HoloMap({i: hv.Image(np.random.randn(10, 10), bounds=extents)\n",
- " for i in range(3)}, key_dimensions=['Observation'])"
+ " for i in range(3)}, kdims=['Observation'])"
]
},
{
@@ -384,7 +384,7 @@
"extents = (0, 0, 2, 10)\n",
"curve = hv.HoloMap({(i) : hv.Curve(zip(xs, np.sin(xs)*i))\n",
" for i in np.linspace(0.5, 1.5, 3)},\n",
- " key_dimensions=['Observation'])\n",
+ " kdims=['Observation'])\n",
"all_samples = curve.table().to.points()\n",
"sampled = curve.sample([0, 2, 4, 6, 8])\n",
"sampling = all_samples * sampled.to.points(extents=extents).opts(style=dict(color='r'))\n",
diff --git a/examples/topics/simulation/sri_model.ipynb b/examples/topics/simulation/sri_model.ipynb
index 7a5d7c82c2..67978f0294 100755
--- a/examples/topics/simulation/sri_model.ipynb
+++ b/examples/topics/simulation/sri_model.ipynb
@@ -226,7 +226,7 @@
" raise Exception(\"Enable visualize option to get compute network visulizations.\")\n",
"\n",
" # Declare HoloMap for network animation and counts array\n",
- " network_hmap = hv.HoloMap(key_dimensions=['Time'])\n",
+ " network_hmap = hv.HoloMap(kdims=['Time'])\n",
" sird = np.zeros((steps, 5))\n",
" \n",
" # Declare dimensions and labels\n",
@@ -247,10 +247,10 @@
" \n",
" path_data = [list(el[()]) for el in paths]\n",
" # Create network path and node Elements\n",
- " network_paths = hv.Path(path_data, key_dimensions=spatial_dims)\n",
+ " network_paths = hv.Path(path_data, kdims=spatial_dims)\n",
" network_nodes = hv.Points(np.hstack([points, state_array]),\n",
- " key_dimensions=spatial_dims,\n",
- " value_dimensions=['State'])\n",
+ " kdims=spatial_dims,\n",
+ " vdims=['State'])\n",
" \n",
" # Create overlay and accumulate in network HoloMap\n",
" network_hmap[i] = (network_paths * network_nodes * nlabel).relabel(group='Network', label='SRI')\n",
@@ -265,7 +265,7 @@
" \n",
" # Animate VLine on top of Curves\n",
" distribution = hv.HoloMap({i: (curves * hv.VLine(i)).relabel(group='Counts', label='SRI')\n",
- " for i in range(steps)}, key_dimensions=['Time'])\n",
+ " for i in range(steps)}, kdims=['Time'])\n",
" \n",
" return network_hmap + distribution"
]
@@ -536,7 +536,7 @@
"outputs": [],
"source": [
"exp2_dims = ['Connections', 'pVaccinated']\n",
- "hmap = hv.HoloMap(key_dimensions=exp2_dims)\n",
+ "hmap = hv.HoloMap(kdims=exp2_dims)\n",
"vacc_rates = np.linspace(0, 1, 21)\n",
"mean_conns = [2**i for i in range(7)]\n",
"for v, c in itertools.product(vacc_rates, mean_conns):\n",
diff --git a/examples/user_guide/07-Tabular_Datasets.ipynb b/examples/user_guide/07-Tabular_Datasets.ipynb
index 3629a6615b..b78237187a 100644
--- a/examples/user_guide/07-Tabular_Datasets.ipynb
+++ b/examples/user_guide/07-Tabular_Datasets.ipynb
@@ -384,7 +384,7 @@
"outputs": [],
"source": [
"obs_hmap = hv.HoloMap({i: hv.Image(np.random.randn(10, 10), bounds=(0,0,3,3))\n",
- " for i in range(3)}, key_dimensions=['Observation'])\n",
+ " for i in range(3)}, kdims=['Observation'])\n",
"obs_hmap"
]
},
@@ -424,7 +424,7 @@
"extents = (0,0,3,3)\n",
"error_hmap = hv.HoloMap({(i, j): hv.Image(j*np.random.randn(3, 3), bounds=extents)\n",
" for i, j in product(range(3), np.linspace(0, 1, 3))},\n",
- " key_dimensions=['Observation', 'noise'])\n",
+ " kdims=['Observation', 'noise'])\n",
"noise_layout = error_hmap.layout('noise')\n",
"noise_layout"
]
diff --git a/examples/user_guide/09-Indexing_and_Selecting_Data.ipynb b/examples/user_guide/09-Indexing_and_Selecting_Data.ipynb
index 06fe2b7c38..2d1ce5f87b 100644
--- a/examples/user_guide/09-Indexing_and_Selecting_Data.ipynb
+++ b/examples/user_guide/09-Indexing_and_Selecting_Data.ipynb
@@ -426,7 +426,7 @@
"outputs": [],
"source": [
"obs_hmap = hv.HoloMap({i: hv.Image(np.random.randn(10, 10), bounds=extents)\n",
- " for i in range(3)}, key_dimensions=['Observation'])"
+ " for i in range(3)}, kdims=['Observation'])"
]
},
{
@@ -490,7 +490,7 @@
"extents = (0, 0, 2, 10)\n",
"curve = hv.HoloMap({(i) : hv.Curve(zip(xs, np.sin(xs)*i))\n",
" for i in np.linspace(0.5, 1.5, 3)},\n",
- " key_dimensions=['Observation'])\n",
+ " kdims=['Observation'])\n",
"all_samples = curve.table().to.points()\n",
"sampled = curve.sample([0, 2, 4, 6, 8])\n",
"sampling = all_samples * sampled.to.points(extents=extents).opts(style=dict(color='r'))\n",
diff --git a/holoviews/core/layout.py b/holoviews/core/layout.py
index d9271adebb..ed3d3d388c 100644
--- a/holoviews/core/layout.py
+++ b/holoviews/core/layout.py
@@ -381,20 +381,6 @@ def __init__(self, items=None, identifier=None, parent=None, **kwargs):
Dimensioned.__init__(self, self.data, **params)
- @classmethod
- def collate(cls, data, kdims=None, key_dimensions=None):
- kdims = key_dimensions if (kdims is None) else kdims
- if kdims is None:
- raise Exception("Please specify the key dimensions.")
-
- collate_deprecation.warning("Layout.collate will be deprecated after version 1.3.0."
- "\nUse HoloMap.collate instead (see HoloViews homepage for example usage)")
- from .element import Collator
- layouts = {k:(v if isinstance(v, Layout) else Layout.from_values([v]))
- for k,v in data.items()}
- return Collator(layouts, kdims=kdims)()
-
-
@classmethod
def from_values(cls, vals):
"""
From c1ba7a2b1dc985cc7063e15f2fb84679d4c4dd7e Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Sun, 8 Oct 2017 17:22:06 +0100
Subject: [PATCH 5/8] Fixed empty MultiInterface constructor
---
holoviews/core/data/multipath.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/holoviews/core/data/multipath.py b/holoviews/core/data/multipath.py
index 0f500c9d67..cbc4a8776e 100644
--- a/holoviews/core/data/multipath.py
+++ b/holoviews/core/data/multipath.py
@@ -26,6 +26,10 @@ class MultiInterface(Interface):
def init(cls, eltype, data, kdims, vdims):
new_data = []
dims = {'kdims': eltype.kdims, 'vdims': eltype.vdims}
+ if kdims is not None:
+ dims['kdims'] = kdims
+ if vdims is not None:
+ dims['vdims'] = vdims
if not isinstance(data, list):
raise ValueError('MultiInterface data must be a list tabular data types.')
prev_interface, prev_dims = None, None
From 0c85b2c526ee72d5d28a825b99c80c4175121ebd Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Sun, 8 Oct 2017 17:22:25 +0100
Subject: [PATCH 6/8] Fix empty VectorField constructor
---
holoviews/element/chart.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/holoviews/element/chart.py b/holoviews/element/chart.py
index f8e082cf36..cbb1e38da1 100644
--- a/holoviews/element/chart.py
+++ b/holoviews/element/chart.py
@@ -345,7 +345,7 @@ class VectorField(Points):
_min_dims = 3 # Minimum number of columns
def __init__(self, data, kdims=None, vdims=None, **params):
- if isinstance(data, list) and all(isinstance(d, np.ndarray) for d in data):
+ if isinstance(data, list) and data and all(isinstance(d, np.ndarray) for d in data):
data = np.column_stack([d.flat if d.ndim > 1 else d for d in data])
super(VectorField, self).__init__(data, kdims=kdims, vdims=vdims, **params)
From 936f000d015867447eb0ab928d8c68da1ad118f5 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Sun, 8 Oct 2017 17:22:51 +0100
Subject: [PATCH 7/8] Fixed Contours dimension initialization
---
holoviews/element/path.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/holoviews/element/path.py b/holoviews/element/path.py
index 0dcac6bb78..a252d31d3c 100644
--- a/holoviews/element/path.py
+++ b/holoviews/element/path.py
@@ -56,7 +56,6 @@ def __init__(self, data, kdims=None, vdims=None, **params):
data = [np.column_stack(path) for path in data]
super(Path, self).__init__(data, kdims=kdims, vdims=vdims, **params)
-
def __setstate__(self, state):
"""
Ensures old-style unpickled Path types without an interface
@@ -132,7 +131,9 @@ def __init__(self, data, kdims=None, vdims=None, **params):
if params.get('level') is not None:
vdims = vdims or [self._level_vdim]
params['vdims'] = []
- super(Contours, self).__init__(data, **params)
+ else:
+ params['vdims'] = vdims
+ super(Contours, self).__init__(data, kdims=kdims, **params)
if params.get('level') is not None:
self.vdims = [d if isinstance(d, Dimension) else Dimension(d)
for d in vdims]
From b97318707b3868dadc1eaaee85381dc6d8dc53e8 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Sun, 8 Oct 2017 17:23:12 +0100
Subject: [PATCH 8/8] Added unit tests for Element constructors signature
---
tests/testelementconstructors.py | 95 +++++++++++++++++++++++++++++++-
1 file changed, 94 insertions(+), 1 deletion(-)
diff --git a/tests/testelementconstructors.py b/tests/testelementconstructors.py
index f3d33b324a..3bbafeb609 100644
--- a/tests/testelementconstructors.py
+++ b/tests/testelementconstructors.py
@@ -1,6 +1,9 @@
import numpy as np
-from holoviews import Dataset, Curve, Path, Histogram, HeatMap
+from holoviews import (Dimension, Dataset, Curve, Path, Histogram,
+ HeatMap, Contours, Scatter, Points, Polygons,
+ VectorField, Spikes, Area, Bars, ErrorBars,
+ BoxWhisker, Raster, Image, QuadMesh, RGB)
from holoviews.element.comparison import ComparisonTestCase
class ElementConstructorTest(ComparisonTestCase):
@@ -82,3 +85,93 @@ def test_heatmap_construct_and_sort(self):
'z': [[np.NaN, 0, 0], [0, np.NaN, 2], [0, 2, np.NaN]]},
kdims=['x', 'y'], vdims=['z'])
self.assertEqual(hmap.gridded, dataset)
+
+
+
+class ElementSignatureTest(ComparisonTestCase):
+ """
+ Test that Element signatures are consistent.
+ """
+
+ def test_curve_string_signature(self):
+ curve = Curve([], 'a', 'b')
+ self.assertEqual(curve.kdims, [Dimension('a')])
+ self.assertEqual(curve.vdims, [Dimension('b')])
+
+ def test_area_string_signature(self):
+ area = Area([], 'a', 'b')
+ self.assertEqual(area.kdims, [Dimension('a')])
+ self.assertEqual(area.vdims, [Dimension('b')])
+
+ def test_errorbars_string_signature(self):
+ errorbars = ErrorBars([], 'a', ['b', 'c'])
+ self.assertEqual(errorbars.kdims, [Dimension('a')])
+ self.assertEqual(errorbars.vdims, [Dimension('b'), Dimension('c')])
+
+ def test_bars_string_signature(self):
+ bars = Bars([], 'a', 'b')
+ self.assertEqual(bars.kdims, [Dimension('a')])
+ self.assertEqual(bars.vdims, [Dimension('b')])
+
+ def test_boxwhisker_string_signature(self):
+ boxwhisker = BoxWhisker([], 'a', 'b')
+ self.assertEqual(boxwhisker.kdims, [Dimension('a')])
+ self.assertEqual(boxwhisker.vdims, [Dimension('b')])
+
+ def test_scatter_string_signature(self):
+ scatter = Scatter([], 'a', 'b')
+ self.assertEqual(scatter.kdims, [Dimension('a')])
+ self.assertEqual(scatter.vdims, [Dimension('b')])
+
+ def test_points_string_signature(self):
+ points = Points([], ['a', 'b'], 'c')
+ self.assertEqual(points.kdims, [Dimension('a'), Dimension('b')])
+ self.assertEqual(points.vdims, [Dimension('c')])
+
+ def test_vectorfield_string_signature(self):
+ vectorfield = VectorField([], ['a', 'b'], ['c', 'd'])
+ self.assertEqual(vectorfield.kdims, [Dimension('a'), Dimension('b')])
+ self.assertEqual(vectorfield.vdims, [Dimension('c'), Dimension('d')])
+
+ def test_path_string_signature(self):
+ path = Path([], ['a', 'b'])
+ self.assertEqual(path.kdims, [Dimension('a'), Dimension('b')])
+
+ def test_spikes_string_signature(self):
+ spikes = Spikes([], 'a')
+ self.assertEqual(spikes.kdims, [Dimension('a')])
+
+ def test_contours_string_signature(self):
+ contours = Contours([], ['a', 'b'])
+ self.assertEqual(contours.kdims, [Dimension('a'), Dimension('b')])
+
+ def test_polygons_string_signature(self):
+ polygons = Polygons([], ['a', 'b'])
+ self.assertEqual(polygons.kdims, [Dimension('a'), Dimension('b')])
+
+ def test_heatmap_string_signature(self):
+ heatmap = HeatMap([], ['a', 'b'], 'c')
+ self.assertEqual(heatmap.kdims, [Dimension('a'), Dimension('b')])
+ self.assertEqual(heatmap.vdims, [Dimension('c')])
+
+ def test_raster_string_signature(self):
+ raster = Raster(np.array([[0]]), ['a', 'b'], 'c')
+ self.assertEqual(raster.kdims, [Dimension('a'), Dimension('b')])
+ self.assertEqual(raster.vdims, [Dimension('c')])
+
+ def test_image_string_signature(self):
+ img = Image(np.array([[0, 1], [0, 1]]), ['a', 'b'], 'c')
+ self.assertEqual(img.kdims, [Dimension('a'), Dimension('b')])
+ self.assertEqual(img.vdims, [Dimension('c')])
+
+ def test_rgb_string_signature(self):
+ img = RGB(np.zeros((2, 2, 3)), ['a', 'b'], ['R', 'G', 'B'])
+ self.assertEqual(img.kdims, [Dimension('a'), Dimension('b')])
+ self.assertEqual(img.vdims, [Dimension('R'), Dimension('G'), Dimension('B')])
+
+ def test_quadmesh_string_signature(self):
+ qmesh = QuadMesh(([0, 1], [0, 1], np.array([[0, 1], [0, 1]])), ['a', 'b'], 'c')
+ self.assertEqual(qmesh.kdims, [Dimension('a'), Dimension('b')])
+ self.assertEqual(qmesh.vdims, [Dimension('c')])
+
+