Animar puntos con tags con matplotlib.

Tengo una animación con líneas y ahora quiero etiquetar los puntos. Intenté con plt.annotate() y probé con plt.text() pero los laboratorios no se mueven. Este es mi código de ejemplo:

 import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation def update_line(num, data, line): newData = np.array([[1+num,2+num/2,3,4-num/4,5+num],[7,4,9+num/3,2,3]]) line.set_data(newData) plt.annotate('A0', xy=(newData[0][0],newData[1][0])) return line, fig1 = plt.figure() data = np.array([[1,2,3,4,5],[7,4,9,2,3]]) l, = plt.plot([], [], 'r-') plt.xlim(0, 20) plt.ylim(0, 20) plt.annotate('A0', xy=(data[0][0], data[1][0])) # plt.text( data[0][0], data[1][0], 'A0') line_ani = animation.FuncAnimation(fig1, update_line, 25, fargs=(data, l), interval=200, blit=True) plt.show() 

¿Puedes ayudarme por favor?

Mi siguiente paso es: Tengo vectores con origen en estos puntos. Estos vectores cambian su longitud y su dirección en cada paso de la animación. ¿Cómo puedo animar estos?

Sin animación esto funciona:

 soa =np.array( [ [data[0][0],data[1][0],F_A0[i][0][0],F_A0[i][1][0]], [data[0][1],data[1][1],F_B0[i][0][0],F_B0[i][1][0]], [data[0][2],data[1][2],F_D[i][0][0],F_D[i][1][0]] ]) X,Y,U,V = zip(*soa) ax = plt.gca() ax.quiver(X,Y,U,V,angles='xy',scale_units='xy',scale=1) 

Primero, muchas gracias por tu respuesta rápida y muy útil.

Mi problema de animación vectorial lo he resuelto con esto:

 annotation = ax.annotate("C0", xy=(data[0][2], data[1][2]), xycoords='data', xytext=(data[0][2]+1, data[1][2]+1), textcoords='data', arrowprops=dict(arrowstyle="->")) 

y en la ‘función de actualización’ escribo:

 annotation.xytext = (newData[0][2], newData[1][2]) annotation.xy = (data[0][2]+num, data[1][2]+num) 

para cambiar la posición inicial y final de los vectores (flechas).

Pero, ¿qué es, bueno, tengo 100 vectores o más? No es practicable escribir:

 annotation1 = ... annotation2 = ... . : annotation100 = ... 

Lo intenté con una lista:

 ... annotation = [annotation1, annotation2, ... , annotation100] ... def update(num): ... return line, annotation 

y obtuvo este error: AttributeError: el objeto ‘list’ no tiene ningún atributo ‘axes’

¿Que puedo hacer? ¿Tienes alguna idea?

Tiene la devolución de todos los objetos que han cambiado desde su función de actualización. Entonces, ya que su anotación cambió su posición, también debe devolverla:

 line.set_data(newData) annotation = plt.annotate('A0', xy=(newData[0][0],newData[1][0])) return line, annotation 

Puedes leer más sobre matplotlib animaciones de matplotlib en este tutorial.

También debe especificar la función de init para que FuncAnimation sepa qué elementos eliminar de la ttwig al volver a dibujar en la primera actualización. Entonces el ejemplo completo sería:

 import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation # Create initial data data = np.array([[1,2,3,4,5], [7,4,9,2,3]]) # Create figure and axes fig = plt.figure() ax = plt.axes(xlim=(0, 20), ylim=(0, 20)) # Create initial objects line, = ax.plot([], [], 'r-') annotation = ax.annotate('A0', xy=(data[0][0], data[1][0])) annotation.set_animated(True) # Create the init function that returns the objects # that will change during the animation process def init(): return line, annotation # Create the update function that returns all the # objects that have changed def update(num): newData = np.array([[1 + num, 2 + num / 2, 3, 4 - num / 4, 5 + num], [7, 4, 9 + num / 3, 2, 3]]) line.set_data(newData) # This is not working i 1.2.1 # annotation.set_position((newData[0][0], newData[1][0])) annotation.xytext = (newData[0][0], newData[1][0]) return line, annotation anim = animation.FuncAnimation(fig, update, frames=25, init_func=init, interval=200, blit=True) plt.show() 

Vengo aquí desde esta pregunta , donde se debe actualizar una anotación que use xy y xytext . Parece que, para actualizar la anotación correctamente, se necesita establecer el atributo .xy de la anotación para establecer la posición del punto anotado y usar el método .set_position() de la anotación para establecer la posición de la anotación . Establecer el atributo .xytext no tiene ningún efecto, algo confuso en mi opinión. A continuación un ejemplo completo:

 import matplotlib.pyplot as plt import numpy as np import matplotlib.animation as animation fig, ax = plt.subplots() ax.set_xlim([-1,1]) ax.set_ylim([-1,1]) L = 50 theta = np.linspace(0,2*np.pi,L) r = np.ones_like(theta) x = r*np.cos(theta) y = r*np.sin(theta) line, = ax.plot(1,0, 'ro') annotation = ax.annotate( 'annotation', xy=(1,0), xytext=(-1,0), arrowprops = {'arrowstyle': "->"} ) def update(i): new_x = x[i%L] new_y = y[i%L] line.set_data(new_x,new_y) ##annotation.xytext = (-new_x,-new_y) <-- does not work annotation.set_position((-new_x,-new_y)) annotation.xy = (new_x,new_y) return line, annotation ani = animation.FuncAnimation( fig, update, interval = 500, blit = False ) plt.show() 

El resultado se ve algo como esto:

resultado del código anterior

En caso de que las versiones importen, este código se probó en Python 2.7 y 3.6 con matplotlib versión 2.1.1, y en ambos casos la configuración de .xytext no tuvo efecto, mientras que .set_position() y .xy funcionaron como se esperaba.

Creo que me di cuenta de cómo animar múltiples anotaciones a través de una lista. Primero creas tu lista de anotaciones:

 for i in range(0,len(someMatrix)): annotations.append(ax.annotate(str(i), xy=(someMatrix.item(0,i), someMatrix.item(1,i)))) 

Luego, en tu función “animar”, haz lo que ya has escrito:

 for num, annot in enumerate(annotations): annot.set_position((someMatrix.item((time,num)), someMatrix.item((time,num)))) 

(Puedes escribirlo como un bucle for tradicional también si no te gusta la forma de enumerar). No olvide devolver la lista completa de anotaciones en su statement de devolución.

Entonces lo importante es establecer “blit = False” en tu FuncAnimation:

 animation.FuncAnimation(fig, animate, frames="yourframecount", interval="yourpreferredinterval", blit=False, init_func=init) 

Es bueno señalar que blit = False puede ralentizar las cosas. Pero, desafortunadamente, es la única forma en que puedo conseguir que la animación de las anotaciones en las listas funcione …