python - examples - Animación con la rutina pcolormesh en matplotlib, ¿cómo inicializo los datos?
pcolormesh example (4)
Intento animar una pcolormesh en matplotlib. He visto muchos ejemplos usando la animación del paquete, la mayoría de ellos usando una rutina de trazado 1D, y algunos de ellos con imshow (). Primero, quiero usar la rutina FuncAnimation. Mi problema es, primero, que no sé si puedo inicializar la trama
fig,ax = plt.subplots()
quad = ax.pcolormesh(X,Y,Z)
He intentado algunas líneas simples:
fig,ax = plt.subplots()
quad = ax.pcolormesh([])
def init():
quad.set_array([])
return quad,
def animate(ktime):
quad.set_array(X,Y,np.sin(Z)+ktime)
return quad,
anim = animation.FuncAnimation(fig,animate,init_func=init,frames=Ntime,interval=200,blit=True)
plt.show ()
Por cierto, ¿cómo configuro las etiquetas y la trama animada? ¿Puedo animar el título, si muestra un número que cambia en el tiempo? Gracias
No estoy seguro de por qué su función quad = ax.pcolormesh (X, Y, Z) está dando un error. ¿Puedes publicar el error?
A continuación se muestra lo que haría para crear una animación simple usando pcolormesh:
import matplotlib.pyplot as plt
import numpy as np
y, x = np.meshgrid(np.linspace(-3, 3,100), np.linspace(-3, 3,100))
z = np.sin(x**2+y**2)
z = z[:-1, :-1]
ax = plt.subplot(111)
quad = plt.pcolormesh(x, y, z)
plt.colorbar()
plt.ion()
plt.show()
for phase in np.linspace(0,10*np.pi,200):
z = np.sin(np.sqrt(x**2+y**2) + phase)
z = z[:-1, :-1]
quad.set_array(z.ravel())
plt.title(''Phase: %.2f''%phase)
plt.draw()
plt.ioff()
plt.show()
Uno de los cuadros:
¿Esto ayuda? Si no, tal vez puedas aclarar la pregunta.
El problema era que estaba usando erróneamente la rutina set_array()
. Es muy importante tener en cuenta que debe pasar una matriz 1D a esta rutina. Para hacerlo, con respecto a ese color, pcolormesh, etc. traza matrices multidimensionales, debe usar .ravel (). Una cosa más importante: para animar diferentes tramas al mismo tiempo, la opción blitz
en animate.FuncAnimation
debe ser False
(Ver la sección "Animar los elementos seleccionados de la trama" de este enlace ).
Aquí publico el código de ese programa simple con varias subtramas:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.gridspec as gridspec
import matplotlib.animation as animation
y, x = np.meshgrid(np.linspace(-10, 10,100), np.linspace(-10, 10,100))
z = np.sin(x)*np.sin(x)+np.sin(y)*np.sin(y)
v = np.linspace(-10, 10,100)
t = np.sin(v)*np.sin(v)
tt = np.cos(v)*np.cos(v)
###########
fig = plt.figure(figsize=(16, 8),facecolor=''white'')
gs = gridspec.GridSpec(5, 2)
ax1 = plt.subplot(gs[0,0])
line, = ax1.plot([],[],''b-.'',linewidth=2)
ax1.set_xlim(-10,10)
ax1.set_ylim(0,1)
ax1.set_xlabel(''time'')
ax1.set_ylabel(''amplitude'')
ax1.set_title(''Oscillationsssss'')
time_text = ax1.text(0.02, 0.95, '''', transform=ax1.transAxes)
#############################
ax2 = plt.subplot(gs[1:3,0])
quad1 = ax2.pcolormesh(x,y,z,shading=''gouraud'')
ax2.set_xlabel(''time'')
ax2.set_ylabel(''amplitude'')
cb2 = fig.colorbar(quad1,ax=ax2)
#########################
ax3 = plt.subplot(gs[3:,0])
quad2 = ax3.pcolormesh(x, y, z,shading=''gouraud'')
ax3.set_xlabel(''time'')
ax3.set_ylabel(''amplitude'')
cb3 = fig.colorbar(quad2,ax=ax3)
############################
ax4 = plt.subplot(gs[:,1])
line2, = ax4.plot(v,tt,''b'',linewidth=2)
ax4.set_xlim(-10,10)
ax4.set_ylim(0,1)
def init():
line.set_data([],[])
line2.set_data([],[])
quad1.set_array([])
return line,line2,quad1
def animate(iter):
t = np.sin(2*v-iter/(2*np.pi))*np.sin(2*v-iter/(2*np.pi))
tt = np.cos(2*v-iter/(2*np.pi))*np.cos(2*v-iter/(2*np.pi))
z = np.sin(x-iter/(2*np.pi))*np.sin(x-iter/(2*np.pi))+np.sin(y)*np.sin(y)
line.set_data(v,t)
quad1.set_array(z.ravel())
line2.set_data(v,tt)
return line,line2,quad1
gs.tight_layout(fig)
anim = animation.FuncAnimation(fig,animate,frames=100,interval=50,blit=False,repeat=False)
plt.show()
print ''Finished!!''
Hay otra respuesta presentada aquí que parece más simple y mejor (en mi humilde opinión)
Aquí hay una copia y pega de la solución alternativa:
import matplotlib.pylab as plt
from matplotlib import animation
fig = plt.figure()
plt.hold(True)
#We need to prime the pump, so to speak and create a quadmesh for plt to work with
plt.pcolormesh(X[0:1], Y[0:1], C[0:1])
anim = animation.FuncAnimation(fig, animate, frames = range(2,155), blit = False)
plt.show()
plt.hold(False)
def animate( self, i):
plt.title(''Ray: %.2f''%i)
#This is where new data is inserted into the plot.
plt.pcolormesh(X[i-2:i], Y[i-2:i], C[i-2:i])
Hay un detalle feo que debe tener cuidado al usar QuadMesh.set_array (). Si intactas tu QuadMesh con X, Y y C puedes actualizar los valores C usando set_array (). Pero set_array no admite la misma entrada que el constructor. La lectura de la fuente revela que debe pasar una matriz 1d y lo que es aún más desconcertante es que, dependiendo de la configuración de shading
, es posible que necesite cortar la matriz C
Editar: Incluso hay un informe de error muy antiguo sobre el tamaño de matriz confuso para shading=''flat''
.
Eso significa:
Usando QuadMesh.set_array () con shading = ''flat''
''plano'' es el valor predeterminado para el shading
.
# preperation
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
y = np.linspace(-10, 10, num=1000)
x = np.linspace(-10, 10, num=1000)
X, Y = np.meshgrid(x, y)
C = np.ones((1000, 1000)) * float(''nan'')
# intantiate empty plot (values = nan)
pcmesh = plt.pcolormesh(X, Y, C, vmin=-100, vmax=100, shading=''flat'')
# generate some new data
C = X * Y
# necessary for shading=''flat''
C = C[:-1, :-1]
# ravel() converts C to a 1d-array
pcmesh.set_array(C.ravel())
# redraw to update plot with new data
plt.draw()
Parece:
Tenga en cuenta que si omite C = C[:-1, :-1]
obtendrá este gráfico roto:
Usando QuadMesh.set_array () con shading = ''gouraud''
# preperation (same as for ''flat'')
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
y = np.linspace(-10, 10, num=1000)
x = np.linspace(-10, 10, num=1000)
X, Y = np.meshgrid(x, y)
C = np.ones((1000, 1000)) * float(''nan'')
# intantiate empty plot (values = nan)
pcmesh = plt.pcolormesh(X, Y, C, vmin=-100, vmax=100, shading=''gouraud'')
# generate some new data
C = X * Y
# here no cut of of last row/column!
# ravel() converts C to a 1d-array
pcmesh.set_array(C.ravel())
# redraw to update plot with new data
plt.draw()
Si corta la última fila / columna con shade = ''gouraud'', obtendrá:
ValueError: total size of new array must be unchanged