From 82c64c2e8e8e27fe1ce0e245c7b369b24a1cb6f6 Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 11:45:53 -0400 Subject: [PATCH 01/12] Slider kwarg 'valstep' allows restricts slider values to integer multiples of 'valstep' (and valmax, if closedmax is True). --- lib/matplotlib/widgets.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 2c395250b2e5..d61322fe5cd5 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -271,9 +271,9 @@ class Slider(AxesWidget): Call :meth:`on_changed` to connect to the slider event """ - def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f', - closedmin=True, closedmax=True, slidermin=None, - slidermax=None, dragging=True, **kwargs): + def __init__(self, ax, label, valmin, valmax, valstep=None, valinit=0.5, + valfmt='%1.2f', closedmin=True, closedmax=True, + slidermin=None, slidermax=None, dragging=True, **kwargs): """ Parameters ---------- @@ -334,6 +334,7 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f', self.drag_active = False self.valmin = valmin self.valmax = valmax + self.valstep = valstep valinit = self._value_in_bounds(valinit) if valinit is None: valinit = valmin @@ -368,6 +369,8 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f', def _value_in_bounds(self, val): """ Makes sure self.val is with given bounds.""" + if self.valstep: + val = round(val/self.valstep)*self.valstep if val <= self.valmin: if not self.closedmin: return From d9d08b54684f5c104a2c7650b2756aad1408276d Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 11:54:13 -0400 Subject: [PATCH 02/12] Second slider in slider_demo exhibits the valstep feature, which makes the value take on integer multiples of parameter valstep. --- examples/widgets/slider_demo.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/widgets/slider_demo.py b/examples/widgets/slider_demo.py index 3edaaf73eb71..f106ce66dc42 100644 --- a/examples/widgets/slider_demo.py +++ b/examples/widgets/slider_demo.py @@ -13,6 +13,7 @@ t = np.arange(0.0, 1.0, 0.001) a0 = 5 f0 = 3 +delta_f = 5.0 s = a0*np.sin(2*np.pi*f0*t) l, = plt.plot(t, s, lw=2, color='red') plt.axis([0, 1, -10, 10]) @@ -21,7 +22,7 @@ axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor) axamp = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=axcolor) -sfreq = Slider(axfreq, 'Freq', 0.1, 30.0, valinit=f0) +sfreq = Slider(axfreq, 'Freq', 0.1, 30.0, valinit=f0, valstep=delta_f) samp = Slider(axamp, 'Amp', 0.1, 10.0, valinit=a0) From 62066d827fb0308ad6af86d61cfb999726afdf70 Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 12:30:30 -0400 Subject: [PATCH 03/12] Better document the valstep feature. --- lib/matplotlib/widgets.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index d61322fe5cd5..7b8f291eb08c 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -289,6 +289,9 @@ def __init__(self, ax, label, valmin, valmax, valstep=None, valinit=0.5, valmax : float The maximum value of the slider. + valstep : float, optional, default: None + If given, the slider will snap to multiples of `valstep`. + valinit : float, optional, default: 0.5 The slider initial position. From 5b448c710d22d3dad200c71b614f13ef91a8f2da Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 12:35:15 -0400 Subject: [PATCH 04/12] Don't redraw everything if we haven't actually changed the slider's value. --- lib/matplotlib/widgets.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 7b8f291eb08c..4de2c3fd80b2 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -420,6 +420,8 @@ def _update(self, event): self.set_val(val) def set_val(self, val): + if self.val == val: + return xy = self.poly.xy xy[2] = val, 1 xy[3] = val, 0 From 98fbf3c1a04f5266d31cb719304665884f444b69 Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 12:47:22 -0400 Subject: [PATCH 05/12] Moved check for value change from inside set_val to its invocation in _update. --- lib/matplotlib/widgets.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 4de2c3fd80b2..b4a35a2b9932 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -416,12 +416,10 @@ def _update(self, event): event.canvas.release_mouse(self.ax) return val = self._value_in_bounds(event.xdata) - if val is not None: + if (val is not None) and (val != self.val): self.set_val(val) def set_val(self, val): - if self.val == val: - return xy = self.poly.xy xy[2] = val, 1 xy[3] = val, 0 From 794894b5fd7c6709850ff5352f7c8b2d129b0b6c Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 13:26:29 -0400 Subject: [PATCH 06/12] Replace round() with np.round() --- lib/matplotlib/widgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index b4a35a2b9932..f85f7d4037da 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -373,7 +373,7 @@ def __init__(self, ax, label, valmin, valmax, valstep=None, valinit=0.5, def _value_in_bounds(self, val): """ Makes sure self.val is with given bounds.""" if self.valstep: - val = round(val/self.valstep)*self.valstep + val = np.round(val/self.valstep)*self.valstep if val <= self.valmin: if not self.closedmin: return From 1ad3a6b71a2d81d21de4b3cf374a6ec37266184a Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 14:44:57 -0400 Subject: [PATCH 07/12] Moved new argument to avoid changing previous order. --- lib/matplotlib/widgets.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index f85f7d4037da..22872a45d839 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -271,9 +271,9 @@ class Slider(AxesWidget): Call :meth:`on_changed` to connect to the slider event """ - def __init__(self, ax, label, valmin, valmax, valstep=None, valinit=0.5, - valfmt='%1.2f', closedmin=True, closedmax=True, - slidermin=None, slidermax=None, dragging=True, **kwargs): + def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f', + closedmin=True, closedmax=True, slidermin=None, slidermax=None, + dragging=True, valstep=None, **kwargs): """ Parameters ---------- @@ -289,9 +289,6 @@ def __init__(self, ax, label, valmin, valmax, valstep=None, valinit=0.5, valmax : float The maximum value of the slider. - valstep : float, optional, default: None - If given, the slider will snap to multiples of `valstep`. - valinit : float, optional, default: 0.5 The slider initial position. @@ -315,6 +312,9 @@ def __init__(self, ax, label, valmin, valmax, valstep=None, valinit=0.5, dragging : bool, optional, default: True If True the slider can be dragged by the mouse. + valstep : float, optional, default: None + If given, the slider will snap to multiples of `valstep`. + Notes ----- Additional kwargs are passed on to ``self.poly`` which is the @@ -419,6 +419,7 @@ def _update(self, event): if (val is not None) and (val != self.val): self.set_val(val) + def set_val(self, val): xy = self.poly.xy xy[2] = val, 1 From adb20e24df729bff9bc58330a7032e12b100bbcc Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 16:30:50 -0400 Subject: [PATCH 08/12] PEP8 compliance --- lib/matplotlib/widgets.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 22872a45d839..ca6d1fd2fcfc 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -272,8 +272,8 @@ class Slider(AxesWidget): Call :meth:`on_changed` to connect to the slider event """ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f', - closedmin=True, closedmax=True, slidermin=None, slidermax=None, - dragging=True, valstep=None, **kwargs): + closedmin=True, closedmax=True, slidermin=None, + slidermax=None, dragging=True, valstep=None, **kwargs): """ Parameters ---------- @@ -419,7 +419,6 @@ def _update(self, event): if (val is not None) and (val != self.val): self.set_val(val) - def set_val(self, val): xy = self.poly.xy xy[2] = val, 1 From db6adffdb09f28fb0bf6db31deba176482856155 Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 16:31:07 -0400 Subject: [PATCH 09/12] Snap-to values behave more like np.arange now. --- lib/matplotlib/widgets.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index ca6d1fd2fcfc..d133e663a676 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -373,7 +373,9 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f', def _value_in_bounds(self, val): """ Makes sure self.val is with given bounds.""" if self.valstep: - val = np.round(val/self.valstep)*self.valstep + val = np.round((val - self.valmin)/self.valstep)*self.valstep + val += self.valmin + if val <= self.valmin: if not self.closedmin: return From 9e4529876f7b61d3421295d67962024f81bd4a53 Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 16:39:44 -0400 Subject: [PATCH 10/12] Added relevant whats_new --- doc/users/next_whats_new/2017-08-31_discrete-sliders.rst | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 doc/users/next_whats_new/2017-08-31_discrete-sliders.rst diff --git a/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst b/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst new file mode 100644 index 000000000000..50c7227a73ea --- /dev/null +++ b/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst @@ -0,0 +1,8 @@ +Slider UI widget can snap to discrete values +-------------------------- + +The slider UI widget can take the optional argument `valstep`. Doing so +forces the slider to take on only discrete values, starting from `valmin` and +counting up to `valmax` with steps of size `valstep`. + +If `closedmax==True`, then the slider will snap to `valmax` as well. From e23b52284e84822b654fd6ead9014b2265ff0620 Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Thu, 31 Aug 2017 16:42:42 -0400 Subject: [PATCH 11/12] Formatting --- doc/users/next_whats_new/2017-08-31_discrete-sliders.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst b/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst index 50c7227a73ea..24a2488dd3d4 100644 --- a/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst +++ b/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst @@ -1,8 +1,8 @@ Slider UI widget can snap to discrete values -------------------------- -The slider UI widget can take the optional argument `valstep`. Doing so -forces the slider to take on only discrete values, starting from `valmin` and -counting up to `valmax` with steps of size `valstep`. +The slider UI widget can take the optional argument *valstep*. Doing so +forces the slider to take on only discrete values, starting from *valmin* and +counting up to *valmax* with steps of size *valstep*. -If `closedmax==True`, then the slider will snap to `valmax` as well. +If *closedmax==True*, then the slider will snap to *valmax* as well. From 07597b17f479f45ed1640ab07ce2bbda71b58146 Mon Sep 17 00:00:00 2001 From: Joseph Albert Date: Tue, 5 Sep 2017 16:47:28 -0400 Subject: [PATCH 12/12] Formatting fix. --- doc/users/next_whats_new/2017-08-31_discrete-sliders.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst b/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst index 24a2488dd3d4..73a9cddfab26 100644 --- a/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst +++ b/doc/users/next_whats_new/2017-08-31_discrete-sliders.rst @@ -1,5 +1,5 @@ Slider UI widget can snap to discrete values --------------------------- +-------------------------------------------- The slider UI widget can take the optional argument *valstep*. Doing so forces the slider to take on only discrete values, starting from *valmin* and