Как обновить участок в 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)
6 ответов:
по существу есть два варианта:
делать именно то, что вы сейчас делаете, но назвать
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()
это сработало для меня. Многократно вызывает функцию, обновляющую график каждый раз.
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 будет неоднократно вызывать "обновление", он будет делать это" xmax " раз.
в случае, если кто-то сталкивается с этой статьей ищет то, что я искал, я нашел примеры в
как визуализировать скалярные 2D данные с помощью Matplotlib?
и
http://mri.brechmos.org/2009/07/automatically-update-a-figure-in-a-loop (on web.archive.org)
затем изменил их, чтобы использовать imshow с входным стеком кадров, вместо того, чтобы генерировать и использовать контуры на лету.
начиная с 3D массива изображений формы (nBins, nBins, nBins), называется
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)
Я также нашел гораздо более простой способ пройти весь этот процесс, хотя и менее надежный:
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
Спасибо за помощь всем.
вы также можете сделать следующее: Это позволит нарисовать случайную матрицу данных 10x1 на графике для 50 циклов цикла for.
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()
я выпустил пакет под названием python-drawnow это обеспечивает функциональность для обновления фигуры, обычно вызываемой в цикле 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 и предоставляет опции для ожидания после каждого обновления фигуры или падения в отладчик.