Reputation: 8052
I've extended following example to use multiple subplots. Here is my code:
#!/usr/bin/python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
########################################
t = np.arange(0.0, 1.0, 0.001)
a0 = 5
f0 = 3
s = a0*np.sin(2*np.pi*f0*t)
########################################
plt.close('all')
fig, ax = plt.subplots(nrows=2, ncols=1)
plt.subplots_adjust(bottom=0.30)
########################################
ax[0].plot(t,s, lw=2, color='red', label="red")
ax[1].plot(t,s, lw=2, color='green', label="green")
########################################
# plt.axis([0, 1, -10, 10])
ax[0].set_xlim([0, 1])
ax[0].set_ylim([-10, 10])
ax[1].set_xlim([0, 1])
ax[1].set_ylim([-10, 10])
########################################
axcolor = 'lightgoldenrodyellow'
f1 = plt.axes([0.25, 0.20, 0.65, 0.03], axisbg=axcolor)
a1 = plt.axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)
f2 = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
a2 = plt.axes([0.25, 0.05, 0.65, 0.03], axisbg=axcolor)
sf1 = Slider(f1, 'Freq1', 0.1, 30.0, valinit=f0)
sa1 = Slider(a1, 'Amp1', 0.1, 10.0, valinit=a0)
sf2 = Slider(f2, 'Freq2', 0.1, 30.0, valinit=f0)
sa2 = Slider(a2, 'Amp2', 0.1, 10.0, valinit=a0)
########################################
def update1(val):
amp = sa1.val
freq = sf1.val
# DOES NOT WORKS - set_ydata DOES NOT EXISTS
# ax[1].set_ydata(amp*np.sin(2*np.pi*freq*t))
# ax[2].set_ydata(amp*np.sin(2*np.pi*freq*t))
# WORKS BUT IT SEEMS SLOW
s = amp*np.sin(2*np.pi*freq*t)
ax[0].clear()
ax[0].plot(t,s, lw=2, color='red', label="red")
ax[0].set_xlim([0, 1])
ax[0].set_ylim([-10, 10])
# THIS HAS NO EFFECT ON SPEED
fig.canvas.draw_idle()
sf1.on_changed(update1)
sa1.on_changed(update1)
def update2(val):
amp = sa2.val
freq = sf2.val
# DOES NOT WORKS - set_ydata DOES NOT EXISTS
# ax[1].set_ydata(amp*np.sin(2*np.pi*freq*t))
# ax[2].set_ydata(amp*np.sin(2*np.pi*freq*t))
# WORKS BUT IT SEEMS SLOW
s = amp*np.sin(2*np.pi*freq*t)
ax[1].clear()
ax[1].plot(t,s, lw=2, color='green', label="green")
ax[1].set_xlim([0, 1])
ax[1].set_ylim([-10, 10])
# THIS HAS NO EFFECT ON SPEED
fig.canvas.draw_idle()
sf2.on_changed(update2)
sa2.on_changed(update2)
plt.show()
The only problem is that it is slower (when the slider is clicked) than the original. I suspect this is caused by bunch of code that is used in update1
and update2
functions. I do not know how to rewrite it more effectively. The original example is using the set_ydata
function but seems that subplots does not have this function. I've been also thinking about one update
function for all four sliders, but I do not know if is it possible to distinguish the object on which the update was triggered and handle it inside the function. Thanks
Upvotes: 0
Views: 952
Reputation: 12711
You try to call set_ydata
on the ax[0]
(or ax[1]
, respectively). This obviously does not work, as these are axes instances. set_ydata
is a method of Line2D
artists. In the example that you have linked a line l
is created in the beginning, which receives the new y data in the update function. You forgot that in your code.
So you need to create the lines:
line0, = ax[0].plot(t,s, lw=2, color='red')
line1, = ax[1].plot(t,s, lw=2, color='green')
in the beginning and then in your update functions you can call:
line0.set_ydata(amp*np.sin(2*np.pi*freq*t))
or
line1.set_ydata(amp*np.sin(2*np.pi*freq*t))
Note: The idea here is to only change the y coordinates of your lines. With your workaround, you deleted the entire graph and recreated it. This is more work and therefore it makes things slower.
Upvotes: 1