在 matplotlib 中使用滑块调整参数方程的常数值
Tweaking the constant values of a parametric equation with sliders in matplotlib
到目前为止,我正在尝试绘制这个 parametric equation and use Slider widget from matplotlib to make the plot interactive. I want to be able to tweak the value of the constants a and k and see how the plot changes. I have been able to produce this,但是虽然滑块是交互式的(即我可以更改它们的值),但更改滑块上的值根本不会影响绘图.我不知道我做错了什么。这是我的代码。如果您能为我指明正确的方向或提供任何帮助,我将不胜感激。谢谢
注意:初始值(a_init 和 k_init)是随机的,没有任何意义。不过,我不认为问题出在他们身上。
from matplotlib.widgets import Slider
import numpy as np
import matplotlib.pyplot as plt
a_init = 15
k_init = 25
t = np.linspace(0, 2*np.pi, 100)
x = 2*k_init*np.cos(t)-a_init*np.cos(k_init*t)
y = 2*k_init*np.sin(t)-a_init*np.sin(k_init*t)
fig = plt.figure(figsize=(8,8))
parametric_ax = plt.axes([0.1, 0.2, 0.8, 0.65])
slider_ax = plt.axes([0.1, 0.03, 0.8, 0.05])
slider2_ax = plt.axes([0.1, 0.10, 0.8, 0.05])
plt.axes(parametric_ax)
parametric_plot, = plt.plot(x, y)
a_slider = Slider(slider_ax, 'a', 0, 1000, valinit=a_init)
k_slider = Slider(slider2_ax, 'k', 0, 1000, valinit=k_init)
def update(a, k):
parametric_plot.set_ydata((2*k*np.cos(t)-a*np.cos(t*k)), (2*k*np.sin(t)-a*np.sin(t*k)))
fig.canvas.draw_idle()
a_slider.on_changed(update)
k_slider.on_changed(update)
plt.show()
在滑块更新时调用的函数 update
只接受一个参数(比如 val
,它对应于修改后的滑块的新值)。由于这个回调函数是两个滑块共享的,所以我建议不要在函数体中使用这个val
参数。相反,可以直接检索滑块的当前值。
方法set_ydata
只更新y的数据,因此只需要一个一维数组作为输入。您可以通过 set_data
同时更改 x 和 y 的值,或者通过 set_xdata
和 set_ydata
分别更新它。第一个解决方案需要一个二维数组,因此在这里不是最合适的。
最后这给了我们类似的东西
def update(*val):
a = a_slider.val
k = k_slider.val
parametric_plot.set_ydata(2 * k * np.sin(t) - a * np.sin(t * k))
parametric_plot.set_xdata(2 * k * np.cos(t) - a * np.cos(t * k))
其他细微改进
- 参数方程的定义出现了两次:在
update
函数中和在显示初始化时。可以通过调用一次 update
来避免初始化时的这种冗余。
- 增加样本数量。
- 调整 x 和 y 限制
a_init, k_init = 15, 25
t = np.linspace(0, 2 * np.pi, 10000)
fig = plt.figure(figsize=(8, 8))
## Main axes
ax = plt.axes([0.125, 0.15, 0.775, 0.80])
plt.axis("equal")
parametric_plot, = plt.plot(0, 0, c="royalblue") # do not define x and y
plt.xlim(-200, 200)
plt.ylim(-200, 200)
## Create sliders
ax_slider_a = plt.axes([0.125, 0.03, 0.775, 0.03])
ax_slider_k = plt.axes([0.125, 0.07, 0.775, 0.03])
a_slider = Slider(ax_slider_a, r"$a$", 0, 100, valinit=a_init)
k_slider = Slider(ax_slider_k, r"$k$", 0, 100, valinit=k_init, valstep=1)
def update(*args):
a, k = a_slider.val, k_slider.val
parametric_plot.set_ydata(2 * k * np.sin(t) - a * np.sin(t * k))
parametric_plot.set_xdata(2 * k * np.cos(t) - a * np.cos(t * k))
a_slider.on_changed(update)
k_slider.on_changed(update)
update() # initialize the plot and thus avoid redundancies
plt.show()
到目前为止,我正在尝试绘制这个 parametric equation and use Slider widget from matplotlib to make the plot interactive. I want to be able to tweak the value of the constants a and k and see how the plot changes. I have been able to produce this,但是虽然滑块是交互式的(即我可以更改它们的值),但更改滑块上的值根本不会影响绘图.我不知道我做错了什么。这是我的代码。如果您能为我指明正确的方向或提供任何帮助,我将不胜感激。谢谢
注意:初始值(a_init 和 k_init)是随机的,没有任何意义。不过,我不认为问题出在他们身上。
from matplotlib.widgets import Slider
import numpy as np
import matplotlib.pyplot as plt
a_init = 15
k_init = 25
t = np.linspace(0, 2*np.pi, 100)
x = 2*k_init*np.cos(t)-a_init*np.cos(k_init*t)
y = 2*k_init*np.sin(t)-a_init*np.sin(k_init*t)
fig = plt.figure(figsize=(8,8))
parametric_ax = plt.axes([0.1, 0.2, 0.8, 0.65])
slider_ax = plt.axes([0.1, 0.03, 0.8, 0.05])
slider2_ax = plt.axes([0.1, 0.10, 0.8, 0.05])
plt.axes(parametric_ax)
parametric_plot, = plt.plot(x, y)
a_slider = Slider(slider_ax, 'a', 0, 1000, valinit=a_init)
k_slider = Slider(slider2_ax, 'k', 0, 1000, valinit=k_init)
def update(a, k):
parametric_plot.set_ydata((2*k*np.cos(t)-a*np.cos(t*k)), (2*k*np.sin(t)-a*np.sin(t*k)))
fig.canvas.draw_idle()
a_slider.on_changed(update)
k_slider.on_changed(update)
plt.show()
在滑块更新时调用的函数 update
只接受一个参数(比如 val
,它对应于修改后的滑块的新值)。由于这个回调函数是两个滑块共享的,所以我建议不要在函数体中使用这个val
参数。相反,可以直接检索滑块的当前值。
方法set_ydata
只更新y的数据,因此只需要一个一维数组作为输入。您可以通过 set_data
同时更改 x 和 y 的值,或者通过 set_xdata
和 set_ydata
分别更新它。第一个解决方案需要一个二维数组,因此在这里不是最合适的。
最后这给了我们类似的东西
def update(*val):
a = a_slider.val
k = k_slider.val
parametric_plot.set_ydata(2 * k * np.sin(t) - a * np.sin(t * k))
parametric_plot.set_xdata(2 * k * np.cos(t) - a * np.cos(t * k))
其他细微改进
- 参数方程的定义出现了两次:在
update
函数中和在显示初始化时。可以通过调用一次update
来避免初始化时的这种冗余。 - 增加样本数量。
- 调整 x 和 y 限制
a_init, k_init = 15, 25
t = np.linspace(0, 2 * np.pi, 10000)
fig = plt.figure(figsize=(8, 8))
## Main axes
ax = plt.axes([0.125, 0.15, 0.775, 0.80])
plt.axis("equal")
parametric_plot, = plt.plot(0, 0, c="royalblue") # do not define x and y
plt.xlim(-200, 200)
plt.ylim(-200, 200)
## Create sliders
ax_slider_a = plt.axes([0.125, 0.03, 0.775, 0.03])
ax_slider_k = plt.axes([0.125, 0.07, 0.775, 0.03])
a_slider = Slider(ax_slider_a, r"$a$", 0, 100, valinit=a_init)
k_slider = Slider(ax_slider_k, r"$k$", 0, 100, valinit=k_init, valstep=1)
def update(*args):
a, k = a_slider.val, k_slider.val
parametric_plot.set_ydata(2 * k * np.sin(t) - a * np.sin(t * k))
parametric_plot.set_xdata(2 * k * np.cos(t) - a * np.cos(t * k))
a_slider.on_changed(update)
k_slider.on_changed(update)
update() # initialize the plot and thus avoid redundancies
plt.show()