New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Datashader operations #894
Changes from 18 commits
dfa037d
c6422b7
e0874c0
ba30243
40f1153
345c413
08ef8e0
d5fc734
b4d3fdf
0488c52
5ce5bab
83acee2
189a231
4dee22f
97381b2
6046f9e
088a1b7
d23d873
ac04550
7b8a92a
10ea44e
d602fde
e151dce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,80 +70,6 @@ def get_overlay_bounds(cls, overlay): | |
raise ValueError("Extents across the overlay are inconsistent") | ||
|
||
|
||
class DynamicOperation(Operation): | ||
""" | ||
Dynamically applies an operation to the elements of a HoloMap | ||
or DynamicMap. Will return a DynamicMap wrapping the original | ||
map object, which will lazily evaluate when a key is requested. | ||
The _process method should be overridden in subclasses to apply | ||
a specific operation, DynamicOperation itself applies a no-op, | ||
making the DynamicOperation baseclass useful for converting | ||
existing HoloMaps to a DynamicMap. | ||
""" | ||
|
||
def __call__(self, map_obj, **params): | ||
self.p = param.ParamOverrides(self, params) | ||
callback = self._dynamic_operation(map_obj) | ||
if isinstance(map_obj, DynamicMap): | ||
return map_obj.clone(callback=callback, shared_data=False) | ||
else: | ||
return self._make_dynamic(map_obj, callback) | ||
|
||
|
||
def _process(self, element): | ||
return element | ||
|
||
|
||
def _dynamic_operation(self, map_obj): | ||
""" | ||
Generate function to dynamically apply the operation. | ||
Wraps an existing HoloMap or DynamicMap. | ||
""" | ||
if not isinstance(map_obj, DynamicMap): | ||
def dynamic_operation(*key): | ||
return self._process(map_obj[key]) | ||
return dynamic_operation | ||
|
||
def dynamic_operation(*key): | ||
key = key[0] if map_obj.mode == 'open' else key | ||
_, el = util.get_dynamic_item(map_obj, map_obj.kdims, key) | ||
return self._process(el) | ||
|
||
return dynamic_operation | ||
|
||
|
||
def _make_dynamic(self, hmap, dynamic_fn): | ||
""" | ||
Accepts a HoloMap and a dynamic callback function creating | ||
an equivalent DynamicMap from the HoloMap. | ||
""" | ||
dim_values = zip(*hmap.data.keys()) | ||
params = util.get_param_values(hmap) | ||
kdims = [d(values=list(set(values))) for d, values in | ||
zip(hmap.kdims, dim_values)] | ||
return DynamicMap(dynamic_fn, **dict(params, kdims=kdims)) | ||
|
||
|
||
|
||
class DynamicFunction(DynamicOperation): | ||
""" | ||
Dynamically applies a function to the Elements in a DynamicMap | ||
or HoloMap. Must supply a HoloMap or DynamicMap type and will | ||
return another DynamicMap type, which will apply the supplied | ||
function with the supplied kwargs whenever a value is requested | ||
from the map. | ||
""" | ||
|
||
function = param.Callable(default=lambda x: x, doc=""" | ||
Function to apply to DynamicMap items dynamically.""") | ||
|
||
kwargs = param.Dict(default={}, doc=""" | ||
Keyword arguments passed to the function.""") | ||
|
||
def _process(self, element): | ||
return self.p.function(element, **self.p.kwargs) | ||
|
||
|
||
|
||
class ElementOperation(Operation): | ||
""" | ||
|
@@ -152,6 +78,12 @@ class ElementOperation(Operation): | |
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 the streams attribute, which can allow dynamic control | ||
over the parameters on the operation. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would have said 'on a streams parameter' instead of 'on the streams attribute'... |
||
""" | ||
|
||
dynamic = param.ObjectSelector(default='default', | ||
|
@@ -171,7 +103,6 @@ class ElementOperation(Operation): | |
first component is a Normalization.ranges list and the second | ||
component is Normalization.keys. """) | ||
|
||
|
||
def _process(self, view, key=None): | ||
""" | ||
Process a single input element and outputs new single element | ||
|
@@ -197,16 +128,19 @@ def __call__(self, element, **params): | |
isinstance(element, DynamicMap)) | ||
or self.p.dynamic is True) | ||
|
||
if isinstance(element, ViewableElement): | ||
processed = self._process(element) | ||
elif isinstance(element, GridSpace): | ||
if isinstance(element, GridSpace): | ||
# Initialize an empty axis layout | ||
grid_data = ((pos, self(cell, **params)) | ||
for pos, cell in element.items()) | ||
processed = GridSpace(grid_data, label=element.label, | ||
kdims=element.kdims) | ||
elif dynamic: | ||
processed = DynamicFunction(element, function=self, kwargs=params) | ||
from ..util import Dynamic | ||
streams = getattr(self, 'streams', []) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feature probably needs mentioning in the docstring wherever |
||
processed = Dynamic(element, streams=streams, | ||
operation=self, kwargs=params) | ||
elif isinstance(element, ViewableElement): | ||
processed = self._process(element) | ||
elif isinstance(element, DynamicMap): | ||
if any((not d.values) for d in element.kdims): | ||
raise ValueError('Applying a non-dynamic operation requires ' | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment would be helpful above this block explaining what the purpose is. Maybe "Extract dimensions from xarray data structure"?