'Is there a way to iteratively add plots to Animation.FuncAnimation()?

I'm working on my master thesis right now and need to animate a high number of points moving. Those points will be representing predators and prey. The number of predators and preys should be changeable and probably around 500 each. For now i hard coded the animation function with 3 predators and 1 prey. is there a way to do it iteratively (e.g for 500 predators and 200 preys)?

EDIT: In google colab the animation is stretched is there a way to make it a proper square?

Thanks in advance!

My code so far (just have random movement for p&p so code is smaller):

import matplotlib
import random

import numpy as np
from matplotlib import pyplot
from matplotlib import animation
from matplotlib import rc
rc('animation', html='jshtml')

max_t=200                 # max experiment time
num_pred = 3              # number of predators
num_prey = 1              # number of prey

pred_pos = np.zeros((2*num_pred, max_t))        # initializing x and y positions for pred based on time
prey_pos = np.zeros((2*num_prey, max_t))        # initializing x and y positions for prey based on time
# [pred1_x1, pred1_x2, pred1_x3,...
#  pred1_y1, pred1_y2, pred1_y3,...
#  pred2_x1, pred2_x2, pred2_x3,...
#  pred2_y1, pred2_y2, pred2_y3,...]


for i in range(2*num_pred):
  pred_pos[i][0] = pred_pos[i][0] + random.uniform(-1, 1)
  for j in range(max_t-1):
    pred_pos[i][j] = pred_pos[i][j-1] + random.uniform(-1, 1)       # random movement

for i in range(2*num_prey):
  prey_pos[i][0] = prey_pos[i][0] + random.uniform(-1, 1)
  for j in range(max_t-1):
    prey_pos[i][j] = prey_pos[i][j-1] + random.uniform(-1, 1)

#print(pred_pos)
#print(prey_pos)


fig=pyplot.figure()
ax = pyplot.axes(xlim=(-10, 10), ylim=(-10, 10))

pred_circle1=pyplot.Circle((pred_pos[0,0],pred_pos[1,0]),0.3,fc='b')
pred_circle2=pyplot.Circle((pred_pos[2,0],pred_pos[3,0]),0.3,fc='b')
pred_circle3=pyplot.Circle((pred_pos[4,0],pred_pos[5,0]),0.3,fc='b')

prey_circle1=pyplot.Circle((prey_pos[0,0],prey_pos[1,0]),0.3,fc='r')


def init():
    pred_circle1.center=(pred_pos[0,0],pred_pos[1,0])       # pred_circle1.center=(x,y)
    pred_circle2.center=(pred_pos[2,0],pred_pos[3,0])
    pred_circle3.center=(pred_pos[4,0],pred_pos[5,0])
    prey_circle1.center=(prey_pos[0,0],prey_pos[1,0])
    ax.add_patch(pred_circle1)
    ax.add_patch(pred_circle2)
    ax.add_patch(pred_circle3)
    ax.add_patch(prey_circle1)
    return pred_circle1, pred_circle2, pred_circle3, prey_circle1,

def animate(i):
    pred_circle1.center=(pred_pos[0,i],pred_pos[1,i])
    pred_circle2.center=(pred_pos[2,i],pred_pos[3,i])
    pred_circle3.center=(pred_pos[4,i],pred_pos[5,i])
    prey_circle1.center=(prey_pos[0,i],prey_pos[1,i])
    return pred_circle1, pred_circle2, pred_circle3, prey_circle1,


anim=animation.FuncAnimation(fig,animate, init_func=init,frames=max_t,blit=True)

anim


Solution 1:[1]

One way to achieve it is by knowing that your first add all the predators, then all the preys. So, ax.patches contains an ordered list of patches, and you can loop over them to update their positions:

import matplotlib
import random

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

max_t=200                 # max experiment time
num_pred = 15              # number of predators
num_prey = 4              # number of prey

pred_pos = np.zeros((2*num_pred, max_t))        # initializing x and y positions for pred based on time
prey_pos = np.zeros((2*num_prey, max_t))        # initializing x and y positions for prey based on time
# [pred1_x1, pred1_x2, pred1_x3,...
#  pred1_y1, pred1_y2, pred1_y3,...
#  pred2_x1, pred2_x2, pred2_x3,...
#  pred2_y1, pred2_y2, pred2_y3,...]


for i in range(2*num_pred):
    pred_pos[i][0] = pred_pos[i][0] + random.uniform(-1, 1)
    for j in range(max_t-1):
        pred_pos[i][j] = pred_pos[i][j-1] + random.uniform(-1, 1)       # random movement

for i in range(2*num_prey):
    prey_pos[i][0] = prey_pos[i][0] + random.uniform(-1, 1)
    for j in range(max_t-1):
        prey_pos[i][j] = prey_pos[i][j-1] + random.uniform(-1, 1)


fig=pyplot.figure()
ax = pyplot.axes(xlim=(-10, 10), ylim=(-10, 10))

# add an arbitrary number of preys and predators
for i in range(num_pred):
    p = pyplot.Circle((pred_pos[2 * i, 0], pred_pos[2 * i + 1, 0]),0.3,fc='b')
    ax.add_patch(p)
for i in range(num_prey):
    p = pyplot.Circle((prey_pos[2 * i, 0], prey_pos[2 * i + 1, 0]),0.3,fc='r')
    ax.add_patch(p)

def animate(i):
    # update positions
    for k in range(num_pred):
        ax.patches[k].center=(pred_pos[2*k,i],pred_pos[2*k+1,i])
    for k in range(num_prey):
        ax.patches[num_pred + k].center=(prey_pos[2*k,i],prey_pos[2*k+1,i])

anim=animation.FuncAnimation(fig,animate, frames=max_t)
pyplot.show()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Davide_sd