From 1e0cd19c4fd51595afaa649f958b756a666bd9db Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Sun, 8 Oct 2017 17:58:44 +0100 Subject: [PATCH] Standardized constructor signature with dimensions as positional args (#1946) --- 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/data/__init__.py | 23 +++-- holoviews/core/data/multipath.py | 4 + holoviews/core/dimension.py | 47 ++++----- holoviews/core/element.py | 2 +- holoviews/core/layout.py | 19 +--- holoviews/core/ndmapping.py | 10 +- holoviews/core/overlay.py | 4 +- holoviews/core/spaces.py | 4 +- holoviews/element/chart.py | 10 +- holoviews/element/chart3d.py | 4 +- holoviews/element/graphs.py | 4 +- holoviews/element/path.py | 17 ++-- holoviews/element/raster.py | 27 +++--- holoviews/operation/element.py | 10 +- holoviews/plotting/widgets/__init__.py | 2 +- tests/testcomparisonraster.py | 10 +- tests/testelementconstructors.py | 95 ++++++++++++++++++- 22 files changed, 204 insertions(+), 116 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/data/__init__.py b/holoviews/core/data/__init__.py index 53f37b8c82..3a0b9b4476 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,24 @@ 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, " + "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') initialized = Interface.initialize(type(self), data, kdims, vdims, datatype=kwargs.get('datatype')) 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 diff --git a/holoviews/core/dimension.py b/holoviews/core/dimension.py index 43223f6841..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 @@ -783,35 +786,21 @@ 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, " + "not %s." % (group, dims)) + 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..ed3d3d388c 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 @@ -380,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): """ 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..cbb1e38da1 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): - if isinstance(data, list) and all(isinstance(d, np.ndarray) for d in data): + def __init__(self, data, kdims=None, vdims=None, **params): + 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, **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..a252d31d3c 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,8 +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 +126,15 @@ 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: + 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] diff --git a/holoviews/element/raster.py b/holoviews/element/raster.py index 2af09c38a6..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): @@ -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,14 @@ 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)) + 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, **params) + super(RGB, self).__init__(data, kdims=kdims, vdims=vdims, **params) @@ -610,9 +613,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,8 +775,8 @@ class HeatMap(Dataset, Element2D): vdims = param.List(default=[Dimension('z')]) - def __init__(self, data, **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 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)