Python 如何在matplotlib中更新绘图?

Python 如何在matplotlib中更新绘图?,python,matplotlib,tkinter,Python,Matplotlib,Tkinter,我在这里重画这个图有问题。我允许用户指定时间刻度(x轴)中的单位,然后重新计算并调用此函数plots()。我希望绘图只是更新,而不是将另一个绘图附加到图中 def plots(): global vlgaBuffSorted cntr() result = collections.defaultdict(list) for d in vlgaBuffSorted: result[d['event']].append(d) result_

我在这里重画这个图有问题。我允许用户指定时间刻度(x轴)中的单位,然后重新计算并调用此函数
plots()
。我希望绘图只是更新,而不是将另一个绘图附加到图中

def plots():
    global vlgaBuffSorted
    cntr()

    result = collections.defaultdict(list)
    for d in vlgaBuffSorted:
        result[d['event']].append(d)

    result_list = result.values()

    f = Figure()
    graph1 = f.add_subplot(211)
    graph2 = f.add_subplot(212,sharex=graph1)

    for item in result_list:
        tL = []
        vgsL = []
        vdsL = []
        isubL = []
        for dict in item:
            tL.append(dict['time'])
            vgsL.append(dict['vgs'])
            vdsL.append(dict['vds'])
            isubL.append(dict['isub'])
        graph1.plot(tL,vdsL,'bo',label='a')
        graph1.plot(tL,vgsL,'rp',label='b')
        graph2.plot(tL,isubL,'b-',label='c')

    plotCanvas = FigureCanvasTkAgg(f, pltFrame)
    toolbar = NavigationToolbar2TkAgg(plotCanvas, pltFrame)
    toolbar.pack(side=BOTTOM)
    plotCanvas.get_tk_widget().pack(side=TOP)

您基本上有两种选择:

  • 执行当前正在执行的操作,但在重新填充数据之前,请调用
    graph1.clear()
    graph2.clear()
    。这是最慢、但最简单、最稳健的选择

  • 您可以只更新打印对象的数据,而不是重新打印。您需要对代码进行一些更改,但这应该比每次都要快得多。但是,正在打印的数据的形状无法更改,如果数据的范围正在更改,则需要手动重置x轴和y轴限制

  • 要给出第二个选项的示例:

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0, 6*np.pi, 100)
    y = np.sin(x)
    
    # You probably won't need this if you're embedding things in a tkinter plot...
    plt.ion()
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma
    
    for phase in np.linspace(0, 10*np.pi, 500):
        line1.set_ydata(np.sin(x + phase))
        fig.canvas.draw()
        fig.canvas.flush_events()
    

    上述所有可能都是正确的,但对我来说,数字的“在线更新”只适用于某些后端,特别是
    wx
    。您可以尝试更改此选项,例如,通过
    ipython--pylab=wx
    启动ipython/pylab!祝你好运

    如果有人看到这篇文章来寻找我想要的东西,我会在

    然后将它们修改为使用imshow和输入帧堆栈,而不是动态生成和使用轮廓


    从一组3D形状图像(nBins、nBins、nBins)开始,称为

    def animate_frames(frames):
        nBins   = frames.shape[0]
        frame   = frames[0]
        tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
        for k in range(nBins):
            frame   = frames[k]
            tempCS1 = plt.imshow(frame, cmap=plt.cm.gray)
            del tempCS1
            fig.canvas.draw()
            #time.sleep(1e-2) #unnecessary, but useful
            fig.clf()
    
    fig = plt.figure()
    ax  = fig.add_subplot(111)
    
    win = fig.canvas.manager.window
    fig.canvas.manager.window.after(100, animate_frames, frames)
    
    我还找到了一种简单得多的方法来完成整个过程,尽管不太可靠:

    fig = plt.figure()
    
    for k in range(nBins):
        plt.clf()
        plt.imshow(frames[k],cmap=plt.cm.gray)
        fig.canvas.draw()
        time.sleep(1e-6) #unnecessary, but useful
    
    请注意,这两种方法似乎只适用于
    ipython--pylab=tk
    ,也称为
    backend=TkAgg


    感谢您提供的一切帮助。

    我发布了一个名为的包,它提供了允许图形更新的功能,通常在for循环中调用,类似于Matlab的
    drawnow

    用法示例:

    from pylab import figure, plot, ion, linspace, arange, sin, pi
    def draw_fig():
        # can be arbitrarily complex; just to draw a figure
        #figure() # don't call!
        plot(t, x)
        #show() # don't call!
    
    N = 1e3
    figure() # call here instead!
    ion()    # enable interactivity
    t = linspace(0, 2*pi, num=N)
    for i in arange(100):
        x = sin(2 * pi * i**2 * t / 100.0)
        drawnow(draw_fig)
    

    该软件包适用于任何matplotlib图形,并提供了在每次图形更新或放入调试器后等待的选项。

    这对我来说很有效。每次重复调用更新图形的函数

    import matplotlib.pyplot as plt
    import matplotlib.animation as anim
    
    def plot_cont(fun, xmax):
        y = []
        fig = plt.figure()
        ax = fig.add_subplot(1,1,1)
    
        def update(i):
            yi = fun()
            y.append(yi)
            x = range(len(y))
            ax.clear()
            ax.plot(x, y)
            print i, ': ', yi
    
        a = anim.FuncAnimation(fig, update, frames=xmax, repeat=False)
        plt.show()
    
    “fun”是一个返回整数的函数。
    FuncAnimation将重复调用“update”,它将多次调用“xmax”。

    您也可以执行以下操作: 这将在for循环的50个循环的绘图上绘制10x1随机矩阵数据

    import matplotlib.pyplot as plt
    import numpy as np
    
    plt.ion()
    for i in range(50):
        y = np.random.random([10,1])
        plt.plot(y)
        plt.draw()
        plt.pause(0.0001)
        plt.clf()
    
    这对我很有用:

    from matplotlib import pyplot as plt
    from IPython.display import clear_output
    import numpy as np
    for i in range(50):
        clear_output(wait=True)
        y = np.random.random([10,1])
        plt.plot(y)
        plt.show()
    

    根据其他答案,我将图形的更新包装在python装饰器中,以将绘图的更新机制与实际绘图分开。这样,更新任何绘图就容易多了

    def plotlive(func):
        plt.ion()
    
        @functools.wraps(func)
        def new_func(*args, **kwargs):
    
            # Clear all axes in the current figure.
            axes = plt.gcf().get_axes()
            for axis in axes:
                axis.cla()
    
            # Call func to plot something
            result = func(*args, **kwargs)
    
            # Draw the plot
            plt.draw()
            plt.pause(0.01)
    
            return result
    
        return new_func 
    
    用法示例 然后你可以像其他装饰师一样使用它

    @plotlive
    def plot_something_live(ax, x, y):
        ax.plot(x, y)
        ax.set_ylim([0, 100])
    
    唯一的限制是必须在循环之前创建地物:

    fig, ax = plt.subplots()
    for i in range(100):
        x = np.arange(100)
        y = np.full([100], fill_value=i)
        plot_something_live(ax, x, y)
    

    我尝试测试“1”。结果是,在我重新输入数据后,在我的GUI中绘制了另一组绘图,因此,在重新计算后,我现在有4个绘图,就像以前一样。@thenickname-您在代码中调用的
    clear
    ?您应该调用
    graph1.clear();graph2.clear()
    for
    循环中,就在调用
    graph1.plot(…)
    之前,
    graph2.plot(…)
    等。for循环创建调用graphx.plot(…)N次,将clear语句放入其中只打印最后一个。实际上,我已经提取了画布代码,并将其与图形代码一起放入主程序循环中,现在我的函数被一个按钮调用。出于某种原因,如果我只调用该函数,则绘图会更新,但如果我按下按钮,则绘图不会更新。这是非常有趣的行为。我想那一定是Tkinter的一个错误。只是一种预感。。。在绘制每个帧后,是否缺少调用
    fig.canvas.draw()
    plt.draw()
    ?(也就是说,每次你想显示一帧时,你都应该有一系列的
    清除
    绘图
    绘制
    )我猜,但我认为这会导致你描述的行为。。。无论如何,祝你好运!是2k14,我无意中实现了这样的目标。。。它按预期工作,但打印窗口正在变为“无响应”。。有什么建议吗?谢谢你的留言,我从来没有使用过交互模式,因为它从来没有使用过我使用的默认后端。使用交互模式比每次想要查看图形时停止执行要好得多!其他答案对我的情况都没有帮助。我正在使用pycharm,问题在于控制台的绘图和交互性。我需要在代码体中添加pylab import*和ion(),以启用交互。现在对我来说,它工作得很顺利。你能举个例子说明如何调用这个函数(特别是如何在函数调用中传递函数)以及fun()函数的样子吗?当然。“fun()”是任何返回整数的函数。您可以将函数作为参数传递给另一个参数,如下所示:“plot\u cont(my\u function,123)”。我在第86行调用plot_cont:注意“a=”是必需的,否则动画将被垃圾收集,代码将无法工作!它是如何同时健壮和不稳定的可能重复?我的意思是健壮,如“与任何matplotlib图形一起工作”中所述,而不稳定,如“周末项目”中所述。我已经更新了我的答案。这似乎没有输出图表。我错过什么了吗?我在Jupyter笔记本中也有
    %matplotlib inline
    。哈哈,当我删除
    plt.clf()
    时为我工作过。哦
    matplotlib
    ,你这个流氓:)但这不是在更新一个绘图!它画了50幅图!你的回答正是我所需要的。谢谢