Chcę utworzyć animację z matplotlib do monitorowania zbieżności algorytmu grupowania. Powinien narysować wykres rozrzutu moich danych, gdy zostanie wywołany po raz pierwszy i narysować elipsy błędów za każdym razem, gdy wykres zostanie zaktualizowany. Próbuję użyć canvas_copy_from_bbox()
i restore_region()
, aby zapisać wykres rozrzutu, a następnie narysować nowy zestaw elips, gdy aktualizuję wykres. Jednak kod po prostu rysuje nowe elipsy na starych, bez uprzedniego wyczyszczenia poprzedniego wydruku. Podejrzeń, w pewien sposób to podejście nie działa dobrze z poleceniami Ellipse()
i add_path()
, ale nie wiem jak to naprawić.Czyszczenie tła w matplotlib za pomocą wxPython
Oto kod:
import wx
import math
from math import pi
from matplotlib.patches import Ellipse
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import \
FigureCanvasWxAgg as FigureCanvas
TIMER_ID = wx.NewId()
class _MonitorPlot(wx.Frame):
def __init__(self, data, scale=1):
self.scale = scale
wx.Frame.__init__(self, None, wx.ID_ANY,
title="FlowVB Progress Monitor", size=(800, 600))
self.fig = Figure((8, 6), 100)
self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
self.ax = self.fig.add_subplot(111)
x_lims = [data[:, 0].min(), data[:, 0].max()]
y_lims = [data[:, 1].min(), data[:, 1].max()]
self.ax.set_xlim(x_lims)
self.ax.set_ylim(y_lims)
self.ax.set_autoscale_on(False)
self.l_data = self.ax.plot(data[:, 0], data[:, 1], color='blue',
linestyle='', marker='o')
self.canvas.draw()
self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
self.Bind(wx.EVT_IDLE, self._onIdle)
def update_plot(self, pos, cov):
self.canvas.restore_region(self.bg)
for k in range(pos.shape[0]):
l_center, = self.ax.plot(pos[k, 0], pos[k, 1],
color='red', marker='+')
U, s, Vh = np.linalg.svd(cov[k, :, :])
orient = math.atan2(U[1, 0], U[0, 0]) * 180/pi
ellipsePlot = Ellipse(xy=pos[k, :], width=2.0 * math.sqrt(s[0]),
height=2.0 * math.sqrt(s[1]),
angle=orient, facecolor='none',
edgecolor='red')
self.ax.add_patch(ellipsePlot)
self.canvas.draw()
self.canvas.blit(self.ax.bbox)
zamiast 'fig.canvas.blit (ax.bbox)' może również rozważyć 'fig.canvas.update()'. Według [tego bloga] (http://bastibe.de/2013-05-30-speeding-up-matplotlib.html) jest równie szybki. Dla mnie rozwiązał problem przepełnienia pamięci. –
@LucM - To, co jest warte, zależy w dużej mierze od zaplecza. 'fig.canvas.blit (updated_region)' będzie znacznie szybszy i będzie działał idealnie z 'TkAgg' i kilkoma innymi popularnymi backendami. Jednak w innych systemach zapleczowych funkcja 'fig.canvas.update()' (która odświeża całe płótno) jest szybsza, ponieważ zabrudzanie podregionu nie jest w pełni obsługiwane. Bez względu na to, dobrze jest wiedzieć o obu. –
To będzie naprawdę przydatne wiedzieć, czy przełączam backend. Podczas korzystania z PyQt miałem przepełnienie pamięci blitem. –