Reputation: 11
I am using mesa (agent based modelling) to implement a landscape model. To generate the landscape I utilize several numpy arrays (800 x 800) that each hold specific information (e.g. elevation, soil moisture etc etc). To initialize the model, Mesa iterates through the user specified grid size (so in this case 800 x 800) and assigns 'agents' to each 'patch' on the grid:
def coord_iter(self):
""" An iterator that returns coordinates as well as cell contents. """
for row in range(self.width):
for col in range(self.height):
yield self.grid[row][col], row, col # agent, x, y
Using this iterator I then assign values from the numpy arrays to each x,y on the grid:
for agent, x, y in self.grid.coord_iter(self.landscape.elevation):
# check that patch is land
if self.landscape.elevation[x, y] != -9999:
self.agents_created += 1
self.create_landscape_patch(x, y)
# set landscape_classes (i.e. 0 = bracken) if 5 then this is a deposition area
if self.landscape.vegetation[x, y] != 5:
self.create_vegetation_patch(x, y)
# populate landscape patch with values
self.add_landscape_patch(x, y)
# if deposition site
if self.landscape.vegetation[x, y] == 5:
self.create_deposition_patch(x,y)
Within the numpy array, there are some x, y values that I do not need to assign to the grid, so I currently use a simple 'if' statement to filter out these values (if self.landscape.elevation[x, y] != -9999:
). Clearly, by using the coord_iter function I inevitably execute the loop 800 x 800 times, when I could avoid iteration when the values in the numpy array == -9999. An example of how each 'agent' is created and then assigned to the mesa grid is given below (landscape patch).
def create_landscape_patch(self, x, y):
self.elevation_xy = int(self.landscape.elevation[x, y])
# calculate burn probabilities based on soil and temp
self.burn_s_m_p = self.landscape.burn_s_m_p_array[x, y]
self.burn_s_t_p = self.landscape.burn_s_t_p_array[x, y]
# calculate succession probabilities based on soil and temp
self.succ_s_m_p = self.landscape.succ_s_m_p_array[x, y]
self.succ_s_t_p = self.landscape.succ_s_t_p_array[x, y]
self.time_colonised_xy = self.landscape.time_colonised[x, y]
self.is_patch_colonised_xy = self.landscape.colonised[x, y]
def add_landscape_patch(self, x, y):
patch = Landscape(self.unique_id, (x, y), self, self.elevation_xy, self.burn_s_m_p, self.burn_s_t_p, self.vegetation_typ_xy,
False, self.time_colonised_xy, self.is_patch_colonised_xy, self.succ_s_m_p, self.succ_s_t_p, self.veg_this_patch)
self.grid.place_agent(patch, (x, y))
self.schedule.add(patch)
self.unique_id += 1
Currently my code works, but I know there must be a more efficient way to achieve this result. The time it is taking to 'build' the landscape is several minutes, and I hope to build several thousand! Any help on how I can make this more efficient would be much appreciated. Thanks
Upvotes: 1
Views: 202