def test_surrounding_cells_2(): """ Tests that no surrounding cells is returned if all are mountain and ocean """ island = Island("OOO\nOJM\nMMM") island.build_map() cor = island.surrounding_cells((1, 1)) nt.assert_list_equal(cor, [])
def test_surrounding_cells(): """ Test that the function surrounding cells returns the right cells """ island = Island("JJJJJJ\nJJJJJJ\nJJJJJJ\nJJJJJJ\nJJJJJJ\nJJJJJJ") island.build_map() cor = island.surrounding_cells((5, 5)) true = [(4, 5), (5, 4), (5, 6), (6, 5)] for index in range(len(cor)): nt.assert_equal(cor[index], true[index])
def test_animals_must_migrate(self): """ Tests that no animals are left in cell after migration """ Herbivore.set_parameters({"mu": 1}) Carnivore.set_parameters({"mu": 1}) island = Island(self.geogr_simple) island.build_map() island.island[1][1].herbivores = [Herbivore() for _ in range(20)] island.island[1][1].carnivores = [Carnivore() for _ in range(20)] for herb in island.island[1][1].herbivores: herb.fitness = 1 for carn in island.island[1][1].carnivores: carn.fitness = 1 island.migration() nt.assert_equal(island.island[1][1].herbivores, []) nt.assert_equal(island.island[1][1].carnivores, [])
def test_one_year(self): """ tests that attributes changes after a year """ island = Island(self.geogr_simple) island.build_map() Herbivore.set_parameters({"mu": 0}) Carnivore.set_parameters({"mu": 0}) island.island[1][1].herbivores = [Herbivore(40, 5)] island.island[1][1].carnivores = [Carnivore(20, 5)] for carnivore in island.island[1][1].carnivores: carnivore.fitness = 1 for herbivore in island.island[1][1].herbivores: herbivore.fitness = 1 island.one_year() nt.assert_equal(island.island[1][1].herbivores[0].age, 6) nt.assert_equal(island.island[1][1].carnivores[0].age, 6) nt.assert_not_equal(island.island[1][1].herbivores[0].weight, 40) nt.assert_not_equal(island.island[1][1].carnivores[0].weight, 20)
def test_num_animal_is_not_change(self): """ Tests that the total number of animals are the same after migration """ initial_num_animals = 20 island = Island(self.geogr_simple) island.build_map() island.island[1][1].herbivores = [Herbivore() for _ in range(10)] island.island[1][1].carnivores = [Carnivore() for _ in range(10)] for herb in island.island[1][1].herbivores: herb.set_parameters({"mu": 1}) herb.fitness = 1 for carn in island.island[1][1].carnivores: carn.set_parameters({"mu": 1}) carn.fitness = 1 island.migration() total_num_animals = 0 for row in island.individuals(): for cell in row: total_num_animals += (cell["herbivores"] + cell["carnivores"]) nt.assert_equal(total_num_animals, initial_num_animals)
def test_relative_food_updates(self): """ Tests that relative food in surrounding cells are updated after each year """ island = Island(self.geogr_simple) island.build_map() island.island[1][1].herbivores = [Herbivore() for _ in range(10)] island.island[1][1].carnivores = [Carnivore() for _ in range(10)] for herb in island.island[1][1].herbivores: herb.set_parameters({"mu": 1}) herb.fitness = 1 for carn in island.island[1][1].carnivores: carn.set_parameters({"mu": 1}) carn.fitness = 1 initial_relative_food_carn = island.island[1][1].relative_food_herb() initial_relative_food_herb = island.island[1][1].relative_food_carn() island.migration() nt.assert_not_equal(initial_relative_food_carn, island.island[1][1].relative_food_carn()) nt.assert_not_equal(initial_relative_food_herb, island.island[1][1].relative_food_herb())
def test_no_animals_migrate(self): """ Test that nothing change if no animal migrate """ initial_num_animals = 20 island = Island(self.geogr_simple) island.build_map() island.island[1][1].herbivores = [Herbivore() for _ in range(10)] island.island[1][1].carnivores = [Carnivore() for _ in range(10)] for herb in island.island[1][1].herbivores: herb.set_parameters({"mu": 0}) for carn in island.island[1][1].carnivores: carn.set_parameters({"mu": 0}) island.migration() total_animals = len(island.island[1][1].herbivores + island.island[1][1].carnivores) nt.assert_equal(total_animals, initial_num_animals) total_num_animals = 0 for row in island.individuals(): for cell in row: total_num_animals += (cell["herbivores"] + cell["carnivores"]) nt.assert_equal(total_num_animals, initial_num_animals)
def test_death(self): """ Runs multiple times to minimise chance of failure due to all animals surviving. :return: """ original = 40 * 5 new = 0 test = Island(self.geogr_simple) test.build_map() Herbivore.set_parameters({"omega": 1}) Carnivore.set_parameters({"omega": 1}) test.island[1][1].herbivores = [Herbivore() for _ in range(10)] test.island[1][2].herbivores = [Herbivore() for _ in range(10)] test.island[1][1].carnivores = [Carnivore() for _ in range(10)] test.island[1][2].carnivores = [Carnivore() for _ in range(10)] test.death() for _ in range(5): for row in test.island: for cell in row: new += \ cell.number_of_individuals()["herbivores"] + \ cell.number_of_individuals()["carnivores"] nt.assert_less(new, original)
class BioSim(object): """ Class BioSim Main simulation class for biosim project """ def __init__(self, island_map=None, ini_pop=None, seed=None): """ Constructor creates island from given map, and adds initial population to island. All parameters needed to create animals are contained within ini_pop. :param island_map: String containing letters representing each type of landscape :param ini_pop: List of initial_populations. [pop1, pop2] :param seed: Seed for rng """ if seed is not None: np.random.seed(seed) random.seed(seed) else: random.seed(1234) np.random.seed(987654) if island_map is None: island_map = """OOOOOOO OJJSJJO OJSSSJO OJSMSJO OJSMSJO OJJJJJO OOOOOOO""" self.island_map = island_map self.island = Island(self.island_map) self.island.build_map() self.vis_steps = None self.img_steps = None self.years_sim = 0 self.heat = None if ini_pop is None: ini_herbs = [{'loc': (3, 3), 'pop': [{'species': 'Herbivore', 'age': 5, 'weight': 20} for _ in xrange(150)]}] ini_carns = [{'loc': (3, 3), 'pop': [{'species': 'Carnivore', 'age': 5, 'weight': 20} for _ in xrange(40)]}] ini_pop = ini_herbs + ini_carns self.add_population(ini_pop) self.fig = None def add_population(self, population): """ Adds given population to cells. Location stored in given population :param population: list of populations """ for species in population: y, x = [n - 1 for n in species['loc']] for ani in species['pop']: if ani['species'] == 'Herbivore': self.island.island[y][x].herbivores.append(Herbivore( weight=ani['weight'], age=ani['age'], coordinates=(y, x))) elif ani['species'] == 'Carnivore': self.island.island[y][x].carnivores.append(Carnivore( weight=ani['weight'], age=ani['age'], coordinates=(y, x))) @staticmethod def heatmap(island_results): """ Returns two nested lists; [row[cell]], one for herbivore population and one for carnivore population. :param island_results: Array containing population data for one year :return kart_herb, kart_carn: Map over populations """ kart_herb = [] kart_carn = [] for row in island_results: h_row = [] c_row = [] for cell in row: h_row.append(cell["herbivores"]) c_row.append(cell["carnivores"]) kart_herb.append(h_row) kart_carn.append(c_row) return kart_herb, kart_carn def years_simulated(self): """ Prints the total number of years simulated """ if self.years_sim != 0: print 'Number of years simulated: {:5}'.format(self.years_sim) else: raise ValueError('No years have been simulated, run .simulate()!') def per_cell_animal_count(self): """ Prints the total amount of animals in island """ print self.island.individuals() def animal(self): """ Returns total number of animals per type :return anim: Dict of animals per type """ animals = self.island.individuals() herb = 0 carn = 0 for row in animals: for cell in row: herb += cell["herbivores"] carn += cell["carnivores"] anim = {"Herbivores": herb, "Carnivores": carn} return anim def animals_by_species(self): """ Prints number of Animals per type on island """ print self.animal() def total_number_of_animals(self): """ Prints the total number of animals on island """ animals = self.animal() print 'Total number of animals on island: {:4}'.format( animals["Herbivores"] + animals["Carnivores"]) def plot_update(self, years, abscissa, ordinate, colour_herb, colour_carn): """ Updates the plot n_steps years :param years: Number of years to plot :param abscissa: Xrange :param ordinate: Yrange :param colour_herb: Colour of heatmap (default None) :param colour_carn: Colour of heatmap (default None) """ if self.years_sim == 0: self.fig = plt.figure() plt.axis('off') if abscissa is None: abscissa = years # + self.years_sim ax1 = self.fig.add_subplot(2, 2, 1) plt.title('Rossum Island') rgb_value = {'O': (0.0, 0.0, 1.0), 'M': (0.5, 0.5, 0.5), 'J': (0.0, 0.6, 0.0), 'S': (0.5, 1.0, 0.5), 'D': (1.0, 1.0, 0.5)} kart_rgb = [[rgb_value[column] for column in row] for row in self.island_map.replace(" ", "").split()] axlg = self.fig.add_axes([0.0, 0.5, 0.025, 0.5]) axlg.axis('off') for ix, name in enumerate(('Ocean', 'Mountain', 'Jungle', 'Savannah', 'Desert')): axlg.add_patch(plt.Rectangle((0., ix * 0.2), 0.3, 0.1, edgecolor='none', facecolor=rgb_value[name[0]])) axlg.text(0.35, ix * 0.2, name, transform=axlg.transAxes) ax1.imshow(kart_rgb, interpolation='nearest') ax1.set_xticks(range(0, len(kart_rgb[0]), 4)) ax1.set_xticklabels(range(1, 1 + len(kart_rgb[0]), 4)) ax1.set_yticks(range(0, len(kart_rgb), 4)) ax1.set_yticklabels(range(1, 1 + len(kart_rgb), 4)) ax2 = self.fig.add_subplot(2, 2, 2) plt.axis([self.years_sim, self.years_sim + abscissa, self.years_sim, ordinate]) title = plt.title('') line_herbs = ax2.plot(np.arange(years + self.years_sim), np.nan * np.ones(self.years_sim + years), 'g-', label="Herbivores")[0] line_carns = ax2.plot(np.arange(years + self.years_sim), np.nan * np.ones(self.years_sim + years), 'r-', label="Carnivores")[0] if self.years_sim == 0: plt.grid() plt.legend(loc=1, prop={'size': 7}) ax3 = self.fig.add_subplot(2, 2, 3) plt.title("Herbivores") ax3.set_xticks(range(0, len(self.island_map), 2)) ax3.set_xticklabels(range(1, 1 + len(self.island_map), 2)) ax3.set_yticks(range(0, len(self.island_map), 2)) ax3.set_yticklabels(range(1, 1 + len(self.island_map), 2)) ax3_bar = plt.imshow([[0 for _ in range(21)] for _ in range(13)]) if self.years_sim == 0: plt.colorbar(ax3_bar, orientation='horizontal', ticks=[]) ax4 = self.fig.add_subplot(2, 2, 4) plt.title("Carnivores") ax4.set_xticks(range(0, len(self.island_map), 2)) ax4.set_xticklabels(range(1, (1 + len(self.island_map)), 2)) ax4.set_yticks(range(0, len(self.island_map), 2)) ax4.set_yticklabels(range(1, (1 + len(self.island_map)), 2)) ax4_bar = plt.imshow([[0 for _ in range(21)] for _ in range(13)]) if self.years_sim == 0: plt.colorbar(ax4_bar, orientation='horizontal', ticks=[]) for n in xrange(self.years_sim, self.years_sim + years): self.heat = self.heatmap(self.island.one_year()) if n % self.vis_steps == 0: ax3.imshow(self.heat[0], interpolation='nearest', cmap=colour_herb) ax4.imshow(self.heat[1], interpolation='nearest', cmap=colour_carn) herbs = np.sum(self.heat[0]) carns = np.sum(self.heat[1]) ydata_herbs = line_herbs.get_ydata() ydata_carns = line_carns.get_ydata() ydata_herbs[n] = herbs ydata_carns[n] = carns line_herbs.set_ydata(ydata_herbs) line_carns.set_ydata(ydata_carns) title.set_text('Year: {:5}'.format(n + 1)) # Year counter self.fig.savefig( 'img{}{}.png'.format('0' * (5 - len(str(n + self.years_sim ))), n)) if \ (n + 1) % self.img_steps == 0 else None plt.pause(1e-7) if np.sum(self.heat) == 0: break self.years_sim += years def simulate(self, num_steps=100, vis_steps=1, img_steps=2000, abscissa=None, ordinate=20000, colour_herb=None, colour_carn=None): """ Runs simulation num_steps number of years :param num_steps: Number of years to simulate :param vis_steps: Number of years between each time results are drawn :param img_steps: Number of years between each .png file created :param abscissa: Length of x-axis :param ordinate: Length of y-axis :param colour_herb: Colour for chart of herbivore population :param colour_carn: Colour for chart of herbivore population """ self.vis_steps = vis_steps self.img_steps = img_steps self.plot_update(num_steps, abscissa, ordinate, colour_herb, colour_carn) plt.show()
class TestMigration: geogr_simple = """OMO OJD OSO""" def __init__(self): """ Saves parameter values """ self.true_params_jungle = Jungle.params self.true_params_savannah = Savannah.params self.true_params_herbivore = Herbivore.params self.true_params_carnivore = Carnivore.params self.island = None def setup(self): self.island = Island(self.geogr_simple) self.island.build_map() for row in self.island.island: for cell in row: if cell.passable: cell.herbivores = [Herbivore(weight=50) for _ in range(10)] cell.carnivores = [Carnivore(weight=50) for _ in range(10)] def teardown(self): """ Resets parameters to correct values """ Jungle.params = self.true_params_jungle Savannah.params = self.true_params_savannah Herbivore.params = self.true_params_herbivore Carnivore.params = self.true_params_carnivore def test_animals_must_migrate(self): """ Tests that no animals are left in cell after migration """ Herbivore.set_parameters({"mu": 1}) Carnivore.set_parameters({"mu": 1}) island = Island(self.geogr_simple) island.build_map() island.island[1][1].herbivores = [Herbivore() for _ in range(20)] island.island[1][1].carnivores = [Carnivore() for _ in range(20)] for herb in island.island[1][1].herbivores: herb.fitness = 1 for carn in island.island[1][1].carnivores: carn.fitness = 1 island.migration() nt.assert_equal(island.island[1][1].herbivores, []) nt.assert_equal(island.island[1][1].carnivores, []) def test_num_animal_is_not_change(self): """ Tests that the total number of animals are the same after migration """ initial_num_animals = 20 island = Island(self.geogr_simple) island.build_map() island.island[1][1].herbivores = [Herbivore() for _ in range(10)] island.island[1][1].carnivores = [Carnivore() for _ in range(10)] for herb in island.island[1][1].herbivores: herb.set_parameters({"mu": 1}) herb.fitness = 1 for carn in island.island[1][1].carnivores: carn.set_parameters({"mu": 1}) carn.fitness = 1 island.migration() total_num_animals = 0 for row in island.individuals(): for cell in row: total_num_animals += (cell["herbivores"] + cell["carnivores"]) nt.assert_equal(total_num_animals, initial_num_animals) def test_no_animals_migrate(self): """ Test that nothing change if no animal migrate """ initial_num_animals = 20 island = Island(self.geogr_simple) island.build_map() island.island[1][1].herbivores = [Herbivore() for _ in range(10)] island.island[1][1].carnivores = [Carnivore() for _ in range(10)] for herb in island.island[1][1].herbivores: herb.set_parameters({"mu": 0}) for carn in island.island[1][1].carnivores: carn.set_parameters({"mu": 0}) island.migration() total_animals = len(island.island[1][1].herbivores + island.island[1][1].carnivores) nt.assert_equal(total_animals, initial_num_animals) total_num_animals = 0 for row in island.individuals(): for cell in row: total_num_animals += (cell["herbivores"] + cell["carnivores"]) nt.assert_equal(total_num_animals, initial_num_animals) def test_relative_food_updates(self): """ Tests that relative food in surrounding cells are updated after each year """ island = Island(self.geogr_simple) island.build_map() island.island[1][1].herbivores = [Herbivore() for _ in range(10)] island.island[1][1].carnivores = [Carnivore() for _ in range(10)] for herb in island.island[1][1].herbivores: herb.set_parameters({"mu": 1}) herb.fitness = 1 for carn in island.island[1][1].carnivores: carn.set_parameters({"mu": 1}) carn.fitness = 1 initial_relative_food_carn = island.island[1][1].relative_food_herb() initial_relative_food_herb = island.island[1][1].relative_food_carn() island.migration() nt.assert_not_equal(initial_relative_food_carn, island.island[1][1].relative_food_carn()) nt.assert_not_equal(initial_relative_food_herb, island.island[1][1].relative_food_herb()) def test_list_of_coordinates(self): """ Tests that shuffled_list function returns coordinates for all cells on map. """ list_ = self.island.shuffle_coordinates() for row in range(len(self.island.island)): for cell in range(len(self.island.island[row])): nt.assert_in((cell, row), list_) def test_list_is_shuffled(self): """ Tests that the list of coordinate from shuffled_list function is shuffled """ sorted_list = [] shuffled_list = self.island.shuffle_coordinates() for row in range(len(self.island.island)): for cell in range(len(self.island.island[row])): sorted_list.append((row, cell)) nt.assert_not_equal(shuffled_list, sorted_list) def test_length_surrounding_cells(self): """ Tests that surrounding cells does not give coordinates of ocean or mountain cells """ cell = self.island.surrounding_cells((1, 2)) nt.assert_equal(cell, [(1, 1)]) cells = self.island.surrounding_cells((1, 1)) correct_cells = [(2, 1), (1, 2)] nt.assert_equal(cells, correct_cells)
class TestIsland: geogr_simple = """OMO OJD OSO""" def __init__(self): """ Saves parameter values """ self.true_params_jungle = Jungle.params self.true_params_savannah = Savannah.params self.true_params_herbivore = Herbivore.params self.true_params_carnivore = Carnivore.params self.island = None def setup(self): self.island = Island(self.geogr_simple) self.island.build_map() for row in self.island.island: for cell in row: if cell.passable: cell.herbivores = [Herbivore(weight=50) for _ in range(10)] cell.carnivores = [Carnivore(weight=50) for _ in range(10)] def teardown(self): """ Resets parameters to correct values """ Jungle.params = self.true_params_jungle Savannah.params = self.true_params_savannah Herbivore.params = self.true_params_herbivore Carnivore.params = self.true_params_carnivore def test_map_build(self): """ Test that the island properly allocates cell types according to input """ nt.assert_equal(self.island.island[1][1].__class__.__name__, "Jungle") nt.assert_equal(self.island.island[0][1].__class__.__name__, "Mountain") nt.assert_equal(self.island.island[2][1].__class__.__name__, "Savannah") nt.assert_equal(self.island.island[1][2].__class__.__name__, "Desert") def test_food_growth(self): """ Test that food grows in each cell """ new = [] true_values = [0, 0, 0, 0, 800, 0, 0, 230, 0] self.island.build_map() self.island.feeding() self.island.grow() for row in self.island.island: for cell in row: new.append(cell.available_food_herb) for index in range(9): nt.assert_equal(new[index], true_values[index]) def test_food_decrease(self): """ Test that the total amount of food on island decreases """ total_food = 0 new_food = 0 for row in self.island.island: for cell in row: total_food += cell.available_food_herb self.island.feeding() for row in self.island.island: for cell in row: new_food += cell.available_food_herb nt.assert_less(new_food, total_food) def test_weight_increase(self): """ test that the weight of herbivores increase (sets number of carnivores to 0 to avoid them reducing herbivore numbers """ new = 0 original = 1500 self.island.feeding() for row in self.island.island: for cell in row: cell.carnivores = [] for herbivore in cell.herbivores: new += herbivore.weight nt.assert_greater(new, original) def test_procreation(self): """ Test that the number of animals increase :return: """ Herbivore.set_parameters({"gamma": 1}) Carnivore.set_parameters({"gamma": 1}) original = 60 new = 0 self.island.procreation() for row in self.island.island: for cell in row: new += \ cell.number_of_individuals()["herbivores"] + \ cell.number_of_individuals()["carnivores"] nt.assert_greater(new, original) nt.assert_less_equal(new, original * 2) def test_age(self): """ Test that average age per cell increases """ original = 0 new = [] self.island.aging() for row in self.island.island: for cell in row: new.append( cell.avg_age()[0] if cell.avg_age()[0] is not None else 0) new.append( cell.avg_age()[1] if cell.avg_age()[1] is not None else 0) average = np.sum(new) / 6. nt.assert_greater(average, original) @staticmethod def test_surrounding_cells(): """ Test that the function surrounding cells returns the right cells """ island = Island("JJJJJJ\nJJJJJJ\nJJJJJJ\nJJJJJJ\nJJJJJJ\nJJJJJJ") island.build_map() cor = island.surrounding_cells((5, 5)) true = [(4, 5), (5, 4), (5, 6), (6, 5)] for index in range(len(cor)): nt.assert_equal(cor[index], true[index]) @staticmethod def test_surrounding_cells_2(): """ Tests that no surrounding cells is returned if all are mountain and ocean """ island = Island("OOO\nOJM\nMMM") island.build_map() cor = island.surrounding_cells((1, 1)) nt.assert_list_equal(cor, []) def test_death(self): """ Runs multiple times to minimise chance of failure due to all animals surviving. :return: """ original = 40 * 5 new = 0 test = Island(self.geogr_simple) test.build_map() Herbivore.set_parameters({"omega": 1}) Carnivore.set_parameters({"omega": 1}) test.island[1][1].herbivores = [Herbivore() for _ in range(10)] test.island[1][2].herbivores = [Herbivore() for _ in range(10)] test.island[1][1].carnivores = [Carnivore() for _ in range(10)] test.island[1][2].carnivores = [Carnivore() for _ in range(10)] test.death() for _ in range(5): for row in test.island: for cell in row: new += \ cell.number_of_individuals()["herbivores"] + \ cell.number_of_individuals()["carnivores"] nt.assert_less(new, original) def test_one_year(self): """ tests that attributes changes after a year """ island = Island(self.geogr_simple) island.build_map() Herbivore.set_parameters({"mu": 0}) Carnivore.set_parameters({"mu": 0}) island.island[1][1].herbivores = [Herbivore(40, 5)] island.island[1][1].carnivores = [Carnivore(20, 5)] for carnivore in island.island[1][1].carnivores: carnivore.fitness = 1 for herbivore in island.island[1][1].herbivores: herbivore.fitness = 1 island.one_year() nt.assert_equal(island.island[1][1].herbivores[0].age, 6) nt.assert_equal(island.island[1][1].carnivores[0].age, 6) nt.assert_not_equal(island.island[1][1].herbivores[0].weight, 40) nt.assert_not_equal(island.island[1][1].carnivores[0].weight, 20)