From c3d03cf723e6214fcb809527ca1445db11681bde Mon Sep 17 00:00:00 2001 From: jlstevens Date: Mon, 8 May 2017 02:38:49 +0100 Subject: [PATCH 1/3] Removed MapOperation class --- holoviews/__init__.py | 2 +- holoviews/core/operation.py | 30 ------------------------------ holoviews/core/spaces.py | 20 ++++++++------------ holoviews/operation/__init__.py | 4 ++-- 4 files changed, 11 insertions(+), 45 deletions(-) diff --git a/holoviews/__init__.py b/holoviews/__init__.py index 3f8a8ea6e7..475cc977c6 100644 --- a/holoviews/__init__.py +++ b/holoviews/__init__.py @@ -24,7 +24,7 @@ GridSpace, GridMatrix) from .interface import * # noqa (API import) -from .operation import ElementOperation, MapOperation, TreeOperation # noqa (API import) +from .operation import ElementOperation, TreeOperation # noqa (API import) from .element import * # noqa (API import) from .element import __all__ as elements_list from . import util # noqa (API import) diff --git a/holoviews/core/operation.py b/holoviews/core/operation.py index 4ab2118260..7fed0f0423 100644 --- a/holoviews/core/operation.py +++ b/holoviews/core/operation.py @@ -185,36 +185,6 @@ def __init__(self, callable, **kwargs): super(OperationCallable, self).__init__(callable, **kwargs) -class MapOperation(param.ParameterizedFunction): - """ - A MapOperation takes a HoloMap containing elements or overlays and - processes them at the HoloMap level, returning arbitrary new - HoloMap objects as output. Unlike ElementOperation, MapOperations - can compute over all the keys and dimensions of the input map. - """ - - group = param.String(default='MapOperation', doc=""" - The group string to identify the output of the MapOperation. - By default this will match the MapOperation name.""") - - def __call__(self, vmap, **params): - self.p = param.ParamOverrides(self, params) - - if not isinstance(vmap, HoloMap): - raise Exception('MapOperation can only process Maps.') - - return self._process(vmap) - - - def _process(self, view): - """ - Process a single input HoloMap, returning a new HoloMap - instance. - """ - raise NotImplementedError - - - class TreeOperation(Operation): """ A TreeOperation is the most general Operation type; it accepts any diff --git a/holoviews/core/spaces.py b/holoviews/core/spaces.py index 4f84ea30e0..a7ec9d0723 100644 --- a/holoviews/core/spaces.py +++ b/holoviews/core/spaces.py @@ -259,7 +259,6 @@ def collapse(self, dimensions=None, function=None, spreadfn=None, **kwargs): on the HoloMap. Homogenous Elements may be collapsed by supplying a function, inhomogenous elements are merged. """ - from .operation import MapOperation if not dimensions: dimensions = self.kdims if not isinstance(dimensions, list): dimensions = [dimensions] @@ -273,18 +272,15 @@ def collapse(self, dimensions=None, function=None, spreadfn=None, **kwargs): collapsed = groups.clone(shared_data=False) for key, group in groups.items(): - if isinstance(function, MapOperation): - collapsed[key] = function(group, **kwargs) - else: - group_data = [el.data for el in group] - args = (group_data, function, group.last.kdims) - if hasattr(group.last, 'interface'): - col_data = group.type(group.table().aggregate(group.last.kdims, function, spreadfn, **kwargs)) + group_data = [el.data for el in group] + args = (group_data, function, group.last.kdims) + if hasattr(group.last, 'interface'): + col_data = group.type(group.table().aggregate(group.last.kdims, function, spreadfn, **kwargs)) - else: - data = group.type.collapse_data(*args, **kwargs) - col_data = group.last.clone(data) - collapsed[key] = col_data + else: + data = group.type.collapse_data(*args, **kwargs) + col_data = group.last.clone(data) + collapsed[key] = col_data return collapsed if self.ndims > 1 else collapsed.last diff --git a/holoviews/operation/__init__.py b/holoviews/operation/__init__.py index e50de18937..a2c179e9dd 100644 --- a/holoviews/operation/__init__.py +++ b/holoviews/operation/__init__.py @@ -1,4 +1,4 @@ -from ..core.operation import ElementOperation, MapOperation, TreeOperation # noqa (API import) +from ..core.operation import ElementOperation, TreeOperation # noqa (API import) from ..core.options import Compositor from .element import * # noqa (API import) @@ -6,7 +6,7 @@ def public(obj): if not isinstance(obj, type): return False - baseclasses = [ElementOperation, MapOperation, TreeOperation] + baseclasses = [ElementOperation, TreeOperation] return any([issubclass(obj, bc) for bc in baseclasses]) From 616bab895bec8cdad41e451db16fec681d55c5c5 Mon Sep 17 00:00:00 2001 From: jlstevens Date: Mon, 8 May 2017 02:40:08 +0100 Subject: [PATCH 2/3] Merged Operation and ElementOperation and added alias --- holoviews/core/operation.py | 146 ++++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 49 deletions(-) diff --git a/holoviews/core/operation.py b/holoviews/core/operation.py index 7fed0f0423..819fffb795 100644 --- a/holoviews/core/operation.py +++ b/holoviews/core/operation.py @@ -20,7 +20,17 @@ class Operation(param.ParameterizedFunction): """ - Base class for all Operation types. + An ElementOperation process an Element or HoloMap at the level of + individual elements or overlays. If a holomap is passed in as + input, a processed holomap is returned as output where the + individual elements have been transformed accordingly. An + ElementOperation may turn overlays in new elements or vice versa. + + An ElementOperation can be set to be dynamic, which will return a + DynamicMap with a callback that will apply the operation + dynamically. An ElementOperation may also supply a list of Stream + classes on a streams parameter, which can allow dynamic control + over the parameters on the operation. """ group = param.String(default='Operation', doc=""" @@ -28,6 +38,37 @@ class Operation(param.ParameterizedFunction): Operation. By default this should match the operation name.""") + dynamic = param.ObjectSelector(default='default', + objects=['default', True, False], doc=""" + Whether the operation should be applied dynamically when a + specific frame is requested, specified as a Boolean. If set to + 'default' the mode will be determined based on the input type, + i.e. if the data is a DynamicMap it will stay dynamic.""") + + input_ranges = param.ClassSelector(default={}, + class_=(dict, tuple), doc=""" + Ranges to be used for input normalization (if applicable) in a + format appropriate for the Normalization.ranges parameter. + + By default, no normalization is applied. If key-wise + normalization is required, a 2-tuple may be supplied where the + first component is a Normalization.ranges list and the second + component is Normalization.keys. """) + + link_inputs = param.Boolean(default=False, doc=""" + If the operation is dynamic, whether or not linked streams + should be transferred from the operation inputs for backends + that support linked streams. + + For example if an operation is applied to a DynamicMap with an + RangeXY, this switch determines whether the corresponding + visualization should update this stream with range changes + originating from the newly generated axes.""") + + streams = param.List(default=[], doc=""" + List of streams that are applied if dynamic=True, allowing + for dynamic interaction with the plot.""") + @classmethod def search(cls, element, pattern): """ @@ -69,53 +110,6 @@ def get_overlay_bounds(cls, overlay): raise ValueError("Extents across the overlay are inconsistent") - -class ElementOperation(Operation): - """ - An ElementOperation process an Element or HoloMap at the level of - individual elements or overlays. If a holomap is passed in as - input, a processed holomap is returned as output where the - individual elements have been transformed accordingly. An - ElementOperation may turn overlays in new elements or vice versa. - - An ElementOperation can be set to be dynamic, which will return a - DynamicMap with a callback that will apply the operation - dynamically. An ElementOperation may also supply a list of Stream - classes on a streams parameter, which can allow dynamic control - over the parameters on the operation. - """ - - dynamic = param.ObjectSelector(default='default', - objects=['default', True, False], doc=""" - Whether the operation should be applied dynamically when a - specific frame is requested, specified as a Boolean. If set to - 'default' the mode will be determined based on the input type, - i.e. if the data is a DynamicMap it will stay dynamic.""") - - input_ranges = param.ClassSelector(default={}, - class_=(dict, tuple), doc=""" - Ranges to be used for input normalization (if applicable) in a - format appropriate for the Normalization.ranges parameter. - - By default, no normalization is applied. If key-wise - normalization is required, a 2-tuple may be supplied where the - first component is a Normalization.ranges list and the second - component is Normalization.keys. """) - - link_inputs = param.Boolean(default=False, doc=""" - If the operation is dynamic, whether or not linked streams - should be transferred from the operation inputs for backends - that support linked streams. - - For example if an operation is applied to a DynamicMap with an - RangeXY, this switch determines whether the corresponding - visualization should update this stream with range changes - originating from the newly generated axes.""") - - streams = param.List(default=[], doc=""" - List of streams that are applied if dynamic=True, allowing - for dynamic interaction with the plot.""") - def _process(self, view, key=None): """ Process a single input element and outputs new single element @@ -169,6 +163,13 @@ def __call__(self, element, **params): return processed +class ElementOperation(Operation): + + def __init__(self, *args, **kwargs): + self.warning('ElementOperation has been deprecated and renamed to Operation.') + super(ElementOperation, self).__init__(*args, **kwargs) + + class OperationCallable(Callable): """ OperationCallable allows wrapping an ElementOperation and the @@ -185,13 +186,60 @@ def __init__(self, callable, **kwargs): super(OperationCallable, self).__init__(callable, **kwargs) -class TreeOperation(Operation): + +class TreeOperation(param.ParameterizedFunction): """ A TreeOperation is the most general Operation type; it accepts any HoloViews datastructure and outputs a Layout containing one or more elements. """ + group = param.String(default='Operation', doc=""" + The group string used to identify the output of the + Operation. By default this should match the operation name.""") + + + @classmethod + def search(cls, element, pattern): + """ + Helper method that returns a list of elements that match the + given path pattern of form {type}.{group}.{label}. + + The input may be a Layout, an Overlay type or a single + Element. + """ + if isinstance(element, Layout): + return [el for cell in element for el in cls.search(cell, pattern)] + if isinstance(element, (NdOverlay, Overlay)): + return [el for el in element if el.matches(pattern)] + elif isinstance(element, Element): + return [element] if element.matches(pattern) else [] + + + @classmethod + def get_overlay_label(cls, overlay, default_label=''): + """ + Returns a label if all the elements of an overlay agree on a + consistent label, otherwise returns the default label. + """ + if all(el.label==overlay.get(0).label for el in overlay): + return overlay.get(0).label + else: + return default_label + + + @classmethod + def get_overlay_bounds(cls, overlay): + """ + Returns the extents if all the elements of an overlay agree on + a consistent extents, otherwise raises an exception. + """ + if all(el.bounds==overlay.get(0).bounds for el in overlay): + return overlay.get(0).bounds + else: + raise ValueError("Extents across the overlay are inconsistent") + + def process_element(self, element, key, **params): """ The process_element method allows a single element to be From 38cc5572e1d02ac388120dd9e829f904d243b7d0 Mon Sep 17 00:00:00 2001 From: jlstevens Date: Mon, 8 May 2017 02:53:14 +0100 Subject: [PATCH 3/3] Renamed ElementOperation to Operation throughout --- holoviews/__init__.py | 7 ++-- holoviews/core/__init__.py | 2 +- holoviews/core/operation.py | 34 ++++++++++---------- holoviews/core/options.py | 6 ++-- holoviews/element/util.py | 4 +-- holoviews/interface/collector.py | 8 ++--- holoviews/operation/__init__.py | 7 ++-- holoviews/operation/datashader.py | 8 ++--- holoviews/operation/element.py | 48 ++++++++++++++-------------- holoviews/operation/normalization.py | 4 +-- holoviews/operation/timeseries.py | 8 ++--- holoviews/util.py | 8 ++--- tests/testoperation.py | 2 +- 13 files changed, 74 insertions(+), 72 deletions(-) diff --git a/holoviews/__init__.py b/holoviews/__init__.py index 475cc977c6..f921a2c3ee 100644 --- a/holoviews/__init__.py +++ b/holoviews/__init__.py @@ -23,9 +23,10 @@ from .core.spaces import (HoloMap, Callable, DynamicMap, # noqa (API import) GridSpace, GridMatrix) -from .interface import * # noqa (API import) -from .operation import ElementOperation, TreeOperation # noqa (API import) -from .element import * # noqa (API import) +from .interface import * # noqa (API import) +from .operation import Operation, TreeOperation # noqa (API import) +from .operation import ElementOperation # noqa (Deprecated API import) +from .element import * # noqa (API import) from .element import __all__ as elements_list from . import util # noqa (API import) diff --git a/holoviews/core/__init__.py b/holoviews/core/__init__.py index 4dc6c090bb..e7aacdbc18 100644 --- a/holoviews/core/__init__.py +++ b/holoviews/core/__init__.py @@ -33,7 +33,7 @@ def public(obj): if not isinstance(obj, type): return False - baseclasses = [Dimension, Dimensioned, ElementOperation, BoundingBox, + baseclasses = [Dimension, Dimensioned, Operation, BoundingBox, SheetCoordinateSystem, AttrTree] return any([issubclass(obj, bc) for bc in baseclasses]) diff --git a/holoviews/core/operation.py b/holoviews/core/operation.py index 819fffb795..bcdb85e450 100644 --- a/holoviews/core/operation.py +++ b/holoviews/core/operation.py @@ -20,17 +20,17 @@ class Operation(param.ParameterizedFunction): """ - An ElementOperation process an Element or HoloMap at the level of - individual elements or overlays. If a holomap is passed in as - input, a processed holomap is returned as output where the - individual elements have been transformed accordingly. An - ElementOperation may turn overlays in new elements or vice versa. + An Operation process an Element or HoloMap at the level of + individual elements or overlays. If a holomap is passed in as input, + a processed holomap is returned as output where the individual + elements have been transformed accordingly. An Operation may turn + overlays in new elements or vice versa. - An ElementOperation can be set to be dynamic, which will return a + An Operation can be set to be dynamic, which will return a DynamicMap with a callback that will apply the operation - dynamically. An ElementOperation may also supply a list of Stream - classes on a streams parameter, which can allow dynamic control - over the parameters on the operation. + dynamically. An Operation may also supply a list of Stream classes + on a streams parameter, which can allow dynamic control over the + parameters on the operation. """ group = param.String(default='Operation', doc=""" @@ -112,9 +112,9 @@ def get_overlay_bounds(cls, overlay): def _process(self, view, key=None): """ - Process a single input element and outputs new single element - or overlay. If a HoloMap is passed into a ElementOperation, - the individual components are processed sequentially with the + Process a single input element and outputs new single element or + overlay. If a HoloMap is passed into an Operation, the + individual components are processed sequentially with the corresponding key passed as the optional key argument. """ raise NotImplementedError @@ -172,13 +172,13 @@ def __init__(self, *args, **kwargs): class OperationCallable(Callable): """ - OperationCallable allows wrapping an ElementOperation and the - objects it is processing to allow traversing the operations - applied on a DynamicMap. + OperationCallable allows wrapping an Operation and the objects it is + processing to allow traversing the operations applied on a + DynamicMap. """ - operation = param.ClassSelector(class_=ElementOperation, doc=""" - The ElementOperation being wrapped.""") + operation = param.ClassSelector(class_=Operation, doc=""" + The Operation being wrapped into an OperationCallable.""") def __init__(self, callable, **kwargs): if 'operation' not in kwargs: diff --git a/holoviews/core/options.py b/holoviews/core/options.py index 759f3fe1ea..ab0e11ab91 100644 --- a/holoviews/core/options.py +++ b/holoviews/core/options.py @@ -705,8 +705,8 @@ class Compositor(param.Parameterized): A Compositor is a way of specifying an operation to be automatically applied to Overlays that match a specified pattern upon display. - Any ElementOperation that takes an Overlay as input may be used to - define a compositor. + Any Operation that takes an Overlay as input may be used to define a + compositor. For instance, a compositor may be defined to automatically display three overlaid monochrome matrices as an RGB image as long as the @@ -719,7 +719,7 @@ class Compositor(param.Parameterized): 'display'.""") operation = param.Parameter(doc=""" - The ElementOperation to apply when collapsing overlays.""") + The Operation to apply when collapsing overlays.""") pattern = param.String(doc=""" The overlay pattern to be processed. An overlay pattern is a diff --git a/holoviews/element/util.py b/holoviews/element/util.py index f93ea050b0..871b0c3e0c 100644 --- a/holoviews/element/util.py +++ b/holoviews/element/util.py @@ -5,7 +5,7 @@ from ..core import Dataset, OrderedDict from ..core.boundingregion import BoundingBox -from ..core.operation import ElementOperation +from ..core.operation import Operation from ..core.sheetcoords import Slice from ..core.util import (is_nan, sort_topologically, one_to_one, cartesian_product, is_cyclic) @@ -102,7 +102,7 @@ def reduce_fn(x): return np.NaN -class categorical_aggregate2d(ElementOperation): +class categorical_aggregate2d(Operation): """ Generates a gridded Dataset of 2D aggregate arrays indexed by the first two dimensions of the passed Element, turning all remaining diff --git a/holoviews/interface/collector.py b/holoviews/interface/collector.py index 9a1d28b4e9..cd6928261c 100644 --- a/holoviews/interface/collector.py +++ b/holoviews/interface/collector.py @@ -348,8 +348,8 @@ def __str__(self): class Analyze(Collect): """ An Analyze is a type of Collect that updates an Attrtree with - the results of a ElementOperation. Analyze takes a ViewRef object as - input which is resolved to generate input for the ElementOperation. + the results of a Operation. Analyze takes a ViewRef object as + input which is resolved to generate input for the Operation. """ def __init__(self, reference, analysis, *args, **kwargs): @@ -406,7 +406,7 @@ class Collector(AttrTree): The analysis method takes a reference to data on the attrtree (a ViewRef) and passes the resolved output to the given analysisfn - ElementOperation. + Operation. >>> Collector.for_type(str, lambda x: ViewableElement(x, name=x)) >>> Collector.interval_hook = param.Dynamic.time_fn.advance @@ -505,7 +505,7 @@ def collect(self, obj, *args, **kwargs): def analyze(self, reference, analysisfn, *args, **kwargs): """ - Given a ViewRef and the ElementOperation analysisfn, process the + Given a ViewRef and the Operation analysisfn, process the data resolved by the reference with analysisfn at each step. """ task = Analyze(reference, analysisfn, *args, **kwargs) diff --git a/holoviews/operation/__init__.py b/holoviews/operation/__init__.py index a2c179e9dd..8a37473431 100644 --- a/holoviews/operation/__init__.py +++ b/holoviews/operation/__init__.py @@ -1,4 +1,5 @@ -from ..core.operation import ElementOperation, TreeOperation # noqa (API import) +from ..core.operation import Operation, TreeOperation # noqa (API import) +from ..core.operation import ElementOperation # noqa (Deprecated API import) from ..core.options import Compositor from .element import * # noqa (API import) @@ -6,7 +7,7 @@ def public(obj): if not isinstance(obj, type): return False - baseclasses = [ElementOperation, TreeOperation] + baseclasses = [Operation, TreeOperation] return any([issubclass(obj, bc) for bc in baseclasses]) @@ -14,7 +15,7 @@ def public(obj): _current_locals = [el for el in locals().items()] for _k, _v in _current_locals: - if public(_v) and issubclass(_v, ElementOperation): + if public(_v) and issubclass(_v, Operation): Compositor.operations.append(_v) __all__ = _public + ['Compositor'] diff --git a/holoviews/operation/datashader.py b/holoviews/operation/datashader.py index 036039cca5..c19200e7ef 100644 --- a/holoviews/operation/datashader.py +++ b/holoviews/operation/datashader.py @@ -17,7 +17,7 @@ from datashape.dispatch import dispatch from datashape import discover as dsdiscover -from ..core import (ElementOperation, Element, Dimension, NdOverlay, +from ..core import (Operation, Element, Dimension, NdOverlay, CompositeOverlay, Dataset) from ..core.data import PandasInterface, DaskInterface from ..core.util import get_param_values, basestring @@ -58,7 +58,7 @@ def dataset_pipeline(dataset, schema, canvas, glyph, summary): return agg -class aggregate(ElementOperation): +class aggregate(Operation): """ aggregate implements 2D binning for any valid HoloViews Element type using datashader. I.e., this operation turns a HoloViews @@ -234,7 +234,7 @@ def _process(self, element, key=None): -class shade(ElementOperation): +class shade(Operation): """ shade applies a normalization function followed by colormapping to an Image or NdOverlay of Images, returning an RGB Element. @@ -362,7 +362,7 @@ def _process(self, element, key=None): -class dynspread(ElementOperation): +class dynspread(Operation): """ Spreading expands each pixel in an Image based Element a certain number of pixels on all sides according to a given shape, merging diff --git a/holoviews/operation/element.py b/holoviews/operation/element.py index 0ee3ff7890..ab4b5fed33 100644 --- a/holoviews/operation/element.py +++ b/holoviews/operation/element.py @@ -1,5 +1,5 @@ """ -Collection of either extremely generic or simple ElementOperation +Collection of either extremely generic or simple Operation examples. """ @@ -8,7 +8,7 @@ import param from param import _is_number -from ..core import (ElementOperation, NdOverlay, Overlay, GridMatrix, +from ..core import (Operation, NdOverlay, Overlay, GridMatrix, HoloMap, Dataset, Element, Collator) from ..core.data import ArrayInterface, DictInterface from ..core.util import find_minmax, group_sanitizer, label_sanitizer, pd @@ -26,10 +26,10 @@ def identity(x,k): return x -class operation(ElementOperation): +class operation(Operation): """ The most generic operation that wraps any callable into an - ElementOperation. The callable needs to accept an HoloViews + Operation. The callable needs to accept an HoloViews component and a key (that may be ignored) and must return a new HoloViews component. @@ -68,7 +68,7 @@ def _process(self, view, key=None): return retval.relabel(group=self.p.group) -class factory(ElementOperation): +class factory(Operation): """ Simple operation that constructs any element that accepts some other element as input. For instance, RGB and HSV elements can be @@ -85,11 +85,11 @@ def _process(self, view, key=None): return self.p.output_type(view) -class chain(ElementOperation): +class chain(Operation): """ - Defining an ElementOperation chain is an easy way to define a new - ElementOperation from a series of existing ones. The argument is a - list of ElementOperation (or ElementOperation instances) that are + Defining an Operation chain is an easy way to define a new + Operation from a series of existing ones. The argument is a + list of Operation (or Operation instances) that are called in sequence to generate the returned element. chain(operations=[gradient, threshold.instance(level=2)]) @@ -111,8 +111,8 @@ class chain(ElementOperation): The group assigned to the result after having applied the chain.""") - operations = param.List(default=[], class_=ElementOperation, doc=""" - A list of ElementOperations (or ElementOperation instances) + operations = param.List(default=[], class_=Operation, doc=""" + A list of Operations (or Operation instances) that are applied on the input from left to right..""") def _process(self, view, key=None): @@ -124,9 +124,9 @@ def _process(self, view, key=None): return processed.clone(group=self.p.group) -class transform(ElementOperation): +class transform(Operation): """ - Generic ElementOperation to transform an input Image or RGBA + Generic Operation to transform an input Image or RGBA element into an output Image. The transformation is defined by the supplied callable that accepts the data of the input Image (typically a numpy array) and returns the transformed data of the @@ -161,7 +161,7 @@ def _process(self, matrix, key=None): -class image_overlay(ElementOperation): +class image_overlay(Operation): """ Operation to build a overlay of images to a specification from a subset of the required elements. @@ -264,7 +264,7 @@ def _process(self, raster, key=None): -class threshold(ElementOperation): +class threshold(Operation): """ Threshold a given Image whereby all values higher than a given level map to the specified high value and all values lower than @@ -301,7 +301,7 @@ def _process(self, matrix, key=None): -class gradient(ElementOperation): +class gradient(Operation): """ Compute the gradient plot of the supplied Image. @@ -351,7 +351,7 @@ def _process(self, matrix, key=None): -class convolve(ElementOperation): +class convolve(Operation): """ Apply a convolution to an overlay using the top layer as the kernel for convolving the bottom layer. Both Image elements in @@ -395,7 +395,7 @@ def _process(self, overlay, key=None): -class contours(ElementOperation): +class contours(Operation): """ Given a Image with a single channel, annotate it with contour lines for a given set of contour levels. @@ -458,7 +458,7 @@ def _process(self, element, key=None): return contours -class histogram(ElementOperation): +class histogram(Operation): """ Returns a Histogram of the input element data, binned into num_bins over the bin_range (if specified) along the specified @@ -547,7 +547,7 @@ def _process(self, view, key=None): -class decimate(ElementOperation): +class decimate(Operation): """ Decimates any column based Element to a specified number of random rows if the current view defined by the x_range and y_range @@ -614,7 +614,7 @@ def _process(self, element, key=None): return element.map(self._process_layer, Element) -class interpolate_curve(ElementOperation): +class interpolate_curve(Operation): """ Resamples a Curve using the defined interpolation method, e.g. to represent changes in y-values as steps. @@ -668,7 +668,7 @@ def _process(self, element, key=None): return element.map(self._process_layer, Element) -class stack_area(ElementOperation): +class stack_area(Operation): """ Stacks an (Nd)Overlay of Area Elements by offsetting their baseline. """ @@ -682,13 +682,13 @@ def _process(self, areas, key=None): #==================# -class collapse(ElementOperation): +class collapse(Operation): """ Given an overlay of Element types, collapse into single Element object using supplied function. Collapsing aggregates over the key dimensions of each object applying the supplied fn to each group. - This is an example of an ElementOperation that does not involve + This is an example of an Operation that does not involve any Raster types. """ diff --git a/holoviews/operation/normalization.py b/holoviews/operation/normalization.py index 4f5ad1736c..4f4188f089 100644 --- a/holoviews/operation/normalization.py +++ b/holoviews/operation/normalization.py @@ -14,13 +14,13 @@ """ import param -from ..core.operation import ElementOperation +from ..core.operation import Operation from ..element import Raster from ..core import Overlay from ..core.util import match_spec -class Normalization(ElementOperation): +class Normalization(Operation): """ Base class for all normalization operation. diff --git a/holoviews/operation/timeseries.py b/holoviews/operation/timeseries.py index 82bbe19761..c09a16b103 100644 --- a/holoviews/operation/timeseries.py +++ b/holoviews/operation/timeseries.py @@ -2,7 +2,7 @@ import numpy as np import pandas as pd -from ..core import ElementOperation, Element +from ..core import Operation, Element from ..core.data import PandasInterface from ..element import Scatter @@ -29,7 +29,7 @@ def _roll_kwargs(self): 'min_periods': self.p.min_periods} -class rolling(ElementOperation,RollingBase): +class rolling(Operation,RollingBase): """ Applies a function over a rolling window. """ @@ -64,7 +64,7 @@ def _process(self, element, key=None): return element.map(self._process_layer, Element) -class resample(ElementOperation): +class resample(Operation): """ Resamples a timeseries of dates with a frequency and function. """ @@ -93,7 +93,7 @@ def _process(self, element, key=None): return element.map(self._process_layer, Element) -class rolling_outlier_std(ElementOperation,RollingBase): +class rolling_outlier_std(Operation, RollingBase): """ Detect outliers using the standard deviation within a rolling window. diff --git a/holoviews/util.py b/holoviews/util.py index 215ba043cc..5b837ff339 100644 --- a/holoviews/util.py +++ b/holoviews/util.py @@ -3,7 +3,7 @@ import param from .core import DynamicMap, HoloMap, ViewableElement -from .core.operation import ElementOperation +from .core.operation import Operation from .core.util import Aliases # noqa (API import) from .core.operation import OperationCallable from .core.spaces import Callable @@ -70,7 +70,7 @@ def _get_streams(self, map_obj): stream = stream() elif not isinstance(stream, Stream): raise ValueError('Streams must be Stream classes or instances') - if isinstance(self.p.operation, ElementOperation): + if isinstance(self.p.operation, Operation): updates = {k: self.p.operation.p.get(k) for k, v in stream.contents.items() if v is None and k in self.p.operation.p} if updates: @@ -84,7 +84,7 @@ def _get_streams(self, map_obj): def _process(self, element, key=None): - if isinstance(self.p.operation, ElementOperation): + if isinstance(self.p.operation, Operation): kwargs = {k: v for k, v in self.p.kwargs.items() if k in self.p.operation.params()} return self.p.operation.process_element(element, key, **kwargs) @@ -106,7 +106,7 @@ def dynamic_operation(*key, **kwargs): def dynamic_operation(*key, **kwargs): self.p.kwargs.update(kwargs) return self._process(map_obj[key], key) - if isinstance(self.p.operation, ElementOperation): + if isinstance(self.p.operation, Operation): return OperationCallable(dynamic_operation, inputs=[map_obj], link_inputs=self.p.link_inputs, operation=self.p.operation) diff --git a/tests/testoperation.py b/tests/testoperation.py index d4c728808d..b1053b7057 100644 --- a/tests/testoperation.py +++ b/tests/testoperation.py @@ -7,7 +7,7 @@ gradient, contours, histogram, interpolate_curve, stack_area) -class ElementOperationTests(ComparisonTestCase): +class OperationTests(ComparisonTestCase): """ Tests allowable data formats when constructing the basic Element types.