2

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.

Ente
  • 2,301
  • 1
  • 16
  • 34
JulioHC
  • 23
  • 4

1 Answers1

2

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()
Ente
  • 2,301
  • 1
  • 16
  • 34
  • I've tested code with `blit=True` but it changes nothing - there is still a series of points on the plot as result. – ipj Jul 23 '20 at 20:31
  • my examples with `blit=True` work for me with Python 3.8.3, IPython 7.16.1, matplotlib 3.2.1. Have you tried running them as-is? – Ente Jul 23 '20 at 20:36
  • 1
    Yes, however to see animation in Jupyter Notebook I always add `%matplotlib notebook` at the top of script. Method that works for me is in the accepted answer of https://stackoverflow.com/questions/35521545/animation-moving-point-error – ipj Jul 23 '20 at 20:41
  • glad you found an answer. – Ente Jul 23 '20 at 20:43
  • Yes, but solution with blit seems to be more compact. My versions: (Python 3.7.7 IPython 7.13.0 matplotlib 3.1.3) I'm curious if it works for @JulioHC – ipj Jul 23 '20 at 20:50
  • Sorry it took so long to answer. I does work! I'm just having some issues now but seem to be related to an update of spyder because code that worked yesterday is no longer working. – JulioHC Jul 24 '20 at 15:53