Matplotlib 中带有 for 循环的滑块

Slider with for loop in Matplotlib

我想求出二次方程 ax^2 + bx + c =0 的两个根,并根据系数 c 绘制它们,同时将 a 保持为可变参数。要更改 a 并查看更改参数后绘图会发生什么情况,我想从 Python 的 Matplotlib 模块为 a 创建一个 Silder

我有以下内容,但是,它似乎不起作用。

# Solve the quadratic equation ax**2 + bx + c = 0

from matplotlib.widgets import Slider  # import the Slider widget
import numpy as np
import matplotlib.pyplot as plt
import cmath


a_min = -2   
a_max = 2 
a_init = -2  


fig = plt.figure(figsize=(8,3))

# Slider layout
slider_ax = plt.axes([0.1, 0.05, 0.8, 0.05])

b = 10

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)

for c in np.linspace(-2, 2, 11):

  print('c=',c,' sol1=',sol1(a_init,b,c),' sol2=',sol2(a_init,b,c))


  # Plot with initial parameter value 
  #plt.axes(func_ax) 
  plt.xlabel('$c$') 
  plt.title('Roots of  $ax^2 + bx + c = 0$')
  plot1, = plt.plot(c, sol1(a_init,b,c), 'r')
  plot2, = plt.plot(c, sol2(a_init,b,c), 'b')

# Create a slider 
a_slider = Slider(slider_ax,      # the axes object containing the slider
                  '$a$',          # the name of the slider parameter
                  a_min,          # minimal value of the parameter
                  a_max,          # maximal value of the parameter
                  valinit=a_init  # initial value of the parameter
                 )

# Update function
def update(a):
    plot1.set_ydata(sol1(a,b,c)) 
    plot2.set_ydata(sol2(a,b,c)) 
    fig.canvas.draw_idle() # redraw the plot

# Execute when parameter gets updated 
a_slider.on_changed(update)

plt.show()

有什么帮助吗?

我对您的代码进行了一些修改以使滑块正常工作:

  • 首先,plot1plot2 是在代码的循环中定义的。这意味着它们在每次迭代时都会被删除并重新创建。相反,计算要绘制的所有变量然后在循环外绘制它们更有意义。这是在 update_sols 函数中执行的。
  • 其次,我更改了滑块的 update 功能。应使用 a_slider.val 访问滑块更新的变量(参见示例 here)。
  • 最后,为了确保您可以看到想要绘制的所有内容,您需要在每次移动滑块时更新绘图的 y 限制。

总体而言,更新后的代码如下所示:

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()

输出如下所示: