From cb78e087a3259d473edff850205badc5d4268acb Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 4 May 2018 18:38:45 +0100 Subject: [PATCH 1/3] Sort dynamic dimension values in widget constructor --- holoviews/plotting/widgets/__init__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/holoviews/plotting/widgets/__init__.py b/holoviews/plotting/widgets/__init__.py index b313269261..de2e3cdb15 100644 --- a/holoviews/plotting/widgets/__init__.py +++ b/holoviews/plotting/widgets/__init__.py @@ -129,9 +129,14 @@ def __init__(self, plot, renderer=None, **params): self.renderer = renderer # Create mock NdMapping to hold the common dimensions and keys + sorted_dims = [] + for dim in self.dimensions: + if dim.values and all(isnumeric(v) for v in dim.values): + dim = dim.clone(values=sorted(dim.values)) + sorted_dims.append(dim) with item_check(False): - self.mock_obj = NdMapping([(k, None) for k in self.keys], kdims=list(self.dimensions), - sort=False) + self.mock_obj = NdMapping([(k, None) for k in self.keys], + kdims=sorted_dims, sort=False) NdWidget.widgets[self.id] = self @@ -386,7 +391,7 @@ def _get_dynamic_widget(cls, idx, dim): # Widgets currently detect dynamic mode by type # this value representation is now redundant # and should be removed in a refactor - values = sorted(dim.values) + values = dim.values dim_vals = {i: i for i, v in enumerate(values)} widget_type = 'slider' value_labels = escape_list(escape_vals([dim.pprint_value(v) From 5017c82697de6dabf24897f0d3a9a9f57aa5eacc Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Mon, 7 May 2018 12:37:10 +0100 Subject: [PATCH 2/3] Ensure initial DynamicMap key respects default and numeric values sorting --- holoviews/core/spaces.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/holoviews/core/spaces.py b/holoviews/core/spaces.py index 76851297f8..c335c1108d 100644 --- a/holoviews/core/spaces.py +++ b/holoviews/core/spaces.py @@ -807,8 +807,13 @@ def _initial_key(self): for kdim in self.kdims: if str(kdim) in stream_params: key.append(None) + elif kdim.default: + key.append(kdim.default) elif kdim.values: - key.append(kdim.values[0]) + if all(util.isnumeric(v) for v in kdim.values): + key.append(sorted(kdim.values)[0]) + else: + key.append(kdim.values[0]) elif kdim.range[0] is not None: key.append(kdim.range[0]) else: From 28f6c33944bb1e598b334009d81b0ac437a3b12a Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Mon, 7 May 2018 12:55:23 +0100 Subject: [PATCH 3/3] Added unit tests for dynamic plot and widget initialization --- tests/plotting/bokeh/testwidgets.py | 22 ++++++++++++++++++++++ tests/plotting/testplotutils.py | 18 +++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/tests/plotting/bokeh/testwidgets.py b/tests/plotting/bokeh/testwidgets.py index 50e1998164..978b50ee2a 100644 --- a/tests/plotting/bokeh/testwidgets.py +++ b/tests/plotting/bokeh/testwidgets.py @@ -373,3 +373,25 @@ def test_holomap_dropdown_bad_default(self): hmap = HoloMap({chr(65+i): Curve([1, 2, 3]) for i in range(10)}, dim) with self.assertRaises(ValueError): bokeh_renderer.get_widget(hmap, 'widgets').get_widgets() + + def test_dynamicmap_default_value_slider_plot_initialization(self): + dims = [Dimension('N', default=5, range=(0, 10))] + dmap = DynamicMap(lambda N: Curve([1, N, 5]), kdims=dims) + widgets = bokeh_renderer.get_widget(dmap, 'widgets') + widgets.get_widgets() + self.assertEqual(widgets.plot.current_key, (5,)) + + def test_dynamicmap_unsorted_numeric_values_slider_plot_initialization(self): + dims = [Dimension('N', values=[10, 5, 0])] + dmap = DynamicMap(lambda N: Curve([1, N, 5]), kdims=dims) + widgets = bokeh_renderer.get_widget(dmap, 'widgets') + widgets.get_widgets() + self.assertEqual(widgets.plot.current_key, (0,)) + + def test_dynamicmap_unsorted_numeric_values_slider_plot_update(self): + dims = [Dimension('N', values=[10, 5, 0])] + dmap = DynamicMap(lambda N: Curve([1, N, 5]), kdims=dims) + widgets = bokeh_renderer.get_widget(dmap, 'widgets') + widgets.get_widgets() + widgets.update((2,)) + self.assertEqual(widgets.plot.current_key, (10,)) diff --git a/tests/plotting/testplotutils.py b/tests/plotting/testplotutils.py index 02038be4f6..d84e4ad361 100644 --- a/tests/plotting/testplotutils.py +++ b/tests/plotting/testplotutils.py @@ -5,7 +5,7 @@ import numpy as np -from holoviews import NdOverlay, Overlay +from holoviews import NdOverlay, Overlay, Dimension from holoviews.core.spaces import DynamicMap, HoloMap from holoviews.core.options import Store, Cycle from holoviews.element.comparison import ComparisonTestCase @@ -323,6 +323,22 @@ def test_dynamic_compute_overlayable_zorders_three_deep_dynamic_layers_reduced_l self.assertNotIn(curve, sources[2]) +class TestInitializeDynamic(ComparisonTestCase): + + def test_dynamicmap_default_initializes(self): + dims = [Dimension('N', default=5, range=(0, 10))] + dmap = DynamicMap(lambda N: Curve([1, N, 5]), kdims=dims) + initialize_dynamic(dmap) + self.assertEqual(dmap.keys(), [5]) + + def test_dynamicmap_numeric_values_initializes(self): + dims = [Dimension('N', values=[10, 5, 0])] + dmap = DynamicMap(lambda N: Curve([1, N, 5]), kdims=dims) + initialize_dynamic(dmap) + self.assertEqual(dmap.keys(), [0]) + + + class TestSplitDynamicMapOverlay(ComparisonTestCase): """ Tests the split_dmap_overlay utility