Prevent Data Overlap Between Two Sliders - Use A Single Slider For Two Quantities
Solution 1:
In some cases it may indeed be desired to have one single Slider which can set some minimum and maximum simultaneously. So instead of having one single value, the slider could have two values and the rectangle inside the slider would be bounded by the two values, instead of starting at the minimum value of the slider.
The following would be solution to such a case. It uses a MinMaxSlider
, i.e. a subclass of the Slider which is adapted to host two values.
Instead of a single input value, it would expect two values,
MinMaxSlider(... , valinit=0.5,valinit2=0.8)
such that the Sliderbar ranges from 0.5 to 0.8. Clicking on the slider would change the value which is closer to the click, making dragging rather easy.
In order to use this slider be aware that the function that the callback via on_changed
now naturally has two arguments.
import six
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
class MinMaxSlider(Slider):
def __init__(self,ax, label, valmin, valmax, **kwargs):
self.valinit2 = kwargs.pop("valinit2", valmax)
self.val2 = self.valinit2
Slider.__init__(self,ax, label, valmin, valmax, **kwargs)
self.poly.xy = np.array([[self.valinit,0],[self.valinit,1],
[self.valinit2,1],[self.valinit2,0]])
self.vline.set_visible(False)
def set_val(self, val):
if np.abs(val-self.val) < np.abs(val-self.val2):
self.val = val
else:
self.val2 = val
self.poly.xy = np.array([[self.val,0],[self.val,1],
[self.val2,1],[self.val2,0]])
self.valtext.set_text(self.valfmt % self.val +"\n"+self.valfmt % self.val2)
if self.drawon:
self.ax.figure.canvas.draw_idle()
if not self.eventson:
return
for cid, func in six.iteritems(self.observers):
func(self.val,self.val2)
import numpy as np
x = np.linspace(0,16,1001)
f = lambda x: np.sin(x)*np.sin(1.7*x+2)*np.sin(0.7*x+0.05)*x
fig,(ax, sliderax) = plt.subplots(nrows=2,gridspec_kw={"height_ratios":[1,0.05]})
fig.subplots_adjust(hspace=0.3)
ax.plot(x,f(x))
slider = MinMaxSlider(sliderax,"slider",x.min(),x.max(),
valinit=x.min(),valinit2=x.max())
def update(mini,maxi):
ax.set_xlim(mini,maxi)
slider.on_changed(update)
update(x.min(),x.max())
plt.show()
Post a Comment for "Prevent Data Overlap Between Two Sliders - Use A Single Slider For Two Quantities"