我需要你的帮助。请考虑以下代码,该代码使用pylab
中的IPython
绘制正弦曲线。轴下方的滑块使用户可以交互地调整正弦曲线的频率。
%pylab
# setup figure
fig, ax = subplots(1)
fig.subplots_adjust(left=0.25, bottom=0.25)
# add a slider
axcolor = 'lightgoldenrodyellow'
ax_freq = axes([0.3, 0.13, 0.5, 0.03], axisbg=axcolor)
s_freq = Slider(ax_freq, 'Frequency [Hz]', 0, 100, valinit=a0)
# plot
g = linspace(0, 1, 100)
f0 = 1
sig = sin(2*pi*f0*t)
myline, = ax.plot(sig)
# update plot
def update(value):
f = s_freq.val
new_data = sin(2*pi*f*t)
myline.set_ydata(new_data) # crucial line
fig.canvas.draw_idle()
s_freq.on_changed(update)
除了上述内容外,我还需要将信号绘制为垂直线,范围从t
中的每个点的幅度到x轴。因此,我的第一个想法是在第15行使用vlines
而不是plot
:
myline = ax.vlines(range(len(sig)), 0, sig)
此解决方案适用于非交互式案例。问题是,plot
返回一个matplotlib.lines.Line2D
对象,该对象提供set_ydata
方法以交互方式更新数据。 vlines
返回的对象属于matplotlib.collections.LineCollection
类型,并未提供此类方法。
我的问题:如何以交互方式更新LineCollection
?
答案 0 :(得分:0)
使用@Aaron Voelker
的注释,使用set_segments
并将其包装在函数中:
def update_vlines(*, h, x, ymin=None, ymax=None):
seg_old = h.get_segments()
if ymin is None:
ymin = seg_old[0][0, 1]
if ymax is None:
ymax = seg_old[0][1, 1]
seg_new = [np.array([[xx, ymin],
[xx, ymax]]) for xx in x]
h.set_segments(seg_new)
hlines
的模拟:
def update_hlines(*, h, y, xmin=None, xmax=None):
seg_old = h.get_segments()
if xmin is None:
xmin = seg_old[0][0, 0]
if xmax is None:
xmax = seg_old[0][1, 0]
seg_new = [np.array([[xmin, yy],
[xmax, yy]]) for yy in y]
h.set_segments(seg_new)
答案 1 :(得分:0)
我将在这里举例说明vlines
。
如果您有多行,@scleronomic解决方案将非常有效。您也可能更喜欢单线:
myline.set_segments([np.array([[x, x_min], [x, x_max]]) for x in xx])
如果仅需要更新最大值,则可以执行以下操作:
def update_maxs(vline):
vline[:,1] = x_min, x_max
return vline
myline.set_segments(list(map(update_maxs, x.get_segments())))
此示例也可能有用:LINK