【问题标题】:Updating pyplot.vlines in interactive plot在交互式绘图中更新 pyplot.vlines
【发布时间】:2015-03-29 16:02:21
【问题描述】:

我需要你的帮助。请考虑下面的代码,它使用pylabIPython 中绘制正弦曲线。轴下方的滑块使用户能够以交互方式调整正弦曲线的频率。

%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

【问题讨论】:

  • 可能是set_offsetsset_verts
  • 我无法让set_offsetset_verts 工作。 set_segments 确实有效,但您必须以 3D 数组的格式提供它,其中每个元素的格式为 [[x, ymin], [x, ymax]]

标签: python-3.x matplotlib python-interactive


【解决方案1】:

使用@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)

【讨论】:

    【解决方案2】:

    我将在此处给出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

    【讨论】:

      猜你喜欢
      • 2018-10-28
      • 2018-04-28
      • 1970-01-01
      • 2020-01-14
      • 2018-10-13
      • 2021-06-16
      • 2012-01-05
      • 2018-07-27
      • 1970-01-01
      相关资源
      最近更新 更多