mefit0
mefit0

Reputation: 11

how to get animated patches instead of n-times plotted patches using Python and matplotlib

i am using Python 2.7 (Anaconda) with matplotlib to get the animation of a square patch on a "desk" square patch -background-, so that the little square has to move along a required direction (north,south,est,west) for range=n positions(move=1). I'm using FuncAnimation for my first time, but as plot i only get the square plotted n times instead of have it moving/animated. Here is my code with sample direction "south":

import matplotlib.pyplot as plt
import matplotlib.patches as ptc
from matplotlib import animation
import numpy as np
#__________________________________________________________________________PLOT
fig = plt.figure()
ax1 = fig.add_subplot(111,aspect='equal')

ax1.set_xlim((0,10))
ax1.set_ylim((0,10))

#________________________________________________FIGURES_VECTORS_INITIALIZATION
#DESK 
desk=np.matrix([[1,1],[9,1],[9,9],[1,9]]) #desk vertices
#setting initialization - DESK
def initDesk():
    ax1.add_patch(ptc.Polygon(desk, closed=True,
                          fill=False, hatch="/"))    

#SQUARE
squVer=np.matrix([[4.5,6.5],[5.5,6.5],[5.5,7.5],[4.5,7.5]]) #square vertices

#_____________________________________________________DIRECTIONS_INITIALIZATION 
move=1
null=0
#4DIRECTIONS
north=np.array(([+null,+move]))
south=np.array([+null,-move])
est=np.array([+move,+null])
west=np.array([-move,+null])

#_____________________________________________________________________ANIMATION
def animate(newPos):
    iniSqu=np.matrix(squVer)
    position=newPos

    for step in range (0,4):
        if step < 1: #starting point
            newPos=iniSqu
        else: 
            newPos=iniSqu+position
        square=ptc.Polygon(newPos, closed=True,
                             facecolor="blue")
        ax1.add_patch(square)
        iniSqu=newPos

anim = animation.FuncAnimation(fig, animate(south),init_func=initDesk(),repeat=True)

plt.show()

This is my output

Suggestions about what could fix the problem and get the patch animated instead of get plotted n times on the same figure?

Upvotes: 1

Views: 1019

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339230

You misunderstood the way FuncAnimation works. Its signature is

FuncAnimation(figure, func, frames, ...)

where func is the function that gets repeatedly called and frames is a number, list or array, or a generator.

The function func is called for each time step with a new argument according to frames. In your code above the function already does everything for each call, which is of course undesired. Instead it should do something different for every call.

Further, you should not call the function yourself, but only provide it to the FuncAnimaton class, which will then call it. So it's really FuncAnimation(figure, func, frames, ...) and not FuncAnimation(figure, func(something), frames, ...)

To make the animation such that the square moves southwards four times, frames would then be a list like frames = [south, south, south, south].

import matplotlib.pyplot as plt
import matplotlib.patches as ptc
from matplotlib import animation
import numpy as np

fig = plt.figure()
ax1 = fig.add_subplot(111,aspect='equal')

ax1.set_xlim((0,10))
ax1.set_ylim((0,10))

desk=np.matrix([[1,1],[9,1],[9,9],[1,9]]) #desk vertices
#SQUARE
squVer=np.matrix([[4.5,6.5],[5.5,6.5],[5.5,7.5],[4.5,7.5]]) #square vertices
iniSqu=[squVer]

move=1
null=0
#4DIRECTIONS
north=np.array(([+null,+move]))
south=np.array([+null,-move])
est=np.array([+move,+null])
west=np.array([-move,+null])

deskpoly = [ptc.Polygon(desk, closed=True, fill=False, hatch="/")]
squarepoly = [ptc.Polygon(iniSqu[0], closed=True, facecolor="blue")]

def initDesk():
    ax1.clear()
    ax1.set_xlim((0,10))
    ax1.set_ylim((0,10))
    iniSqu[0] = squVer
    ax1.add_patch(deskpoly[0])
    ax1.add_patch(squarepoly[0])

def animate(direction):
    iniSqu[0] = iniSqu[0] + direction
    squarepoly[0].remove()
    squarepoly[0] = ptc.Polygon(iniSqu[0], closed=True, facecolor="blue")
    ax1.add_patch(squarepoly[0])

frames = (south, south, south, south)
anim = animation.FuncAnimation(fig, animate, frames=frames, init_func=initDesk,repeat=True)

plt.show()

enter image description here

Upvotes: 2

Related Questions