def launch_two_groups(output_file: str,
                      L: float,
                      n_birds_1: int,
                      n_birds_2: int,
                      radius_1: int,
                      radius_2: int,
                      center_1: list,
                      center_2: list,
                      angle_1: float,
                      angle_2: float,
                      vel: float = 1,
                      ang_vel: float = np.pi / 2,
                      interaction_radius: float = 1,
                      eta: float = .1,
                      dt: float = 1,
                      total_time: float = 100) -> None:
    gridstep = interaction_radius
    sky = Sky(L, gridstep)
    group_1_positions = (np.random.rand(n_birds_1, 2) -
                         .5) * radius_1 + np.array(center_1)
    for i in range(n_birds_1):
        sky.add_bird(Bird(group_1_positions[i], vel, ang_vel, angle_1))
    group_2_positions = (np.random.rand(n_birds_2, 2) -
                         .5) * radius_2 + np.array(center_2)
    for i in range(n_birds_2):
        sky.add_bird(Bird(group_2_positions[i], vel, ang_vel, angle_2))

    physics = Physics(sky, interaction_radius, eta)
    Life.simulate(physics,
                  dt,
                  total_time,
                  verbose_prop=.1,
                  output_file=output_file)
def recreate_frame(frame: List[List], L: float, grid_step: float) -> Sky:
    sky = Sky(L, grid_step)
    for bird in frame:
        pos, angle, vel, ang_vel = bird
        sky.add_bird(Bird(np.array(pos), vel, ang_vel, angle))

    return sky