Quiero crear una animación con matplotlib para controlar la convergencia de un algoritmo de agrupamiento. Debería dibujar un diagrama de dispersión de mis datos cuando se invoque por primera vez y dibujar elipses de error cada vez que se actualice el trazado. Intento usar canvas_copy_from_bbox()
y restore_region()
para guardar el diagrama de dispersión y luego dibujar un nuevo conjunto de elipses cada vez que actualizo el gráfico. Sin embargo, el código solo traza las nuevas elipsis sobre las antiguas, sin borrar primero la gráfica anterior. Sospecho que, de alguna manera, este enfoque no funciona bien con los comandos Ellipse()
y add_path()
, pero no sé cómo solucionarlo.Borrado de fondo en matplotlib usando wxPython
Aquí está el código:
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)
en lugar de 'fig.canvas.blit (ax.bbox)' también se podría considerar 'fig.canvas.update()'. Según [este blog] (http://bastibe.de/2013-05-30-speeding-up-matplotlib.html), es igualmente rápido. Para mí, resolvió un problema de desbordamiento de memoria. –
@LucM - Por lo que vale, eso depende mucho del back-end. 'fig.canvas.blit (updated_region)' será mucho más rápido y funcionará perfectamente con 'TkAgg' y algunos otros back-end comunes. Sin embargo, en otros backends, 'fig.canvas.update()' (que actualiza todo el lienzo) es más rápido porque no es totalmente compatible con bligar una subregión. De todos modos, es bueno saber sobre ambos. –
Eso será realmente útil para saber si cambio de servidor. Tuve un desbordamiento de memoria con blit cuando usé PyQt. –