Skip to content

Commit 79ae33a

Browse files
authored
Create a RangeSlider widget (#18829)
* create RangeSlider widget * Update comments and docstring for RangeSlider + SliderBase * test vertical orientation of RangeSlider Also add a test of the polygon points to make sure that the slider is being rendered correctly.
1 parent 0520035 commit 79ae33a

File tree

4 files changed

+458
-58
lines changed

4 files changed

+458
-58
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
New RangeSlider widget
2+
----------------------
3+
`.widgets.RangeSlider` allows for creating a slider that defines
4+
a range rather than a single value.

examples/widgets/range_slider.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""
2+
======================================
3+
Thresholding an Image with RangeSlider
4+
======================================
5+
6+
Using the RangeSlider widget to control the thresholding of an image.
7+
8+
The RangeSlider widget can be used similarly to the `.widgets.Slider`
9+
widget. The major difference is that RangeSlider's ``val`` attribute
10+
is a tuple of floats ``(lower val, upper val)`` rather than a single float.
11+
"""
12+
13+
import numpy as np
14+
import matplotlib.pyplot as plt
15+
from matplotlib.widgets import RangeSlider
16+
17+
# generate a fake image
18+
np.random.seed(19680801)
19+
N = 128
20+
img = np.random.randn(N, N)
21+
22+
fig, axs = plt.subplots(1, 2, figsize=(10, 5))
23+
plt.subplots_adjust(bottom=0.25)
24+
25+
im = axs[0].imshow(img)
26+
axs[1].hist(img.flatten(), bins='auto')
27+
axs[1].set_title('Histogram of pixel intensities')
28+
29+
# Create the RangeSlider
30+
slider_ax = plt.axes([0.20, 0.1, 0.60, 0.03])
31+
slider = RangeSlider(slider_ax, "Threshold", img.min(), img.max())
32+
33+
# Create the Vertical lines on the histogram
34+
lower_limit_line = axs[1].axvline(slider.val[0], color='k')
35+
upper_limit_line = axs[1].axvline(slider.val[1], color='k')
36+
37+
38+
def update(val):
39+
# The val passed to a callback by the RangeSlider will
40+
# be a tuple of (min, max)
41+
42+
# Update the image's colormap
43+
im.norm.vmin = val[0]
44+
im.norm.vmax = val[1]
45+
46+
# Update the position of the vertical lines
47+
lower_limit_line.set_xdata([val[0], val[0]])
48+
upper_limit_line.set_xdata([val[1], val[1]])
49+
50+
# Redraw the figure to ensure it updates
51+
fig.canvas.draw_idle()
52+
53+
54+
slider.on_changed(update)
55+
plt.show()
56+
57+
#############################################################################
58+
#
59+
# ------------
60+
#
61+
# References
62+
# """"""""""
63+
#
64+
# The use of the following functions, methods, classes and modules is shown
65+
# in this example:
66+
67+
import matplotlib
68+
matplotlib.widgets.RangeSlider

lib/matplotlib/tests/test_widgets.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,33 @@ def test_slider_horizontal_vertical():
298298
assert_allclose(box.bounds, [0, 0, 1, 10/24])
299299

300300

301+
@pytest.mark.parametrize("orientation", ["horizontal", "vertical"])
302+
def test_range_slider(orientation):
303+
if orientation == "vertical":
304+
idx = [1, 0, 3, 2]
305+
else:
306+
idx = [0, 1, 2, 3]
307+
308+
fig, ax = plt.subplots()
309+
310+
slider = widgets.RangeSlider(
311+
ax=ax, label="", valmin=0.0, valmax=1.0, orientation=orientation
312+
)
313+
box = slider.poly.get_extents().transformed(ax.transAxes.inverted())
314+
assert_allclose(box.get_points().flatten()[idx], [0.25, 0, 0.75, 1])
315+
316+
slider.set_val((0.2, 0.6))
317+
assert_allclose(slider.val, (0.2, 0.6))
318+
box = slider.poly.get_extents().transformed(ax.transAxes.inverted())
319+
assert_allclose(box.get_points().flatten()[idx], [0.2, 0, 0.6, 1])
320+
321+
slider.set_val((0.2, 0.1))
322+
assert_allclose(slider.val, (0.1, 0.2))
323+
324+
slider.set_val((-1, 10))
325+
assert_allclose(slider.val, (0, 1))
326+
327+
301328
def check_polygon_selector(event_sequence, expected_result, selections_count):
302329
"""
303330
Helper function to test Polygon Selector.

0 commit comments

Comments
 (0)