Slider with for loop in Matplotlib
I made a couple of modifications to your code to make the slider work:
- First,
plot1
andplot2
are defined in a loop in your code. This means that they are deleted and created again at each iteration. Instead, it makes more sense to compute all the variables you want to plot and then plot them outside the loop. This is performed in theupdate_sols
function. - Second, I changed the
update
function of your slider. The variable updated by the slider should be accessed by usinga_slider.val
(see an example here). - Finally, to make sure that you can see everything that you want to plot, you need to update the y limits of your plot each time you move your slider.
Overall, the updated code looks like that:
from matplotlib.widgets import Slider
import numpy as np
import matplotlib.pyplot as plt
import cmath
#Initial values
a_min = -2
a_max = 2
a_init = -2
b = 10
c_list=np.linspace(-2, 2, 11)
fig, ax = plt.subplots()
plt.subplots_adjust(left=0.25, bottom=0.25)
# Slider layout
slider_ax = plt.axes([0.25, 0.1, 0.65, 0.03])
def sol1(a,b,c):
d = (b**2) - (4*a*c) # Discriminant
return (-b-np.sqrt(d))/(2*a)
def sol2(a,b,c):
d = (b**2) - (4*a*c) # Discriminant
return (-b+np.sqrt(d))/(2*a)
#Function to update solutions after modifying c
def update_sols(a):
res1=[]
res2=[]
for c in c_list:
res1.append(sol1(a,b,c))
res2.append(sol2(a,b,c))
return res1,res2
#Initialising plot with solutions for a_init
sols1,sols2=update_sols(a_init)
plot1,=ax.plot(c_list, sols1, 'r')
plot2,=ax.plot(c_list, sols2, 'b')
ax.set_xlabel('$c$')
ax.set_title('Roots of $ax^2 + bx + c = 0$')
# Create a slider
a_slider = Slider(ax=slider_ax,label='$a$',valmin=a_min,valmax=a_max,valinit=a_init)
# Update function
def update(val):
#updating y data
sols1,sols2=update_sols(a_slider.val)
plot1.set_ydata(sols1)
plot2.set_ydata(sols2)
#updating y limits
sols1_abs=np.abs(sols1)
sols2_abs=np.abs(sols2)
max_ylim=np.amax(np.concatenate((sols1_abs,sols2_abs)))
ax.set_ylim([-1.1*max_ylim,1.1*max_ylim])
fig.canvas.draw_idle() # redraw the plot
# Execute when parameter gets updated
a_slider.on_changed(update)
plt.show()
And the output looks like that: