Skip to content
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

Implemented DynamicMap.map method #1240

Merged
merged 1 commit into from Apr 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions holoviews/core/spaces.py
Expand Up @@ -817,6 +817,22 @@ def _cache(self, key, val):
self.data[key] = val


def map(self, map_fn, specs=None, clone=True):
"""
Recursively replaces elements using a map function when the
specification applies. Extends regular map with functionality
to dynamically apply functions.
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow! That really was a massive simplification. I like it!

I just hope it works as expected and doesn't become complicated again. Perhaps a few more unit tests would help?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added one more test to check the clone=False condition, I generally prefer not adding multiple unit tests that just test end up testing the same code paths and Dimensioned.map is already tested.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. As long as you feel map is tested on sufficiently complex examples somewhere, I don't mind.

deep_mapped = super(DynamicMap, self).map(map_fn, specs, clone)
if isinstance(deep_mapped, type(self)):
from ..util import Dynamic
def apply_map(obj):
return obj.map(map_fn, specs, clone)
dmap = Dynamic(deep_mapped, shared_data=True, operation=apply_map)
return dmap
return deep_mapped


def relabel(self, label=None, group=None, depth=1):
"""
Assign a new label and/or group to an existing LabelledData
Expand Down
26 changes: 25 additions & 1 deletion tests/testdynamic.py
@@ -1,7 +1,7 @@
from collections import deque

import numpy as np
from holoviews import Dimension, NdLayout, GridSpace
from holoviews import Dimension, NdLayout, GridSpace, Layout
from holoviews.core.spaces import DynamicMap, HoloMap, Callable
from holoviews.element import Image, Scatter, Curve, Text
from holoviews.streams import PositionXY, PositionX, PositionY
Expand Down Expand Up @@ -85,6 +85,30 @@ def test_deep_select_slice_kdim_no_match(self):
dmap = DynamicMap(fn, kdims=[Dimension('Test', range=(10, 20))])
self.assertEqual(dmap.select(DynamicMap, x=(5, 10))[10], fn(10))

def test_deep_map_apply_element_function(self):
fn = lambda i: Curve(np.arange(i))
dmap = DynamicMap(fn, kdims=[Dimension('Test', range=(10, 20))])
mapped = dmap.map(lambda x: x.clone(x.data*2), Curve)
curve = fn(10)
self.assertEqual(mapped[10], curve.clone(curve.data*2))

def test_deep_map_apply_dmap_function(self):
fn = lambda i: Curve(np.arange(i))
dmap1 = DynamicMap(fn, kdims=[Dimension('Test', range=(10, 20))])
dmap2 = DynamicMap(fn, kdims=[Dimension('Test', range=(10, 20))])
mapped = (dmap1 + dmap2).map(lambda x: x[10], DynamicMap)
self.assertEqual(mapped, Layout([('DynamicMap.I', fn(10)),
('DynamicMap.II', fn(10))]))

def test_deep_map_apply_dmap_function_no_clone(self):
fn = lambda i: Curve(np.arange(i))
dmap1 = DynamicMap(fn, kdims=[Dimension('Test', range=(10, 20))])
dmap2 = DynamicMap(fn, kdims=[Dimension('Test', range=(10, 20))])
layout = (dmap1 + dmap2)
mapped = layout.map(lambda x: x[10], DynamicMap, clone=False)
self.assertIs(mapped, layout)



class DynamicTestCallableBounded(ComparisonTestCase):

Expand Down