如何在matplotlib中更新一个情节?

时间:2021-09-05 04:17:33

I'm having issues with redrawing the figure here. I allow the user to specify the units in the time scale (x-axis) and then I recalculate and call this function plots(). I want the plot to simply update, not append another plot to the figure.

我对重新画这个图有意见。我允许用户在时间尺度(x轴)中指定单位,然后重新计算并调用这个函数图()。我希望这个图只是更新,而不是添加另一个图到这个图中。

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)

7 个解决方案

#1


102  

You essentially have two options:

你基本上有两个选择:

  1. Do exactly what you're currently doing, but call graph1.clear() and graph2.clear() before replotting the data. This is the slowest, but most simplest and most robust option.

    做你目前正在做的事情,但在重新整理数据之前要调用graph1.clear()和graph2.clear()。这是最慢、但最简单、最健壮的选项。

  2. Instead of replotting, you can just update the data of the plot objects. You'll need to make some changes in your code, but this should be much, much faster than replotting things every time. However, the shape of the data that you're plotting can't change, and if the range of your data is changing, you'll need to manually reset the x and y axis limits.

    您可以更新plot对象的数据,而不是重新编写。您需要在代码中进行一些更改,但是这应该比每次都重新进行处理要快得多。但是,您正在绘制的数据的形状不能改变,如果您的数据范围正在改变,您将需要手动重置x轴和y轴的限制。

To give an example of the second option:

举第二个选择的例子:

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()

#2


12  

This worked for me. Repeatedly calls a function updating the graph every time.

这为我工作。每次重复调用一个函数更新图形。

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" is a function that returns an integer. FuncAnimation will repeatedly call "update", it will do that "xmax" times.

“fun”是返回整数的函数。FuncAnimation会反复调用“update”,它会执行“xmax”次数。

#3


8  

In case anyone comes across this article looking for what I was looking for, I found examples at

如果有人看到这篇文章寻找我要找的东西,我可以在上面找到例子

How to visualize scalar 2D data with Matplotlib?

如何用Matplotlib可视化标量2D数据?

and

http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop (on web.archive.org)

http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop(web.archive.org)

then modified them to use imshow with an input stack of frames, instead of generating and using contours on the fly.

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


Starting with a 3D array of images of shape (nBins, nBins, nBins), called frames.

从一组被称为框架的三维图形(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)

I also found a much simpler way to go about this whole process, albeit less robust:

我还发现了一种更简单的方法来处理整个过程,尽管不那么健壮:

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

Note that both of these only seem to work with ipython --pylab=tk, a.k.a.backend = TkAgg

请注意,这两种方法似乎只适用于ipython——pylab=tk, a.k.a。后端= TkAgg

Thank you for the help with everything.

谢谢你对一切的帮助。

#4


5  

I have released a package called python-drawnow that provides functionality to let a figure update, typically called within a for loop, similar to Matlab's drawnow.

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

An example usage:

用法:一个例子

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)

This package works with any matplotlib figure and provides options to wait after each figure update or drop into the debugger.

此包与任何matplotlib图一起工作,并提供了在每个图更新或放入调试器后等待的选项。

#5


3  

All of the above might be true, however for me "online-updating" of figures only works with some backends, specifically wx. You just might try to change to this, e.g. by starting ipython/pylab by ipython --pylab=wx! Good luck!

以上这些可能都是对的,但是对我来说,“在线更新”的数字只提供一些支持,特别是wx。您可以尝试改变一下,例如,通过ipython启动ipython/pylab——pylab=wx!好运!

#6


2  

You can also do like the following: This will draw a 10x1 random matrix data on the plot for 50 cycles of the for loop.

您还可以这样做:这将在图上绘制一个10x1随机矩阵数据,用于for循环的50个周期。

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()

#7


-2  

import csv
import sys
import getopt
import socket
import time
import numpy as np
import matplotlib
from scipy.misc import imread
from matplotlib import pyplot as plt
import warnings
fig, ax = plt.subplots()
ax.set_xlim(-158, 553)
ax.set_ylim(-290, 733)
im = plt.imread("")
plt.imshow(img, zorder=0, extent=[0.5, 8.0, 1.0, 7.0])

fig.show()
l_global=[]
points=[]
master_tag_csvlink='c:/logfolde.log.csv'
csvfile=open(master_tag_csvlink, 'r')
for ainfo in csvfile:
        line= ainfo
        l_list= list(line.split('_'))
        l_local=[]
        for i in range(int(l_list[0])):
            l_local.append(list(l_list[i+1].split(',')))
        function1= lambda x,i: x[i] # return list[n,X] of elements at x
        c= lambda x,l: [x for i in range(l) if True]
        for i in range(len(l_local)):
            l_local[i][1],l_local[i][2]=int(l_local[i][1]),int(l_local[i][2])

        if l_global: #In begining l_glocal is empty, so just copy the data in to l_global
            l_global=l_local[:]
            for i in range(len(l_global)):
                points.append(plt.plot(function1(l_global[i],1),function1(l_global[i],2),'g',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2))))



        else: # compare the l_local & l_global for any updates 
            tag_Id=map(function1,l_local,c(0,len(l_local))) #list of list of tagId,x,y TagId is filtered - local
            mTag_Id=map(fuction1,l_global,c(0,len(l_global))) #list of list of tagId,x,y TagId is filtered - master

            for i in mTag_Id: 
                if i not in tag_Id: #comparing master tags and tag_Id's
                    index=mTag_Id.index(i) ###############  Tags in master list but not in Tag_id
                    copy_point=l_global[index]
                    [removing_point]=points[index]########  means tag is in-active ,turn tag color into red
                    removing_point.remove()
                    del points[index]

                    points.insert(index,plt.plot(function1(l_global[index],1),function1(l_global[index],2),'r',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2))))

                elif i in tag_Id: # append the tag into l_global
                    index=mTag_Id.index(i) ###############  Tags in master list but not in Tag_id
                    l_global[index]=l_local[index][:]
                    [removing_point]=points[index]########  means tag is active update coordinates
                    removing_point.remove()
                    del points[index]
                    points.insert(index,plt.plot(function1(l_global[index],1),function1(l_global[index],2),'g',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2))))
            for i in Tag_Id:
                if i not in mTag_Id:
                    index=Tag_Id(i)
                    l_global.append(l_local[index]]
                    points.append(plt.plot(function1(l_global[-1],1),function1(l_global[-1],2),'g',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2))))

# 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(11)1
# 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()

#1


102  

You essentially have two options:

你基本上有两个选择:

  1. Do exactly what you're currently doing, but call graph1.clear() and graph2.clear() before replotting the data. This is the slowest, but most simplest and most robust option.

    做你目前正在做的事情,但在重新整理数据之前要调用graph1.clear()和graph2.clear()。这是最慢、但最简单、最健壮的选项。

  2. Instead of replotting, you can just update the data of the plot objects. You'll need to make some changes in your code, but this should be much, much faster than replotting things every time. However, the shape of the data that you're plotting can't change, and if the range of your data is changing, you'll need to manually reset the x and y axis limits.

    您可以更新plot对象的数据,而不是重新编写。您需要在代码中进行一些更改,但是这应该比每次都重新进行处理要快得多。但是,您正在绘制的数据的形状不能改变,如果您的数据范围正在改变,您将需要手动重置x轴和y轴的限制。

To give an example of the second option:

举第二个选择的例子:

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()

#2


12  

This worked for me. Repeatedly calls a function updating the graph every time.

这为我工作。每次重复调用一个函数更新图形。

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" is a function that returns an integer. FuncAnimation will repeatedly call "update", it will do that "xmax" times.

“fun”是返回整数的函数。FuncAnimation会反复调用“update”,它会执行“xmax”次数。

#3


8  

In case anyone comes across this article looking for what I was looking for, I found examples at

如果有人看到这篇文章寻找我要找的东西,我可以在上面找到例子

How to visualize scalar 2D data with Matplotlib?

如何用Matplotlib可视化标量2D数据?

and

http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop (on web.archive.org)

http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop(web.archive.org)

then modified them to use imshow with an input stack of frames, instead of generating and using contours on the fly.

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


Starting with a 3D array of images of shape (nBins, nBins, nBins), called frames.

从一组被称为框架的三维图形(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)

I also found a much simpler way to go about this whole process, albeit less robust:

我还发现了一种更简单的方法来处理整个过程,尽管不那么健壮:

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

Note that both of these only seem to work with ipython --pylab=tk, a.k.a.backend = TkAgg

请注意,这两种方法似乎只适用于ipython——pylab=tk, a.k.a。后端= TkAgg

Thank you for the help with everything.

谢谢你对一切的帮助。

#4


5  

I have released a package called python-drawnow that provides functionality to let a figure update, typically called within a for loop, similar to Matlab's drawnow.

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

An example usage:

用法:一个例子

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)

This package works with any matplotlib figure and provides options to wait after each figure update or drop into the debugger.

此包与任何matplotlib图一起工作,并提供了在每个图更新或放入调试器后等待的选项。

#5


3  

All of the above might be true, however for me "online-updating" of figures only works with some backends, specifically wx. You just might try to change to this, e.g. by starting ipython/pylab by ipython --pylab=wx! Good luck!

以上这些可能都是对的,但是对我来说,“在线更新”的数字只提供一些支持,特别是wx。您可以尝试改变一下,例如,通过ipython启动ipython/pylab——pylab=wx!好运!

#6


2  

You can also do like the following: This will draw a 10x1 random matrix data on the plot for 50 cycles of the for loop.

您还可以这样做:这将在图上绘制一个10x1随机矩阵数据,用于for循环的50个周期。

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()

#7


-2  

import csv
import sys
import getopt
import socket
import time
import numpy as np
import matplotlib
from scipy.misc import imread
from matplotlib import pyplot as plt
import warnings
fig, ax = plt.subplots()
ax.set_xlim(-158, 553)
ax.set_ylim(-290, 733)
im = plt.imread("")
plt.imshow(img, zorder=0, extent=[0.5, 8.0, 1.0, 7.0])

fig.show()
l_global=[]
points=[]
master_tag_csvlink='c:/logfolde.log.csv'
csvfile=open(master_tag_csvlink, 'r')
for ainfo in csvfile:
        line= ainfo
        l_list= list(line.split('_'))
        l_local=[]
        for i in range(int(l_list[0])):
            l_local.append(list(l_list[i+1].split(',')))
        function1= lambda x,i: x[i] # return list[n,X] of elements at x
        c= lambda x,l: [x for i in range(l) if True]
        for i in range(len(l_local)):
            l_local[i][1],l_local[i][2]=int(l_local[i][1]),int(l_local[i][2])

        if l_global: #In begining l_glocal is empty, so just copy the data in to l_global
            l_global=l_local[:]
            for i in range(len(l_global)):
                points.append(plt.plot(function1(l_global[i],1),function1(l_global[i],2),'g',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2))))



        else: # compare the l_local & l_global for any updates 
            tag_Id=map(function1,l_local,c(0,len(l_local))) #list of list of tagId,x,y TagId is filtered - local
            mTag_Id=map(fuction1,l_global,c(0,len(l_global))) #list of list of tagId,x,y TagId is filtered - master

            for i in mTag_Id: 
                if i not in tag_Id: #comparing master tags and tag_Id's
                    index=mTag_Id.index(i) ###############  Tags in master list but not in Tag_id
                    copy_point=l_global[index]
                    [removing_point]=points[index]########  means tag is in-active ,turn tag color into red
                    removing_point.remove()
                    del points[index]

                    points.insert(index,plt.plot(function1(l_global[index],1),function1(l_global[index],2),'r',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2))))

                elif i in tag_Id: # append the tag into l_global
                    index=mTag_Id.index(i) ###############  Tags in master list but not in Tag_id
                    l_global[index]=l_local[index][:]
                    [removing_point]=points[index]########  means tag is active update coordinates
                    removing_point.remove()
                    del points[index]
                    points.insert(index,plt.plot(function1(l_global[index],1),function1(l_global[index],2),'g',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2))))
            for i in Tag_Id:
                if i not in mTag_Id:
                    index=Tag_Id(i)
                    l_global.append(l_local[index]]
                    points.append(plt.plot(function1(l_global[-1],1),function1(l_global[-1],2),'g',label="Tag:%s, X:%f, y: %f"%(function1(l_global[i],0),function1(l_global[i],1),function1(l_global[i],2))))

# 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(11)1
# 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()