Titulo animado en matplotlib

No puedo averiguar cómo hacer que un título animado funcione en un gráfico de FuncAnimation (que utiliza blit). Basado en http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/ y Python / Matplotlib – Actualizando rápidamente el texto en los ejes , he creado una animación, pero las partes del texto simplemente ganaron No animes Ejemplo simplificado:

import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np vls = np.linspace(0,2*2*np.pi,100) fig=plt.figure() img, = plt.plot(np.sin(vls)) ax = plt.axes() ax.set_xlim([0,2*2*np.pi]) #ttl = ax.set_title('',animated=True) ttl = ax.text(.5, 1.005, '', transform = ax.transAxes) def init(): ttl.set_text('') img.set_data([0],[0]) return img, ttl def func(n): ttl.set_text(str(n)) img.set_data(vls,np.sin(vls+.02*n*2*np.pi)) return img, ttl ani = animation.FuncAnimation(fig,func,init_func=init,frames=50,interval=30,blit=True) plt.show() 

Si se elimina blit=True , el texto aparece, pero disminuye la velocidad. Parece fallar con plt.title , ax.set_title y ax.text .

Edición: descubrí por qué funcionaba el segundo ejemplo en el primer enlace; El texto estaba dentro de la parte img . Si haces lo anterior 1.005 a .99 , verás lo que quiero decir. Probablemente hay una manera de hacer esto con un cuadro delimitador, de alguna manera …

Consulte Animación de los ejes / garrapatas de matplotlib y python matplotlib blit en los ejes o lados de la figura.

Entonces, el problema es que en las entrañas de la animation donde se guardan realmente los fondos de blit (línea 792 de animation.py ), captura lo que está en el cuadro delimitador de los ejes . Esto tiene sentido cuando tienes múltiples ejes siendo animados independientemente. En su caso, solo tiene que preocuparse por un axes y queremos animar cosas fuera del cuadro delimitador de ejes. Con un poco de parches de mono, un nivel de tolerancia para alcanzar las entrañas de mpl y hurgando un poco, y la aceptación de la solución más rápida y sucia, podemos resolver su problema como tal:

 import matplotlib import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np def _blit_draw(self, artists, bg_cache): # Handles blitted drawing, which renders only the artists given instead # of the entire figure. updated_ax = [] for a in artists: # If we haven't cached the background for this axes object, do # so now. This might not always be reliable, but it's an attempt # to automate the process. if a.axes not in bg_cache: # bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox) # change here bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.figure.bbox) a.axes.draw_artist(a) updated_ax.append(a.axes) # After rendering all the needed artists, blit each axes individually. for ax in set(updated_ax): # and here # ax.figure.canvas.blit(ax.bbox) ax.figure.canvas.blit(ax.figure.bbox) # MONKEY PATCH!! matplotlib.animation.Animation._blit_draw = _blit_draw vls = np.linspace(0,2*2*np.pi,100) fig=plt.figure() img, = plt.plot(np.sin(vls)) ax = plt.axes() ax.set_xlim([0,2*2*np.pi]) #ttl = ax.set_title('',animated=True) ttl = ax.text(.5, 1.05, '', transform = ax.transAxes, va='center') def init(): ttl.set_text('') img.set_data([0],[0]) return img, ttl def func(n): ttl.set_text(str(n)) img.set_data(vls,np.sin(vls+.02*n*2*np.pi)) return img, ttl ani = animation.FuncAnimation(fig,func,init_func=init,frames=50,interval=30,blit=True) plt.show() 

Tenga en cuenta que esto puede no funcionar como se espera si tiene más de un eje en su figura. Una solución mucho mejor es expandir axes.bbox solo lo suficiente para capturar sus títulos y las tags de tick del eje. Sospecho que hay código en algún lugar en mpl para hacer eso, pero no sé dónde está fuera de mi cabeza.

Para agregar a la solución de “parches de mono” de tcaswell, aquí se explica cómo puede agregar animación a las tags de marca de eje. Específicamente, para animar el eje x, establezca ax.xaxis.set_animated(True) y devuelva ax.xaxis desde las funciones de animación.

 import matplotlib import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np def _blit_draw(self, artists, bg_cache): # Handles blitted drawing, which renders only the artists given instead # of the entire figure. updated_ax = [] for a in artists: # If we haven't cached the background for this axes object, do # so now. This might not always be reliable, but it's an attempt # to automate the process. if a.axes not in bg_cache: # bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox) # change here bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.figure.bbox) a.axes.draw_artist(a) updated_ax.append(a.axes) # After rendering all the needed artists, blit each axes individually. for ax in set(updated_ax): # and here # ax.figure.canvas.blit(ax.bbox) ax.figure.canvas.blit(ax.figure.bbox) # MONKEY PATCH!! matplotlib.animation.Animation._blit_draw = _blit_draw vls = np.linspace(0,2*2*np.pi,100) fig=plt.figure() img, = plt.plot(np.sin(vls)) ax = plt.axes() ax.set_xlim([0,2*2*np.pi]) #ttl = ax.set_title('',animated=True) ttl = ax.text(.5, 1.05, '', transform = ax.transAxes, va='center') ax.xaxis.set_animated(True) def init(): ttl.set_text('') img.set_data([0],[0]) return img, ttl, ax.xaxis def func(n): ttl.set_text(str(n)) vls = np.linspace(0.2*n,0.2*n+2*2*np.pi,100) img.set_data(vls,np.sin(vls)) ax.set_xlim(vls[0],vls[-1]) return img, ttl, ax.xaxis ani = animation.FuncAnimation(fig,func,init_func=init,frames=60,interval=200,blit=True) plt.show() 

Si necesita arreglar el título, simplemente puede actualizar el título con:

 fig.suptitle() 

Ver la figura del documento API .

Debes llamar

 plt.draw() 

Después

 ttl.set_text(str(n)) 

Aquí hay un ejemplo muy simple de una animación de texto dentro de una figura “sin FuncAnimation ()”. Pruébalo, verás si es útil para ti.

 import matplotlib.pyplot as plt import numpy as np titles = np.arange(100) plt.ion() fig = plt.figure() for text in titles: plt.clf() fig.text(0.5,0.5,str(text)) plt.draw()