Mosquitos are being fed and people are dying
This commit is contained in:
parent
2cc19b961e
commit
a910266296
1 changed files with 82 additions and 10 deletions
92
malaria.py
92
malaria.py
|
@ -8,7 +8,7 @@ from enum import IntEnum
|
||||||
class Model:
|
class Model:
|
||||||
def __init__(self, width=32, height=32, humandens=0.15, mosquitodens=0.10,
|
def __init__(self, width=32, height=32, humandens=0.15, mosquitodens=0.10,
|
||||||
immunepct=0.1, mosqinfpct=0.1, hm_infpct=0.5, mh_infpct=0.5,
|
immunepct=0.1, mosqinfpct=0.1, hm_infpct=0.5, mh_infpct=0.5,
|
||||||
hinfdiepct=0.01, mhungrypct=0.1, humandiepct=10**-3,
|
hinfdiepct=0.01, mhungrypct=0.1, humandiepct=10**-6,
|
||||||
mosqdiepct=10**-3, mosqnetdens=0.05, time_steps=2000,
|
mosqdiepct=10**-3, mosqnetdens=0.05, time_steps=2000,
|
||||||
graphical=True):
|
graphical=True):
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ class Model:
|
||||||
self.immunepct = immunepct
|
self.immunepct = immunepct
|
||||||
# Chance for a mosquito to be infectuous
|
# Chance for a mosquito to be infectuous
|
||||||
self.mosqinfpct = mosqinfpct
|
self.mosqinfpct = mosqinfpct
|
||||||
# Chance for a human to be infected by a mosquito bite
|
# Chance for a mosquito to be infected by a human
|
||||||
self.hm_infpct = hm_infpct
|
self.hm_infpct = hm_infpct
|
||||||
# Chance for a mosquito to be infected from biting an infected human
|
# Chance for a human to be infected from a mosquito
|
||||||
self.mh_infpct = mh_infpct
|
self.mh_infpct = mh_infpct
|
||||||
# Chance that an infected human dies
|
# Chance that an infected human dies
|
||||||
self.hinfdiepct = hinfdiepct
|
self.hinfdiepct = hinfdiepct
|
||||||
|
@ -46,6 +46,17 @@ class Model:
|
||||||
self.mosquitos = self.gen_mosquitos()
|
self.mosquitos = self.gen_mosquitos()
|
||||||
self.nets = self.gen_nets()
|
self.nets = self.gen_nets()
|
||||||
|
|
||||||
|
# statistics
|
||||||
|
self.stats = {
|
||||||
|
"natural deaths": 0,
|
||||||
|
"malaria deaths": 0,
|
||||||
|
"total deaths": 0,
|
||||||
|
"mosquitos fed": 0,
|
||||||
|
"humans infected": 0,
|
||||||
|
"mosquitos infected": 0,
|
||||||
|
"net count": 0
|
||||||
|
}
|
||||||
|
|
||||||
if self.graphical:
|
if self.graphical:
|
||||||
self.init_draw()
|
self.init_draw()
|
||||||
|
|
||||||
|
@ -57,6 +68,9 @@ class Model:
|
||||||
self.norm = matplotlib.colors.BoundaryNorm(bounds, self.colors.N)
|
self.norm = matplotlib.colors.BoundaryNorm(bounds, self.colors.N)
|
||||||
|
|
||||||
def recycle_human(self):
|
def recycle_human(self):
|
||||||
|
"""
|
||||||
|
Determine if a human dies of natural causes and then replace them by a new human
|
||||||
|
"""
|
||||||
# Get all living humans
|
# Get all living humans
|
||||||
humans = np.transpose(np.where(self.grid != Human.DEAD))
|
humans = np.transpose(np.where(self.grid != Human.DEAD))
|
||||||
|
|
||||||
|
@ -71,6 +85,7 @@ class Model:
|
||||||
|
|
||||||
death_count = len(humans) - humans_survive
|
death_count = len(humans) - humans_survive
|
||||||
|
|
||||||
|
self.stats["natural deaths"] += death_count
|
||||||
|
|
||||||
# Pick a random, unpopulated spot
|
# Pick a random, unpopulated spot
|
||||||
births = np.array(random.sample(list(np.transpose(np.where(self.grid == Human.DEAD))),
|
births = np.array(random.sample(list(np.transpose(np.where(self.grid == Human.DEAD))),
|
||||||
|
@ -93,8 +108,40 @@ class Model:
|
||||||
|
|
||||||
# Now let's kill them
|
# Now let's kill them
|
||||||
self.grid[infected[deaths][:, 0], infected[deaths][:, 1]] = Human.DEAD
|
self.grid[infected[deaths][:, 0], infected[deaths][:, 1]] = Human.DEAD
|
||||||
|
|
||||||
|
self.stats["malaria deaths"] += len(np.where(deaths)[0])
|
||||||
|
|
||||||
|
def feed(self):
|
||||||
|
#TODO: dit refactoren?
|
||||||
|
"""
|
||||||
|
Feed the mosquitos that want to and can be fed
|
||||||
|
"""
|
||||||
|
for mos in self.mosquitos:
|
||||||
|
if not mos.hungry:
|
||||||
|
continue
|
||||||
|
# state of current place on the grid where mosquito lives
|
||||||
|
state = self.grid[mos.x, mos.y]
|
||||||
|
|
||||||
|
if state != Human.DEAD:
|
||||||
|
self.stats["mosquitos fed"] += 1
|
||||||
|
mos.hungry = False
|
||||||
|
|
||||||
|
# check if healthy human needs to be infected or mosquito becomes infected from eating
|
||||||
|
if state == Human.HEALTHY and mos.infected and random.uniform(0, 1) < self.mh_infpct:
|
||||||
|
self.grid[mos.x, mos.y] = Human.INFECTED
|
||||||
|
self.stats["humans infected"] += 1
|
||||||
|
elif state == Human.INFECTED and not mos.infected and random.uniform(0, 1) < self.hm_infpct:
|
||||||
|
self.stats["mosquitos infected"] += 1
|
||||||
|
mos.infected = True
|
||||||
|
|
||||||
|
def determine_hunger(self):
|
||||||
|
"""
|
||||||
|
Determines which mosquitos should get hungry
|
||||||
|
"""
|
||||||
|
for mos in self.mosquitos:
|
||||||
|
mos.hungry = not mos.hungry and random.uniform(0, 1) < self.mhungrypct
|
||||||
|
|
||||||
def get_movementbox(self, x, y):
|
def get_movementbox(self, x: int, y: int):
|
||||||
"""
|
"""
|
||||||
Returns indices of a moore neighbourhood around the given index
|
Returns indices of a moore neighbourhood around the given index
|
||||||
"""
|
"""
|
||||||
|
@ -176,17 +223,36 @@ class Model:
|
||||||
p=[1-self.mosqnetdens, self.mosqnetdens],
|
p=[1-self.mosqnetdens, self.mosqnetdens],
|
||||||
size=(self.width, self.height))
|
size=(self.width, self.height))
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
"""
|
||||||
This functions runs the simulation
|
This functions runs the simulation
|
||||||
"""
|
"""
|
||||||
|
print(chr(27) + "[2J")
|
||||||
for t in range(self.time_steps):
|
for t in range(self.time_steps):
|
||||||
|
print("Simulating timestep: {}".format(t), end='\r')
|
||||||
self.step()
|
self.step()
|
||||||
if self.graphical:
|
if self.graphical:
|
||||||
self.draw(t)
|
self.draw(t)
|
||||||
else:
|
|
||||||
print("Simulating timestep: {}".format(t), end='\r')
|
print(chr(27) + "[2J")
|
||||||
|
self.compile_stats()
|
||||||
|
self.print_stats()
|
||||||
|
|
||||||
|
def compile_stats(self):
|
||||||
|
"""
|
||||||
|
Compiles a comprehensive list of statistics of the simulation
|
||||||
|
"""
|
||||||
|
self.stats["total deaths"] = self.stats["malaria deaths"] + self.stats["natural deaths"]
|
||||||
|
|
||||||
|
# print(np.where(self.nets))
|
||||||
|
self.stats["net count"] = len(np.where(self.nets)[0])
|
||||||
|
|
||||||
|
def print_stats(self):
|
||||||
|
"""
|
||||||
|
Prints the gathered statistics from the simulation
|
||||||
|
"""
|
||||||
|
for stat in self.stats:
|
||||||
|
print(f"{stat}: {self.stats[stat]}")
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
"""
|
"""
|
||||||
|
@ -198,9 +264,15 @@ class Model:
|
||||||
self.recycle_human()
|
self.recycle_human()
|
||||||
# move mosquitos
|
# move mosquitos
|
||||||
self.move_mosquitos()
|
self.move_mosquitos()
|
||||||
|
# feed hungry mosquitos
|
||||||
|
self.feed()
|
||||||
|
# make mosquitos hungry again
|
||||||
|
self.determine_hunger()
|
||||||
|
|
||||||
|
|
||||||
def draw(self, t: int):
|
def draw(self, t: int):
|
||||||
|
"""
|
||||||
|
Draws the grid of humans, tents and mosquitos
|
||||||
|
"""
|
||||||
# this function draws the humans
|
# this function draws the humans
|
||||||
plt.title("t={}".format(t))
|
plt.title("t={}".format(t))
|
||||||
# draw the grid
|
# draw the grid
|
||||||
|
@ -240,9 +312,9 @@ class Human(IntEnum):
|
||||||
HEALTHY = 1
|
HEALTHY = 1
|
||||||
INFECTED = 2
|
INFECTED = 2
|
||||||
IMMUNE = 3
|
IMMUNE = 3
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
model = Model(graphical=True)
|
model = Model(graphical=False)
|
||||||
model.run()
|
model.run()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue