Source code for farmgym.v2.entities.Pests

import numpy as np
from farmgym.v2.entity_api import Entity_API, Range, fillarray, checkissubclass, expglm
from PIL import Image


[docs]class Pests(Entity_API): def __init__(self, field, parameters): Entity_API.__init__(self, field, parameters) X = self.field.X Y = self.field.Y self.variables = {} self.variables["plot_population#nb"] = fillarray( X, Y, (0, 1000), 0.0 ) # np.full((X,Y),fill_value=Range((0,1000),0.)) # TODO: This is bad, as plants are perhaps added later on. + What about weeds? plants = [field.entities[e] for e in field.entities if checkissubclass(field.entities[e].__class__, "Plant")] weeds = [ self.field.entities[e] for e in self.field.entities if checkissubclass(self.field.entities[e].__class__, "Weeds") ] self.variables["onplant_population#nb"] = {} for i in range(len(plants)): self.variables["onplant_population#nb"][plants[i].name] = fillarray( X, Y, (0, 1000), 0.0 ) # np.full((X,Y),fill_value=Range((0,1000),0.)) for i in range(len(weeds)): self.variables["onplant_population#nb"][weeds[i].name] = fillarray( X, Y, (0, 1000), 0.0 ) # np.full((X,Y),fill_value=Range((0,1000),0.)) # Actions self.actions = {} # self.variables["total_cumulated_plot_population#nb"] = Range((0, 10000), 0.0) self.dependencies = {"Weather", "Soil", "Plant", "Birds"} def get_parameter_keys(self): return [ "min_population#nb", "max_population#nb", "arrival_frequency#day-1", "appear_conditions", "leave_conditions", ] def reset(self): X = self.field.X Y = self.field.Y self.variables["plot_population#nb"] = fillarray( X, Y, (0, 1000), 0.0 ) # np.full((X,Y),fill_value=Range((0,1000),0.)) plants = [ self.field.entities[e] for e in self.field.entities if checkissubclass(self.field.entities[e].__class__, "Plant") ] weeds = [ self.field.entities[e] for e in self.field.entities if checkissubclass(self.field.entities[e].__class__, "Weeds") ] self.variables["onplant_population#nb"] = {} for i in range(len(plants)): self.variables["onplant_population#nb"][plants[i].name] = fillarray( X, Y, (0, 1000), 0.0 ) # np.full((X, Y), fill_value=Range((0, 1000), 0.)) for i in range(len(weeds)): self.variables["onplant_population#nb"][weeds[i].name] = fillarray( X, Y, (0, 1000), 0.0 ) # np.full((X,Y),fill_value=Range((0,1000),0.)) self.initialize_variables(self.initial_conditions) def update_variables(self, field, entities): weather = [entities[e] for e in entities if checkissubclass(entities[e].__class__, "Weather")][0] soil = [entities[e] for e in entities if checkissubclass(entities[e].__class__, "Soil")][0] plants = [entities[e] for e in entities if checkissubclass(entities[e].__class__, "Plant")] weeds = [entities[e] for e in entities if checkissubclass(entities[e].__class__, "Weeds")] birds = [entities[e] for e in entities if checkissubclass(entities[e].__class__, "Birds")] nb_birds_eating_pests = np.sum([b.variables["population#nb"].value for b in birds if b.parameters["pest_eater"]]) # print("BIRDS_EAT_PESTS",nb_birds_eating_pests) for x in range(self.field.X): for y in range(self.field.Y): # pests randomly move to neighbor locations: neighbors = field.get_neighbors((x, y)) w = {"H": self.np_random.random()} for k in neighbors.keys(): w[k] = self.np_random.random() # Adding wind effect if weather.variables["wind"]["direction"].value == k: w[k] += weather.variables["wind"]["speed#km.h-1"].value / 10.0 W = np.sum(list(w.values())) pop = self.variables["plot_population#nb"][x, y].value for k in neighbors.keys(): nbp = min( np.ceil(w[k] / W * pop), self.variables["plot_population#nb"][x, y].value, ) self.variables["plot_population#nb"][neighbors[k]].set_value( self.variables["plot_population#nb"][neighbors[k]].value + nbp ) self.variables["plot_population#nb"][x, y].set_value( self.variables["plot_population#nb"][x, y].value - nbp ) # Add random pests on field border: # if (field.plots[x][y].type=='edge'): # nb_edge_arrival =self.parameters['min_population#nb']+ np.ceil( (self.parameters['max_population#nb']-self.parameters['min_population#nb'])*max(np.sin(self.parameters['arrival_frequency#day-1']* weather.variables['day#int365'].value),0)) is_arrival = self.np_random.binomial(1, self.parameters["arrival_frequency#day-1"], 1)[0] == 1 if is_arrival: nb_edge_arrival = self.np_random.integers( self.parameters["min_population#nb"], self.parameters["max_population#nb"], ) else: nb_edge_arrival = 0 p = self.parameters["leave_conditions"] q = [] maxd = max(field.X, field.Y) / 2.0 q.append( ( p["sensitivity_dist_edge"], field.distance_to_edge((x, y)), maxd, np.infty, ) ) q.append( ( p["sensitivity_death_birds"], nb_birds_eating_pests, 0, p["death_birds_max"], ) ) q.append( ( p["sensitivity_T"], weather.variables["air_temperature"]["mean#°C"].value, p["T_min"], p["T_max"], ) ) q.append( ( p["sensitivity_pesticide"], soil.variables["amount_cide#g"]["pests"][x, y].value, -np.infty, p["pesticide_min"], ) ) # TODO: Add total repulsive/attractive effect of plants on plot! q_stay = expglm(p["sensitivity_0"], q) self.variables["plot_population#nb"][x, y].set_value( self.np_random.binomial( (int)(self.variables["plot_population#nb"][x, y].value), q_stay, 1, )[0] ) p = self.parameters["appear_conditions"] q = [] q.append( ( p["sensitivity_dist_edge"], field.distance_to_edge((x, y)), -np.infty, 0.0, ) ) q.append( ( p["sensitivity_T"], weather.variables["air_temperature"]["mean#°C"].value, p["T_min"], p["T_max"], ) ) q.append( ( p["sensitivity_pesticide"], soil.variables["amount_cide#g"]["pests"][x, y].value, -np.infty, p["pesticide_min"], ) ) # TODO: Add total repulsive/attractive effect of plants on plot! q_appear = expglm(p["sensitivity_0"], q) nb_appear = self.np_random.binomial(nb_edge_arrival, q_appear, 1)[0] new_value = min( self.variables["plot_population#nb"][x, y].value + nb_appear, self.parameters["max_population#nb"], ) self.variables["total_cumulated_plot_population#nb"].set_value( self.variables["total_cumulated_plot_population#nb"].value + new_value - self.variables["plot_population#nb"][x, y].value ) self.variables["plot_population#nb"][x, y].set_value(new_value) ## We do the following next in order not to mess up with for x, for y loop and neighbors changes. for x in range(self.field.X): for y in range(self.field.Y): # TODO: Add repulsive effect only if plant is there and not dead !! # Distribute pests equally amongst plants: weights = np.zeros((len(plants) + len(weeds))) for i in range(len(plants)): if plants[i].is_active((x, y)): weights[i] = ( np.exp(-plants[i].parameters["pest_repulsive_effect#float"]) * plants[i].variables["population#nb"][x, y].value ) for i in range(len(weeds)): if weeds[i].variables["grow#nb"][x, y].value + weeds[i].variables["flowers#nb"][x, y].value > 0: weights[i + len(plants)] = np.exp(-weeds[i].parameters["pest_repulsive_effect#float"]) * ( weeds[i].variables["grow#nb"][x, y].value + weeds[i].variables["flowers#nb"][x, y].value ) if np.sum(weights) > 0: weights = weights / np.sum(weights) # print("WW",weights,len(plants)) ns = self.np_random.multinomial((int)(self.variables["plot_population#nb"][x, y].value), weights) for i in range(len(plants)): self.variables["onplant_population#nb"][plants[i].name][x, y].set_value(ns[i]) for i in range(len(weeds)): self.variables["onplant_population#nb"][weeds[i].name][x, y].set_value(ns[i + len(plants)]) else: for i in range(len(plants)): self.variables["onplant_population#nb"][plants[i].name][x, y].set_value(0) for i in range(len(weeds)): self.variables["onplant_population#nb"][weeds[i].name][x, y].set_value(0) def act_on_variables(self, action_name, action_params): pass def to_fieldimage(self): im_width, im_height = 1216, 1216 image = Image.new( "RGBA", (im_width * self.field.X, im_height * self.field.Y), (255, 255, 255, 0), ) for x in range(self.field.X): for y in range(self.field.Y): # print("XY",x,y,self.variables['wet_surface#m2.day-1'][x,y].value) if self.variables["plot_population#nb"][x, y].value > 0: if self.variables["plot_population#nb"][x, y].value > 3: image.paste(self.images["many"], (im_width * x, im_height * y)) else: image.paste(self.images["few"], (im_width * x, im_height * y)) return image