From b5f9033a59b2d07df00fdd504d55529e9a255fa1 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Mon, 10 Apr 2017 00:08:49 +0100
Subject: [PATCH] Defined Dimension.step and used it for dynamic widgets
---
holoviews/core/dimension.py | 5 +++++
holoviews/plotting/bokeh/widgets.py | 2 ++
holoviews/plotting/widgets/__init__.py | 2 ++
tests/testbokehwidgets.py | 13 +++++++++++++
4 files changed, 22 insertions(+)
diff --git a/holoviews/core/dimension.py b/holoviews/core/dimension.py
index 29a629b5f9..ece24a9ad6 100644
--- a/holoviews/core/dimension.py
+++ b/holoviews/core/dimension.py
@@ -149,6 +149,11 @@ class Dimension(param.Parameterized):
may be an inbuilt constructor (such as int, str, float) or a
custom class object.""")
+ step = param.Number(default=None, doc="""
+ Optional floating point step specifying how frequently the
+ underlying space should be sampled. May be used to define a
+ discrete sampling of over the range.""")
+
unit = param.String(default=None, allow_None=True, doc="""
Optional unit string associated with the Dimension. For
instance, the string 'm' may be used represent units of meters
diff --git a/holoviews/plotting/bokeh/widgets.py b/holoviews/plotting/bokeh/widgets.py
index 39b51658d1..28c94fa18e 100644
--- a/holoviews/plotting/bokeh/widgets.py
+++ b/holoviews/plotting/bokeh/widgets.py
@@ -114,6 +114,8 @@ def create_widget(self, dim, holomap=None, editable=False):
int_type = isinstance(dim.type, type) and issubclass(dim.type, int)
if isinstance(dim_range, int) or int_type:
step = 1
+ elif dim.step is not None:
+ step = dim.step
else:
step = 10**((round(math.log10(dim_range))-3))
if editable:
diff --git a/holoviews/plotting/widgets/__init__.py b/holoviews/plotting/widgets/__init__.py
index f095015f94..9f5ac123b7 100644
--- a/holoviews/plotting/widgets/__init__.py
+++ b/holoviews/plotting/widgets/__init__.py
@@ -302,6 +302,8 @@ def get_widgets(self):
int_type = isinstance(dim.type, type) and issubclass(dim.type, int)
if isinstance(dim_range, int) or int_type:
step = 1
+ elif dim.step is not None:
+ step = dim.step
else:
step = 10**(round(math.log10(dim_range))-3)
init_dim_vals.append(dim_vals[0])
diff --git a/tests/testbokehwidgets.py b/tests/testbokehwidgets.py
index 391c83185b..bc4d993f2a 100644
--- a/tests/testbokehwidgets.py
+++ b/tests/testbokehwidgets.py
@@ -47,6 +47,19 @@ def test_bokeh_server_dynamic_range_float(self):
self.assertEqual(label.value, '3.1')
self.assertIs(mapping, None)
+ def test_bokeh_server_dynamic_range_float_step(self):
+ dim = Dimension('x', range=(3.1, 11.2), step=0.1)
+ widget, label, mapping = BokehServerWidgets.create_widget(dim, editable=True)
+ self.assertIsInstance(widget, Slider)
+ self.assertEqual(widget.value, 3.1)
+ self.assertEqual(widget.start, 3.1)
+ self.assertEqual(widget.end, 11.2)
+ self.assertEqual(widget.step, 0.1)
+ self.assertIsInstance(label, TextInput)
+ self.assertEqual(label.title, dim.pprint_label)
+ self.assertEqual(label.value, '3.1')
+ self.assertIs(mapping, None)
+
def test_bokeh_server_dynamic_range_not_editable(self):
dim = Dimension('x', range=(3.1, 11.2))
widget, label, mapping = BokehServerWidgets.create_widget(dim, editable=False)