Search code examples
pythonpython-3.xmatplotlibmatplotlib-animation

Why is a point not moving when plotting using FuncAnimation?


I'm trying to simulate from scratch the motion of a planet in a binary star system. For this I need to be able to plot points in an animated graph. Before coding the whole thing, I'm learning to animate a plot using pyplot. So far I haven't had any luck animating a moving point. After looking at several tutorials and at the documentation this what I've got:

import matplotlib
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
ax.set_xlim(0,2)
ax.set_ylim(0,2)
line, = plt.plot(0,0,'bo')
def animation(i):
    x=np.linspace(0,2,100)
    y=np.linspace(0,1,100)
    line.set_data(x[i],y[i],'bo')
    return line,
FuncAnimation(fig, animation, frames=np.arange(100),interval=10)
plt.show()

However the output of this code is just a point at 0,0 and I don't understand what I may be doing wrong.


Solution

  • For your example to work you have to change two things:

    1. Store the return value from FuncAnimation somewhere. Otherwise your animation gets deleted before the plt.show().
    2. If don't want to draw a line but just dots, use plt.plot in animation
    from matplotlib.animation import FuncAnimation
    import matplotlib.pyplot as plt
    import numpy as np
    fig, ax = plt.subplots()
    ax.set_xlim(0,2)
    ax.set_ylim(0,2)
    line, = plt.plot(0,0,'bo')
    def animation(i):
        x=np.linspace(0,2,100)
        y=np.linspace(0,1,100)
        plt.plot(x[i],y[i],'bo')
        return line,
    
    my_animation=FuncAnimation(fig, animation, frames=np.arange(100),interval=10)
    plt.show()
    

    If you want to just have one moving point on the graph, you have to set blit=True and return the result from plot.plot in animation:

    from matplotlib.animation import FuncAnimation
    import matplotlib.pyplot as plt
    import numpy as np
    fig, ax = plt.subplots()
    ax.set_xlim(0,2)
    ax.set_ylim(0,2)
    line, = plt.plot(0,0,'bo')
    def animation(i):
      x=np.linspace(0,2,100)
      y=np.linspace(0,1,100)
      return plt.plot(x[i],y[i],'bo')
    
    my_animation=FuncAnimation(
        fig,
        animation,
        frames=np.arange(100),
        interval=10,
        blit=True
    )
    plt.show()
    

    Also you probably want to get rid of the point at (0,0) and you don't want to compute x and y for every animation frame:

    from matplotlib.animation import FuncAnimation
    import matplotlib.pyplot as plt
    import numpy as np
    
    fig, ax = plt.subplots()
    
    ax.set_xlim(0,2) 
    ax.set_ylim(0,2) 
    
    x=np.linspace(0,2,100) 
    y=np.linspace(0,1,100) 
    
    def animation(i):
      return plt.plot(x[i], y[i], 'bo')
    
    my_animation=FuncAnimation(
        fig,
        animation,
        frames=np.arange(100),
        interval=10,
        blit=True
    )
    plt.show()