Reputation: 715
I have a line generalisation algorithm and want to add a scroll bar to the plot that will increase the tolerance (i,e make the line more and more generalised). Using matplotlib how would this be possible?
So to sum up, I want to be able to click and drag a slider that will display the increase in the tolerances effect on the line.
Still really struggling with this. I only want one slider on a simple scale from 1-10.
yeah the demo helps, i'm just struggerling to get one slider to work, this is what I have so far,
fig = mp.figure()
ax = fig.add_subplot(111)
fig.subplots_adjust(left=0.25, bottom=0.25)
min0=1
max0=10
tolerance = 0
chain1 = ChainLoader('Wiggle1.txt')
chain = chain1[0]
chain2 = chain.generalise(tolerance)
axcolor = 'lightgoldenrodyellow'
axmin = fig.add_axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
axmax = fig.add_axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)
tolerance = Slider(axmin, 'Min', 1, 10, valinit=min0)
#smax = Slider(axmax, 'Max', 0, 30000, valinit=max0)
def update(val):
tolerance = tolerance.val
#pp.show()
tolerance.on_changed(update)
#smax.on_changed(update)
chain2 = chain.generalise(tolerance)
pp.plotPolylines(chain2)
pp.show()
My problems are how to write the def update section. Any help?
from PointPlotter import PointPlotter
from ChainHandler import ChainLoader
pp=PointPlotter()
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
ax = plt.subplot(111)
plt.subplots_adjust(left=0.25, bottom=0.25)
tolerance = 0
f0 = 0
chain2 = ChainLoader('Wiggle1.txt')
for chain in chain2:
chain2 = chain.generalise(tolerance)
pp.plotPolylines(chain2)
axcolor = 'lightgoldenrodyellow'
axtol = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
tolerance = Slider(axtol, 'tol', 0.1, 30.0, valinit=f0)
def update(val):
tolerance = tolerance.val
for chain in chain2:
chain2 = chain.generalise(tolerance)
pp.plotPolylines(chain2)
pp.plotPolylines(chain2)
tolerance.on_changed(update)
plt.show()
So close! Its now plotting, but returns "UnboundLocalError: local variable 'tolerance' referenced before assignment" when the scroll bar is used. @tcaswell any help?
Upvotes: 1
Views: 21281
Reputation: 87376
You want the slider
widget (doc).
Here is the demo from the examples:
http://matplotlib.org/examples/widgets/slider_demo.html
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
ax = plt.subplot(111)
plt.subplots_adjust(left=0.25, bottom=0.25)
t = np.arange(0.0, 1.0, 0.001)
a0 = 5
f0 = 3
s = a0*np.sin(2*np.pi*f0*t)
l, = plt.plot(t,s, lw=2, color='red')
plt.axis([0, 1, -10, 10])
axcolor = 'lightgoldenrodyellow'
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)
samp = Slider(axamp, 'Amp', 0.1, 10.0, valinit=a0)
def update(val):
amp = samp.val
freq = sfreq.val
l.set_ydata(amp*np.sin(2*np.pi*freq*t))
plt.draw()
sfreq.on_changed(update)
samp.on_changed(update)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
def reset(event):
sfreq.reset()
samp.reset()
button.on_clicked(reset)
rax = plt.axes([0.025, 0.5, 0.15, 0.15], facecolor=axcolor)
radio = RadioButtons(rax, ('red', 'blue', 'green'), active=0)
def colorfunc(label):
l.set_color(label)
plt.draw()
radio.on_clicked(colorfunc)
plt.show()
To adapt this to your case:
#smax.on_changed(update)
chain2 = chain.generalise(tol)
pp.plotPolylines(chain2)
def update(val):
tol = tolerance.val # get the value from the slider
chain2 = chain.generalise(tol) # shove that value into your code
ax.cla() # clear the axes
pp.plotPolylines(chain2) # re-plot your new results
# register the call back
tolerance.on_changed(update)
Be careful about re-using variable names (you use tolerance
twice, once for a float
and once for the Slider
and python will happily clobber your old variables with new ones of an entirely different type).
In update
I went with the most brute-force approach, clearing the axes
and then re-drawing it, in general you want to grab the artists that are returned by plotPolylines
and update those with your new data. (If you need help with that step, open a new question with details about your data structure).
The way to understand .on_changed
is that when the slider notices it has been changed, it will call the function you passed in (update
) with a single argument (val
) which is the current value of the slider. Inside that function you can do what ever you want, and it will be executed in full every time the slider is changed.
Upvotes: 4