def create_boids(dims): if dims == 3: bb = BigBoids( num_big_boids=1, dimensions=3, start_center=[1.6, 1.6, 0.5], max_velocity2= 0.001, # avoids ever-increasing velocity that causes it to escape the screen approach_factor=0.001 # velocity at which it approaches the boids ) b = Boids( num_boids=1000, big_boids=bb, dimensions=3, start_center=[0.1, 0.1, 0.5], rule1_factor=0.0003, # factor for going to the common center rule2_threshold=0.005, # threshold for birds being close rule2_factor= 0.08, # speed at which close birds should move outside the threshold rule3_factor= 0.04, # factor for going at the same velocity as average escape_threshold=0.03, # threshold for a big bird being close max_velocity2= 0.001, # avoids ever-increasing velocity that causes boids to escape the screen rule_direction=0.003 # factor for going to a random direction ) else: bb = BigBoids( num_big_boids=1, dimensions=2, start_center=[1.6, 1.6], max_velocity2= 0.0009, # avoids ever-increasing velocity that causes it to escape the screen approach_factor=0.001 # velocity at which it approaches the boids ) b = Boids( num_boids=1000, big_boids=bb, dimensions=2, start_center=[0.1, 0.1], rule1_factor=0.0003, # factor for going to the common center rule2_threshold=0.001, # threshold for birds being close rule2_factor= 0.08, # speed at which close birds should move outside the threshold rule3_factor= 0.06, # factor for going at the same velocity as average escape_threshold=0.01, # threshold for a big bird being close max_velocity2= 0.0008, # avoids ever-increasing velocity that causes boids to escape the screen rule_direction=0.003 # factor for going to a random direction ) bb.set_boids(b) return (b, bb)
def test_Boids(): maxlim = 100 minlim = -100 lims = [minlim,maxlim] for boid_count in (10, 2): boidobject = Boids(boid_count=boid_count,x_positions=lims) assert_equals(boidobject.boids_x.size, boid_count) assert_equals(boidobject.boids_y.size, boid_count) assert_equals(boidobject.boid_x_velocities.size, boid_count) assert_equals(boidobject.boid_y_velocities.size, boid_count) assert (boidobject.boids_x>=minlim).all() and (boidobject.boids_x<=maxlim).all() with assert_raises(ValueError): boidobject = Boids(boid_count=-2)
def create_boids_3D(nboids=1000, nbig=1, use_process=False): bb = BigBoids( num_big_boids=nbig, dimensions=3, start_center=[-1.0, -1.0, 0.0], max_velocity2= 1.0, # avoids ever-increasing velocity that causes it to escape the screen approach_factor=1.0, # velocity at which it approaches the boids dt=dt) b = Boids( num_boids=nboids, big_boids=bb, dimensions=3, start_center=[0.5, 0.5, 0.5], rule1_factor=1.9, # factor for going to the common center rule2_threshold=0.01, # threshold for birds being close rule2_factor= 5.0, # speed at which close birds should move outside the threshold rule3_factor=8.0, # factor for going at the same velocity as average escape_threshold=0.014, # threshold for a big bird being close min_velocity2=0.2, # avoids too much passivity max_velocity2= 1.0, # avoids ever-increasing velocity that causes boids to escape the screen rule_direction=1.0, # factor for going to a random direction bounds_factor=1.1, dt=dt, num_neighbors=60, # escape_factor = 0.3, enforce_bounds=True, in_random_direction=False, use_global_velocity_average=False, use_process=use_process) bb.set_boids(b) return (b, bb)
def test_avoid_collissions(): new_flock = Boids(2, config_filename) new_flock.positions[0][0] = 0 new_flock.positions[1][0] = 0 new_flock.positions[0][1] = 1 new_flock.positions[1][1] = 0 new_flock.velocities[0][0] = 0 new_flock.velocities[0][1] = 0 new_flock.velocities[1][0] = 0 new_flock.velocities[1][1] = 0 old_velocities_x1 = new_flock.velocities[0][0] old_velocities_x2 = new_flock.velocities[0][1] old_velocities_y1 = new_flock.velocities[1][0] old_velocities_y2 = new_flock.velocities[1][1] new_flock.avoid_collisions() print new_flock.velocities assert (old_velocities_x1 > new_flock.velocities[0][0]) assert (old_velocities_x2 < new_flock.velocities[0][1]) assert (old_velocities_y1 == 0) assert (old_velocities_y2 == 0)
def test_fly_towards_middle(): new_flock = Boids(2, config_filename) # Set initial positions new_flock.positions[0][0] = 0 new_flock.positions[1][0] = 0 new_flock.positions[0][1] = 0 new_flock.positions[1][1] = 10 new_flock.velocities[0][0] = 0 new_flock.velocities[0][1] = 0 new_flock.velocities[1][0] = 0 new_flock.velocities[1][1] = 0 old_position_x1 = new_flock.positions[0][0] old_position_x2 = new_flock.positions[0][1] old_position_y1 = new_flock.positions[1][0] old_position_y2 = new_flock.positions[1][1] old_velocities_x1 = new_flock.velocities[0][0] old_velocities_x2 = new_flock.velocities[0][1] old_velocities_y1 = new_flock.velocities[1][0] old_velocities_y2 = new_flock.velocities[1][1] new_flock.fly_to_middle() assert (old_velocities_x1 == new_flock.velocities[0][0]) assert (old_velocities_x2 == new_flock.velocities[0][1]) assert (old_velocities_y1 < new_flock.velocities[1][0]) assert (old_velocities_y2 > new_flock.velocities[1][1])
def test_match_speed( ): # Check that velocities match. Should change in y-direction but stay constant in x-direction for input values. new_flock = Boids(2, config_filename) new_flock.positions[0][0] = 0 new_flock.positions[1][0] = 10 new_flock.positions[0][1] = 0 new_flock.positions[1][1] = 10 new_flock.velocities[0][0] = 0 new_flock.velocities[0][1] = 0 new_flock.velocities[1][0] = 0 new_flock.velocities[1][1] = 10 old_velocities_x1 = new_flock.velocities[0][0] old_velocities_x2 = new_flock.velocities[0][1] old_velocities_y1 = new_flock.velocities[1][0] old_velocities_y2 = new_flock.velocities[1][1] new_flock.match_velocity() assert (old_velocities_x1 == new_flock.velocities[0][0]) assert (old_velocities_x2 == new_flock.velocities[0][1]) assert (old_velocities_y1 < new_flock.velocities[1][0]) assert (old_velocities_y2 > new_flock.velocities[1][1])
def test_new_flock(): boids = Boids() array = boids.new_flock(np.array([0, 50]), np.array([50, 100])) x_array = array[0, :] y_array = array[1, :] assert_equals(array.shape, (2, 50)) assert_true((x_array > 0).all() and (x_array < 50).all()) assert_true((y_array > 50).all() and (y_array < 100).all())
def test_bad_boids_regression(): regression_data = yaml.load( open(os.path.join(os.path.dirname(__file__), 'fixtures', 'fixture.yml'))) boid_data = np.array(regression_data["before"]) Boids().update_boids(boid_data) after_data = np.array(regression_data["after"]) for after, before in zip(after_data, boid_data): for after_value, before_value in zip(after, before): np.testing.assert_almost_equal(after_value, before_value)
def test_animate(): with patch.object(Boids, 'update_boids') as mock_get: new_flock = Boids(2, config_filename) """new_flock.positions[0][0] = 0 new_flock.positions[1][0] = 0 new_flock.positions[0][1] = 1 new_flock.positions[1][1] = 0""" new_flock.animate() print mock_get.mock_calls mock_get.assert_called_with()
def test_fly_away_from_nearby_boids(): data = yaml.load( open(os.path.join(os.path.dirname(__file__), 'fixtures', 'fixture_fly_away_from_nearby_boids.yml'))) boid_data_before = np.array(data["before"]) boid_data_after = np.array(data["after"]) alert_distance = data["alert_distance"] boids = Boids() boids.boids = boid_data_before boids.fly_away_from_nearby_boids(boids.boids, alert_distance) np.testing.assert_array_almost_equal(boids.boids, boid_data_after)
def test_fly_towards_the_middle(): data = yaml.load(open(os.path.join(os.path.dirname(__file__), 'fixtures', 'fixture_fly_towards_the_middle.yml'))) boid_data_before = np.array(data["before"]) boid_data_after = np.array(data["after"]) move_to_middle_strength = data["move_to_middle_strength"] boids = Boids() boids.boids = boid_data_before boids.fly_towards_the_middle(boids.boids, move_to_middle_strength) np.testing.assert_array_almost_equal(boids.boids, boid_data_after)
def test_match_speed_with_nearby_boids(): data = yaml.load( open(os.path.join(os.path.dirname(__file__), 'fixtures', 'fixture_match_speed_with_nearby_boids.yml'))) boid_data_before = np.array(data["before"]) boid_data_after = np.array(data["after"]) formation_flying_distance = data["formation_flying_distance"] formation_flying_strength = data["formation_flying_strength"] boids = Boids() boids.boids = boid_data_before boids.match_speed_with_nearby_boids(boids.boids, formation_flying_distance, formation_flying_strength) np.testing.assert_array_almost_equal(boids.boids, boid_data_after)
def test_update_boids(): data = yaml.load(open(os.path.join(os.path.dirname(__file__), 'fixtures', 'fixture_update_boids_only.yml'))) boid_data_before = np.array(data["before"]) boid_data_after = np.array(data["after"]) boid_count = data["boid_count"] boids = Boids(boid_count=boid_count) boids.boids = boid_data_before with patch.object(boids, 'fly_towards_the_middle') as mocked1: with patch.object(boids, 'fly_away_from_nearby_boids') as mocked2: with patch.object(boids, 'match_speed_with_nearby_boids') as mocked3: boids.update_boids(boids.boids) np.testing.assert_almost_equal(boids.boids, boid_data_after)
def test_separation(): data = yaml.load(open(os.path.join(os.path.dirname(__file__), 'fixtures', 'fixture_separation.yml'))) xcoords = np.array(data["xcoords"]) ycoords = np.array(data["ycoords"]) x_separation = np.array(data["x_separation"]) y_separation = np.array(data["y_separation"]) separation_distance_squared = np.array(data["separation_distance_squared"]) boids = Boids(boid_count=data["boid_count"]) calc_separations, calc_separation_distance_squared = boids.separation((xcoords, ycoords)) np.testing.assert_array_almost_equal(calc_separations, (x_separation, y_separation)) np.testing.assert_array_almost_equal(calc_separation_distance_squared, separation_distance_squared)
def main(): _ROOT = os.path.abspath(os.path.dirname(__file__)) defaultconfig = os.path.join(_ROOT, 'config.yml') parser = ArgumentParser(description="Boid Flocking Modelling") parser.add_argument('--config', default=defaultconfig, help="Configuration file", metavar="FILE") parser.add_argument('--saveto', help="Filename to save animation", metavar="FILE") args = parser.parse_args() try: with open(args.config, 'r') as ymlfile: configdata = yaml.load(ymlfile) boid_count = configdata['Boids_Setup']['boid_count'] x_positions = configdata['Boids_Setup']['x_positions'] y_positions = configdata['Boids_Setup']['y_positions'] x_velocities = configdata['Boids_Setup']['x_velocities'] y_velocities = configdata['Boids_Setup']['y_velocities'] move_to_middle_strength = configdata['Flock_Dynamics']['move_to_middle_strength'] alert_distance = configdata['Flock_Dynamics']['alert_distance'] formation_flying_distance = configdata['Flock_Dynamics']['formation_flying_distance'] formation_flying_strength = configdata['Flock_Dynamics']['formation_flying_strength'] xlim = configdata['Axis_Limits']['xlim'] ylim = configdata['Axis_Limits']['ylim'] frames = configdata['Animation']['frames'] interval = configdata['Animation']['interval'] saveto = args.saveto #works even if it is None boidsobject = Boids(boid_count=boid_count, x_positions=x_positions, y_positions=y_positions, x_velocities=x_velocities, y_velocities=y_velocities, move_to_middle_strength=move_to_middle_strength, alert_distance=alert_distance, formation_flying_distance=formation_flying_distance, formation_flying_strength=formation_flying_strength) boidsobject.model(xlim=xlim, ylim=ylim, frames=frames, interval=interval, savefile=saveto) except IOError as error: print('IOError: No such config file') except KeyError as error: print('KeyError: Missing parameters in config file')
def boid(config_name='config.yaml'): config = yaml.load( open(os.path.join(os.path.dirname(__file__), config_name))) flock_1 = Boids( Boids_total=config['boid_count'], dimension_limits=config['dimension_limits'], velocity_limits=config['velocity_limits'], Limits=config['Limits'], move_to_middle_strength=config['move_to_middle_strength'], alert_distance=config['alert_distance'], formation_flying_distance=config['formation_flying_distance'], formation_flying_strength=config['formation_flying_strength'], frames=config['frames'], interval=config['interval']) flock_1.show_sim()
def main(): parser = ArgumentParser(description="A simulation of a flock of birds.") parser.add_argument('--config', '-c', default='config.cfg', help='select config file') arguments = parser.parse_args() config = ConfigParser.ConfigParser() with open(arguments.config) as config_file: config.readfp(config_file) no_of_boids = config.getint('boids_initiate', 'no_of_boids') position_limits = json.loads( config.get('boids_initiate', 'position_limits')) velocity_limits = json.loads( config.get('boids_initiate', 'velocity_limits')) move_to_middle_strength = config.getfloat('boids_initiate', 'move_to_middle_strength') alert_distance = config.getfloat('boids_initiate', 'alert_distance') formation_flying_distance = config.getfloat( 'boids_initiate', 'formation_flying_distance') formation_flying_strength = config.getfloat( 'boids_initiate', 'formation_flying_strength') xlim = json.loads(config.get('run_simulation', 'xlim')) ylim = json.loads(config.get('run_simulation', 'ylim')) frames = config.getint('run_simulation', 'frames') interval = config.getint('run_simulation', 'interval') boids = Boids(no_of_boids=no_of_boids, position_limits=position_limits, velocity_limits=velocity_limits, move_to_middle_strength=move_to_middle_strength, alert_distance=alert_distance, formation_flying_distance=formation_flying_distance, formation_flying_strength=formation_flying_strength) boids.run_simulation(xlim=tuple(xlim), ylim=tuple(ylim), frames=frames, interval=interval)
def test_bad_boids_regression(): # open(os.path.join(os.path.dirname(__file__),'boids.py')) config_filename = os.path.join(os.path.dirname(__file__), 'fixtures/config.yaml') regression_data = yaml.load( open(os.path.join(os.path.dirname(__file__), 'fixtures/fixture.yaml'))) boids = Boids(10, config_filename) boid_data = np.asarray(regression_data["before"]) boids.positions = np.array([boid_data[0], boid_data[1]]) boids.velocities = np.array([boid_data[2], boid_data[3]]) boids.update_boids() new_boid_data = np.asarray(regression_data["after"]) new_positions = np.asarray([new_boid_data[0], new_boid_data[1]]) new_velocities = np.asarray([new_boid_data[2], new_boid_data[3]]) new_boids = (new_positions, new_velocities) for after, before in zip(new_positions, boids.positions): for after_value, before_value in zip(after, before): assert_almost_equal(after_value, before_value, delta=0.06)
def process(): parser = ArgumentParser(description='Simulate boids') parser.add_argument('boid_no', type=int, help='Number of boids') parser.add_argument('config_file', help='Configuration file') parser.add_argument('--example_view', '-ex', help='View config file example', action='store_true') #parser.add_argument('--generate_example', '-gen', type = str, help = 'Generate config.yaml example file in current directory.') #parser.add_argument('--save', '-s', type =str, help = 'Save animation as .mp4 file. Input is the filename.') arguments = parser.parse_args() # print 'Boids -- Simulating animal flocking behaviour. \n Input -h for help. ' #gen = (x for x in args_iterate if type(x) == None) #for x in gen: if arguments.example_view: print 'The following is an example yaml config file. Copy the test below and past it into a file called filename.yaml. Make sure that the indentation is preserved. \n \n - position: \n \t xmin: ' "-450" ' \n \t xmax: "50" \n \t ymin: "300" \n \t ymax: "600" \n \n - velocity: \n \t vxmin: "0" \n \t vxmax: "10" \n \t vymin: "-20"\n \t vymax: "20"' quit() """ if arguments.generate_example: __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) if not os.path.exists(__location__ + arguments.generate_example): os.makedirs(path) quit() """ new_flock = Boids(arguments.boid_no, arguments.config_file) anim = animation.FuncAnimation(new_flock.figure, new_flock.animate, frames=50, interval=50) plt.show() """
import yaml from boids import Boids from copy import deepcopy import numpy as np boids = Boids() before = deepcopy(boids.boids) move_to_middle = 0.01 boids.fly_towards_the_middle(boids.boids, move_to_middle) after = boids.boids fixture = { "before": np.array(before).tolist(), "after": np.array(after).tolist(), "move_to_middle_strength": move_to_middle } fixture_file = open("fixture_fly_towards_the_middle.yml", 'w') fixture_file.write(yaml.dump(fixture)) fixture_file.close() boids = Boids() before = deepcopy(boids.boids) alert_distance = 100 boids.fly_away_from_nearby_boids(boids.boids, alert_distance) after = boids.boids fixture = { "before": np.array(before).tolist(), "after": np.array(after).tolist(), "alert_distance": alert_distance } fixture_file = open("fixture_fly_away_from_nearby_boids.yml", 'w')
# Python libraries import time # Code from local files from boids import Boids # ----------------------------------- setup ----------------------------------- num_points = 100 max_neighbour_dist = 100 world_size = [0, 1000, 0, 1000] boids = Boids(num_points, world_size, max_neighbour_dist) boids.generate_members() openmp_threads = 1 # ------------------------------------ main ----------------------------------- print('Comparing cython implementations of the linear search nearest ' 'neighbour algorithm') print(f'Finding the neighbours of {num_points} generated points...') print('Execution time for make_neighbourhoods function, pure python linear ' 'search algorithm:') START = time.time() boids.make_neighbourhoods() elapsed = time.time() - START print(f'\t {elapsed*1000:0.2f} ms') print('Execution time for make_neighbourhoods_cython function, cythonised ' 'linear search algorithm:')
def test_initialise(): with patch.object(numpy.random, 'rand') as mock_get: new_flock = Boids(10, config_filename) print mock_get.mock_calls mock_get.assert_called_with(2, 10)
def test_bad_input_file(): with assert_raises(IOError) as exception: new_flock = Boids(10, 'file_that_does_not_exist')
if __name__ == '__main__': print("Starting boids.") parser = argparse.ArgumentParser( description="Implementing Craig Reynold's Boids.") # adding arguments parser.add_argument('--num-boids', dest='N', required=False) args = parser.parse_args() N = 100 if args.N: N = int(args.N) boids = Boids(N) fig = plt.figure() ax = plt.axes(xlim=(0, width), ylim=(0, height)) # plt.plot([300,20],[300,50]) body, = ax.plot([], [], markersize=10, c='k', marker='o', ls='None') head, = ax.plot([], [], markersize=4, c='r', marker='o', ls='None') ani = animation.FuncAnimation(fig, tick, fargs=(body, head, boids), interval=50) # cid = fig.canvas.mpl_connect('button_press_event', boids.button_press) plt.show()
def test_negative_boid_no(): with assert_raises(ValueError) as exception: new_flock = Boids(-10, config_filename)
def test_zero_boids(): with assert_raises(ValueError) as exception: new_flock = Boids(0, config_filename)
def test_wrong_boid_no_type(): with assert_raises(TypeError) as exception: new_flock = Boids('string', config_filename)
# File to capture fixtures from boids import Boids import copy import yaml import numpy as np import os filename = os.path.join(os.path.dirname(__file__), 'new_fixtures.yaml') #yaml.load(open(filename)) new_flock = Boids(10, 'config.yaml') old_positions = copy.deepcopy(new_flock.positions) old_velocities = copy.deepcopy(new_flock.velocities) with open(filename, "w") as f: yaml.dump(old_positions, f, default_flow_style=True) yaml.dump(old_velocities, f, default_flow_style=True) doc = yaml.load(open(filename)) print doc #npzfile = np.load('new_fixtures.npz') #np.save(npzfile, old_positions) #np.save('new_fixtures.yml', old_velocities) #test = np.load('new_fixtures.npz')
matplotlib.use('agg') import numpy as np import rendermpl from boids import Boids from rules import Separation, Alignment, Cohesion, Drag N = 400 dims = 2 boids = Boids( N, dims=dims, rules=[ Separation(.1, 1), #Drag(.5), Alignment(.1, 4), Cohesion(.1, 4), ]) #xx, yy = np.meshgrid(np.linspace(0,1,20), np.linspace(0,1,20)) #boids.velocity[(yy<.5).ravel(),0] = 1 #boids.velocity[(yy>=.5).ravel(),0] = -1 #boids.position = np.random.random((N,dims)).astype(float) boids['position'] = np.random.random((N, dims)).astype(float) boids['velocity'][boids['position'][:, 1] < 0.5, 0] = 1 boids['velocity'][boids['position'][:, 1] <= 0.5, 0] = -1
# ----------------------------------------------------------------------------- # Setup world num_boids = 1000 WORLD_SIZE = [0, options['world_width'], 0, options['world_height']] world = World(WORLD_SIZE) filename = f"{num_boids}_plot.png" # Setup plot NUM_COLOURS = options['num_colours'] cmap = plotting.ColourMap(options) plot = plotting.Plotter(options, world) # Setup Boids boids = Boids(num_boids, world, options) boids.generate_boids(options, distribution='random') # ----------------------------------------------------------------------------- def triang_ver(): boids.triangulate_boids() boids.make_neighbourhoods() # ----------------------------------- Main ------------------------------------ triang_ver() for i in range(num_boids):