Animation with pcolormesh routine in matplotlib, how do I initialize the data?

后端 未结 4 711
傲寒
傲寒 2020-12-01 17:23

I am trying to animate a pcolormesh in matplotlib. I have seen many of the examples using the package animation, most of them using a 1D plot routi

相关标签:
4条回答
  • 2020-12-01 17:43

    I am not sure why your quad = ax.pcolormesh(X,Y,Z) function is giving an error. Can you post the error?

    Below is what I would do to create a simple animation using 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()
    

    One of the frames: enter image description here

    Does this help? If not, maybe you can clarify the question.

    0 讨论(0)
  • 2020-12-01 17:56

    There is an ugly detail you need to take care when using QuadMesh.set_array(). If you intantiate your QuadMesh with X, Y and C you can update the values C by using set_array(). But set_array does not support the same input as the constructor. Reading the source reveals that you need to pass a 1d-array and what is even more puzzling is that depending on the shading setting you might need to cut of your array C.

    Edit: There is even a very old bug report about the confusing array size for shading='flat'.

    That means:

    Using QuadMesh.set_array() with shading = 'flat'

    'flat' is default value for 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()
    

    Looks like:

    resulting graphic with shadig=flat

    Note that if you omit C = C[:-1, :-1] your will get this broken graphic:

    broken graphic with shading=flat

    Using QuadMesh.set_array() with 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()
    

    If you cut off the last row/column with shade='gouraud' you will get:

    ValueError: total size of new array must be unchanged
    
    0 讨论(0)
  • 2020-12-01 17:57

    The problem was that I was wrongly using set_array() routine. It is very important to note that you must pass a 1D array to this routine. To do so, regarding that color, pcolormesh and so on usually plots multidimensional arrays, you should use .ravel() . One more important thing: In order to animate different plots at the same time, the blitz option at animate.FuncAnimation must be False (See section "Animating selected plot elements" of this link).

    Here I post the code that simple program with various subplots:

    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!!'
    
    0 讨论(0)
  • 2020-12-01 18:01

    There is another answer presented here that looks simpler thus better (IMHO)

    Here is a copy & paste of the alternative solution :

    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])
    
    0 讨论(0)
提交回复
热议问题