2019-ics-malariafreek/malaria.py

143 lines
4.6 KiB
Python
Raw Normal View History

2019-03-07 16:06:20 +00:00
import matplotlib.pyplot as plt
import matplotlib.colors
2019-03-07 15:42:41 +00:00
import numpy as np
import random
from enum import IntEnum
class Model:
def __init__(self, width=32, height=32, humandens=0.15, mosquitodens=0.10,
2019-03-07 16:06:20 +00:00
immunepct=0.1, mosqinfpct=0.1, hm_infpct=0.5, mh_infpct=0.5,
2019-03-07 18:53:26 +00:00
hinfdiepct=0.01, mhungrypct=0.1, humandiepct=10**-3,
2019-03-07 18:19:46 +00:00
mosqdiepct=10**-3, mosqnetdens=0.05, time_steps=2000):
plt.ion()
2019-03-07 15:42:41 +00:00
self.width = width
self.height = height
2019-03-07 16:06:20 +00:00
2019-03-07 18:19:46 +00:00
# The percentage of tiles that start as humans
2019-03-07 15:42:41 +00:00
self.humandens = humandens
2019-03-07 18:19:46 +00:00
# The percentage of tiles that contain mosquitos
2019-03-07 15:42:41 +00:00
self.mosquitodens = mosquitodens
2019-03-07 18:19:46 +00:00
# Percentage of humans that are immune
2019-03-07 15:42:41 +00:00
self.immunepct = immunepct
2019-03-07 18:19:46 +00:00
# Chance for a mosquito to be infected
2019-03-07 15:42:41 +00:00
self.mosqinfpct = mosqinfpct
2019-03-07 18:19:46 +00:00
# Chance for a human to be infected by a mosquito bite
2019-03-07 15:42:41 +00:00
self.hm_infpct = hm_infpct
2019-03-07 18:19:46 +00:00
# Chance for a mosquito to be infected from biting an infected human
2019-03-07 15:42:41 +00:00
self.mh_infpct = mh_infpct
2019-03-07 18:19:46 +00:00
# Chance that an infected human dies
2019-03-07 15:42:41 +00:00
self.hinfdiepct = hinfdiepct
2019-03-07 18:19:46 +00:00
# Chance for a mosquito to be hungry
2019-03-07 15:42:41 +00:00
self.mhungrypct = mhungrypct
2019-03-07 18:19:46 +00:00
# Chance for human to die from random causes
2019-03-07 15:42:41 +00:00
self.humandiepct = humandiepct
2019-03-07 18:19:46 +00:00
# Chance for a mosquito to die
2019-03-07 15:42:41 +00:00
self.mosqdiepct = mosqdiepct
2019-03-07 18:19:46 +00:00
# Percentage of tiles that contain mosquito nets
2019-03-07 15:42:41 +00:00
self.mosqnetdens = mosqnetdens
2019-03-07 18:19:46 +00:00
# The number of timesteps to run te simulation for
2019-03-07 15:42:41 +00:00
self.time_steps = time_steps
2019-03-07 18:53:26 +00:00
self.grid = self.gen_humans()
2019-03-07 15:42:41 +00:00
self.mosquitos = self.gen_mosquitos()
2019-03-07 18:19:46 +00:00
self.init_draw()
def init_draw(self):
self.colors = matplotlib.colors.ListedColormap(
["black", "green", "red", "yellow"])
bounds = [Human.DEAD, Human.HEALTHY, Human.INFECTED, Human.IMMUNE]
self.norm = matplotlib.colors.BoundaryNorm(bounds, self.colors.N)
2019-03-07 15:42:41 +00:00
def recycle_human(self):
# Get all living humans
2019-03-07 18:53:26 +00:00
humans = np.transpose(np.where(self.grid != Human.DEAD))
2019-03-07 16:06:20 +00:00
# Get a mask of humans to kill
deaths = np.random.rand(len(humans)) < self.humandiepct
# Kill them.
2019-03-07 18:53:26 +00:00
self.grid[humans[deaths][:, 0], humans[deaths][:, 1]] = Human.DEAD
# get num humans after killing
humans_survive = len(np.transpose(np.where(self.grid != Human.DEAD)))
death_count = len(humans) - humans_survive
2019-03-07 16:06:20 +00:00
2019-03-07 15:42:41 +00:00
# Pick a random, unpopulated spot
2019-03-07 18:53:26 +00:00
births = np.array(random.sample(list(np.transpose(np.where(self.grid == Human.DEAD))),
death_count))
2019-03-07 16:06:20 +00:00
2019-03-07 18:53:26 +00:00
# Deliver the newborns
for birth in births:
self.grid[birth[0]][birth[1]] = np.random.choice([Human.HEALTHY, Human.IMMUNE],
p=[1-self.immunepct, self.immunepct])
2019-03-07 18:19:46 +00:00
def do_malaria(self):
"""
This function determines who of the infected dies from their illness
"""
# Get all infected humans
2019-03-07 18:53:26 +00:00
infected = np.transpose(np.where(self.grid == Human.INFECTED))
2019-03-07 18:19:46 +00:00
# Decide which infected people die
deaths = np.random.rand(len(infected)) < self.hinfdiepct
# Now let's kill them
2019-03-07 18:53:26 +00:00
self.grid[infected[deaths][:, 0], infected[deaths][:, 1]] = Human.DEAD
2019-03-07 18:19:46 +00:00
2019-03-07 15:42:41 +00:00
def gen_humans(self):
2019-03-07 16:06:20 +00:00
# Calculate the probabilities
2019-03-07 15:42:41 +00:00
p_dead = 1 - self.humandens
p_immune = self.humandens * self.immunepct
2019-03-07 16:06:20 +00:00
p_healthy = self.humandens - p_immune
2019-03-07 15:42:41 +00:00
2019-03-07 16:06:20 +00:00
# Create the grid with humans.
2019-03-07 15:42:41 +00:00
return np.random.choice((Human.DEAD, Human.HEALTHY, Human.IMMUNE),
size=(self.width, self.height),
2019-03-07 16:06:20 +00:00
p=(p_dead, p_healthy, p_immune))
2019-03-07 15:42:41 +00:00
def gen_mosquitos(self):
count = self.width * self.height * self.mosquitodens
def run(self):
2019-03-07 18:19:46 +00:00
for t in range(self.time_steps):
2019-03-07 15:42:41 +00:00
self.step()
2019-03-07 18:19:46 +00:00
self.draw(t)
2019-03-07 15:42:41 +00:00
def step(self):
2019-03-07 18:53:26 +00:00
# self.do_malaria()
self.recycle_human()
2019-03-07 16:06:20 +00:00
2019-03-07 18:19:46 +00:00
def draw(self, t):
2019-03-07 15:42:41 +00:00
# this function draws the humans
2019-03-07 18:19:46 +00:00
plt.title("t={}".format(t))
2019-03-07 18:53:26 +00:00
plt.imshow(self.grid, cmap=self.colors, norm=self.norm)
2019-03-07 16:06:20 +00:00
2019-03-07 15:42:41 +00:00
plt.pause(0.0001)
plt.clf()
class Mosquito:
def __init__(self, x: int, y: int, infected: bool, hungry: bool):
self.x = x
self.y = y
self.infected = infected
self.hungry = hungry
class Human(IntEnum):
DEAD = 0
HEALTHY = 1
INFECTED = 2
IMMUNE = 3
if __name__ == "__main__":
2019-03-07 16:06:20 +00:00
model = Model()
2019-03-07 18:19:46 +00:00
model.run()
2019-03-07 15:42:41 +00:00