如何更新matplotlib中的情节?
我在这里重绘图的问题。 我允许用户在时间尺度(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)
你基本上有两个select:
-
做你正在做的事情,但在
graph1.clear()
graph2.clear()
数据之前调用graph1.clear()
和graph2.clear()
。 这是最慢,但也是最简单和最稳健的select。 -
而不是重新绘图,您可以更新绘图对象的数据。 您需要对代码进行一些更改,但这应该比每次重新绘制代码要快得多。 但是,您绘制的数据的形状不能改变,如果数据范围发生变化,则需要手动重置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()
这对我有效。 反复调用每次更新graphics的函数。
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”次。
万一任何人遇到这篇文章寻找我正在寻找什么,我发现的例子
如何用Matplotlib可视化标量二维数据?
和
http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop(在web.archive.org上);
然后修改它们以使用input堆栈的imshow,而不是即时生成和使用轮廓。
从形状(nBins,nBins,nBins)的3D图像开始,称为frames
。
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)
我还发现了一个简单的方法去做这个整个过程,尽pipe不太稳健:
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
谢谢你的帮助。
我已经发布了一个名为python-drawnow的包,它提供了一个函数来更新graphics,通常在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图一起使用,并提供了在每个数字更新之后等待或放入debugging器的选项。
以上所有可能都是真实的,但对于我来说,“在线更新”的数字只适用于一些后端,特别是wx
。 你可能会尝试改变,例如通过ipython启动ipython / ipython --pylab=wx
! 祝你好运!