¿Cómo animar un diagtwig de dispersión?

Estoy tratando de hacer una animación de un diagtwig de dispersión donde los colores y el tamaño de los puntos cambian en diferentes etapas de la animación. Para los datos tengo dos ndarray numpy con un valor de x y un valor de y:

data.shape = (ntime, npoint) x.shape = (npoint) y.shape = (npoint) 

Ahora quiero trazar un diagtwig de dispersión del tipo

 pylab.scatter(x,y,c=data[i,:]) 

y crear una animación sobre el índice i . ¿Cómo hago esto?

Aquí hay un ejemplo rápido usando el nuevo módulo de animación.

Es un poco más complejo de lo que tiene que ser, pero esto debería darle un marco para hacer cosas más sofisticadas.

Si está usando OSX y está usando el backend de OSX, deberá cambiar blit=True a blit=False en la FuncAnimation inicialización de FuncAnimation . El backend OSX no soporta completamente el blitting. El rendimiento se verá afectado, pero el ejemplo debería ejecutarse correctamente en OSX con blit deshabilitado.

 import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np class AnimatedScatter(object): """An animated scatter plot using matplotlib.animations.FuncAnimation.""" def __init__(self, numpoints=50): self.numpoints = numpoints self.stream = self.data_stream() # Setup the figure and axes... self.fig, self.ax = plt.subplots() # Then setup FuncAnimation. self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, init_func=self.setup_plot, blit=True) def setup_plot(self): """Initial drawing of the scatter plot.""" x, y, s, c = next(self.stream) self.scat = self.ax.scatter(x, y, c=c, s=s, animated=True) self.ax.axis([-10, 10, -10, 10]) # For FuncAnimation's sake, we need to return the artist we'll be using # Note that it expects a sequence of artists, thus the trailing comma. return self.scat, def data_stream(self): """Generate a random walk (brownian motion). Data is scaled to produce a soft "flickering" effect.""" data = np.random.random((4, self.numpoints)) xy = data[:2, :] s, c = data[2:, :] xy -= 0.5 xy *= 10 while True: xy += 0.03 * (np.random.random((2, self.numpoints)) - 0.5) s += 0.05 * (np.random.random(self.numpoints) - 0.5) c += 0.02 * (np.random.random(self.numpoints) - 0.5) yield data def update(self, i): """Update the scatter plot.""" data = next(self.stream) # Set x and y data... self.scat.set_offsets(data[:2, :]) # Set sizes... self.scat._sizes = 300 * abs(data[2])**1.5 + 100 # Set colors.. self.scat.set_array(data[3]) # We need to return the updated artist for FuncAnimation to draw.. # Note that it expects a sequence of artists, thus the trailing comma. return self.scat, def show(self): plt.show() if __name__ == '__main__': a = AnimatedScatter() a.show() 

introduzca la descripción de la imagen aquí

Para un ejemplo más simple, eche un vistazo a lo siguiente:

 import matplotlib.pyplot as plt import numpy as np import matplotlib.animation as animation def main(): numframes = 100 numpoints = 10 color_data = np.random.random((numframes, numpoints)) x, y, c = np.random.random((3, numpoints)) fig = plt.figure() scat = plt.scatter(x, y, c=c, s=100) ani = animation.FuncAnimation(fig, update_plot, frames=xrange(numframes), fargs=(color_data, scat)) plt.show() def update_plot(i, data, scat): scat.set_array(data[i]) return scat, main() 

Aquí está la cosa. Utilicé a un usuario de Qt y Matlab y no estoy muy familiarizado con el sistema de animación en matplotlib.

Pero sí tengo una manera de hacer cualquier tipo de animación que quieras, como en Matlab. Es realmente poderoso. No hay necesidad de verificar las referencias del módulo y eres bueno para trazar lo que quieras. Así que espero que pueda ayudar.

La idea básica es usar el evento de tiempo dentro de PyQt (estoy seguro de que otro sistema Gui en el Python como wxPython y TraitUi tiene el mismo mecanismo interno para hacer una respuesta al evento. Pero no sé cómo). Cada vez que se llama un evento de temporizador de PyQt, actualizo todo el canvas y vuelvo a dibujar toda la imagen, sé que la velocidad y el rendimiento pueden verse afectados lentamente, pero no es tanto.

Aquí hay un pequeño ejemplo de ello:

 import sys from PyQt4 import QtGui from matplotlib.figure import Figure from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas import numpy as np class Monitor(FigureCanvas): def __init__(self): self.fig = Figure() self.ax = self.fig.add_subplot(111) FigureCanvas.__init__(self, self.fig) self.x = np.linspace(0,5*np.pi,400) self.p = 0.0 self.y = np.sin(self.x+self.p) self.line = self.ax.scatter(self.x,self.y) self.fig.canvas.draw() self.timer = self.startTimer(100) def timerEvent(self, evt): # update the height of the bars, one liner is easier self.p += 0.1 self.y = np.sin(self.x+self.p) self.ax.cla() self.line = self.ax.scatter(self.x,self.y) self.fig.canvas.draw() if __name__ == "__main__": app = QtGui.QApplication(sys.argv) w = Monitor() w.setWindowTitle("Convergence") w.show() sys.exit(app.exec_()) 

Puede ajustar la velocidad de actualización en el

  self.timer = self.startTimer(100) 

Soy como usted que quiere usar el diagtwig de dispersión animado para hacer una animación de clasificación. Pero simplemente no puedo encontrar una función llamada “set”. Así que refresqué todo el canva.

Espero eso ayude..

Escribí celuloide para hacer esto más fácil. Probablemente sea más fácil de mostrar con un ejemplo:

 import matplotlib.pyplot as plt from matplotlib import cm import numpy as np from celluloid import Camera numpoints = 10 points = np.random.random((2, numpoints)) colors = cm.rainbow(np.linspace(0, 1, numpoints)) camera = Camera(plt.figure()) for _ in range(100): points += 0.1 * (np.random.random((2, numpoints)) - .5) plt.scatter(*points, c=colors, s=100) camera.snap() anim = camera.animate(blit=True) anim.save('scatter.mp4') 

introduzca la descripción de la imagen aquí

Utiliza ArtistAnimation bajo el capó. camera.snap captura el estado actual de la figura que se utiliza para crear los cuadros en la animación.

Edición: para cuantificar la cantidad de memoria que utiliza, lo ejecuté a través de memory_profiler .

 Line # Mem usage Increment Line Contents ================================================ 11 65.2 MiB 65.2 MiB @profile 12 def main(): 13 65.2 MiB 0.0 MiB numpoints = 10 14 65.2 MiB 0.0 MiB points = np.random.random((2, numpoints)) 15 65.2 MiB 0.1 MiB colors = cm.rainbow(np.linspace(0, 1, numpoints)) 16 65.9 MiB 0.6 MiB fig = plt.figure() 17 65.9 MiB 0.0 MiB camera = Camera(fig) 18 67.8 MiB 0.0 MiB for _ in range(100): 19 67.8 MiB 0.0 MiB points += 0.1 * (np.random.random((2, numpoints)) - .5) 20 67.8 MiB 1.9 MiB plt.scatter(*points, c=colors, s=100) 21 67.8 MiB 0.0 MiB camera.snap() 22 70.1 MiB 2.3 MiB anim = camera.animate(blit=True) 23 72.1 MiB 1.9 MiB anim.save('scatter.mp4') 

Para resumir esto:

  • Creando 100 plots utilizadas 1.9 MiB.
  • Haciendo la animación utilizada 2.3 MiB.
  • Este método de hacer animaciones utilizó 4.2 MiB de memoria en sum.