superDuck
superDuck

Reputation: 309

How to stop FuncAnimation by func in matplotlib?

I write a matplotlib animation program like this:

def animate(frame):
    observation = env.render()
    action = RL.choose_action(str(observation)) # TODO
    action = [random.randint(0, 4) for i in range(ROBOT_NUM)] # TO BE DELETE TODO
    env.step(action)
    observation_ = env.render()
    reward = env.reward
    RL.learn(str(observation), action, reward, str(observation_))  # TODO
    for i in range(TARGET_NUM):
        patchs_target[i].center = (env.targets[i].x, env.targets[i].y)
    for i in range(ROBOT_NUM):
        patchs[i].center = (env.robots[i].x, env.robots[i].y)
        patchs_inner[i].center = (env.robots[i].x, env.robots[i].y)
    return patchs + patchs_inner + patchs_target

.....

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

Now I want to stop animation.FuncAnimation by judge a condition in animate function. Such as if reward < 10 then stop animation.FuncAnimation, but I have no idea how to deal with it.
Or if there are any method to stop animation.FuncAnimation by condition? not by animation times.

Upvotes: 11

Views: 11744

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339340

Two options:

(1) Using a generator

In order to steer the animation dynamically you may use a generator, which yields new values in a while loop as long some condition is fulfilled. This could look as follows:

reward = 0

def gen():
    global reward
    i = 0
    while reward <= 10:
        i += 1
        yield i

def animate(i):
    global reward
    reward = update(reward)
    some_object[i] = func(reward)
    return some_object

anim = animation.FuncAnimation(fig, animate, frames=gen, repeat = False)

(2) Using a class with event_source.stop().

Alternatively you may stop the animation with anim.event_source.stop(). In order to have access to the animation inside the animating function one may use a class and make the animation a class variable.

class Anim():
    def __init__(self, fig, **kw):
        self.reward=0
        self.ani = animation.FuncAnimation(fig, self.animate, 
                                           frames=100, repeat = False) 

    def animate(self,i):
        reward = update(reward)
        some_object[i] = func(reward)
        if self.reward > 10:
            self.ani.event_source.stop()
        return some_object

Note that both codes are untested because the question does not provide a test case.

Upvotes: 21

Related Questions