student
student

Reputation: 1646

Matplotlib animation in real time

In the example below I want to make an animation where a point moves around a circle in T seconds (for example T=10). However it is a lot slower and doesn't work. So, what is wrong with my code and how to fix it? As far as I understand the api (http://matplotlib.org/api/animation_api.html) setting interval=1 should update the figure every millisecond.

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation

R = 3
T = 10

fig = plt.figure()
fig.set_dpi(300)
fig.set_size_inches(7, 6.5)

ax = plt.axes(xlim=(-10, 10), ylim=(-R*1.5, R*1.5))
ax.set_aspect('equal')


patch = plt.Circle((0, 0), 0.1, fc='r')
looping = plt.Circle((0,0),R,color='b',fill=False)
ax.add_artist(looping)
time_text = ax.text(-10,R*1.2,'',fontsize=15)

def init():
    time_text.set_text('')
    patch.center = (0, 0)
    ax.add_patch(patch)
    return patch,time_text,


def animate(i):
    t=i/1000.0
    time_text.set_text(t)
    x, y = patch.center
    x = R*np.sin(t/T*2*np.pi)
    y = R*np.cos(t/T*2*np.pi)
    patch.center = (x, y)
    return patch,time_text

slow_motion_factor=1

anim = animation.FuncAnimation(fig, animate, 
                               init_func=init, 
                               frames=10000,
                               interval=1*slow_motion_factor,
                               blit=True)

plt.show()

I should add that the problem depends on the machine where I run the program. For example on a old Intel dualcore (P8700) (that's the box where the program should run), it is considerable slower than on a newer haswell i7 desktop cpu. But in the latter case it is also much slower as intended.

Upvotes: 0

Views: 4836

Answers (1)

MaxNoe
MaxNoe

Reputation: 14987

The problem is, that your computer is not fast enough, to deliver a new image every 1 ms. Which is kind of expected.

You should go for a more realistic speed. 25 frames per second should be enough and also be possible to render in time.

I also made a few adjustment to you code, mostly style and more semantic variable names. The biggest change was adapting this answer to your code to get rid of the first frame being still there after the init: Matplotlib animation: first frame remains in canvas when using blit

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation

R = 3
T = 10
time = 3 * T
slow_motion_factor = 1
fps = 50
interval = 1 / fps

fig = plt.figure(figsize=(7.2, 7.2))
ax = fig.add_subplot(1, 1, 1, aspect='equal')
ax.set_xlim(-1.5 * R, 1.5 * R)
ax.set_ylim(-1.5 * R, 1.5 * R)

runner = plt.Circle((0, 0), 0.1, fc='r')
circle = plt.Circle((0, 0), R, color='b', fill=False)
ax.add_artist(circle)
time_text = ax.text(1.1 * R, 1.1 * R,'', fontsize=15)

def init():
    time_text.set_text('')
    return time_text,


def animate(i):
    if i == 0:
        ax.add_patch(runner)
    t = i * interval
    time_text.set_text('{:1.2f}'.format(t))
    x = R * np.sin(2 * np.pi * t / T)
    y = R * np.cos(2 * np.pi * t / T)
    runner.center = (x, y)
    return runner, time_text

anim = animation.FuncAnimation(
    fig,
    animate,
    init_func=init,
    frames=time * fps,
    interval=1000 * interval * slow_motion_factor,
    blit=True,
)

plt.show()

Upvotes: 1

Related Questions