I'm trying to plot this 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 so far, but although sliders are interactive (i.e. I can change the values on them), changing the values on the sliders doesn't affect the plot at all. I couldn't figure out what I'm doing wrong. Here's my code. I would appreciate if you could point me in the right direction or provide any sort of help, really. Thanks.
NB: Initial values (a_init and k_init) are random and have no significance whatsoever. I don't think the problem is with them, though.
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()
The function
updatecalled on a slider update accepts only one argument (sayval, which corresponds to the new value of the modified slider). Since this callback function is shared by two sliders, I suggest not to use thisvalparameter in the body of the function. Instead, the current values of the sliders can be directly retrieved.Method
set_ydataonly updates the data for y, and thus takes only a 1D array as input. Either you change the values of x and y simultaneously viaset_data, or update it separately viaset_xdataandset_ydata. The first solution requires a 2D array and is thus not the most suitable here.Finally that gives us something like
Other slight improvements
updatefunction and at the initialization of the display. This redundancy at initialization can be avoided by callingupdateonce.