SIMULATING THE TRANSMISSION OF VIRUSES
Simulating the Transmission of Viruses
Table of Contents
Abstract.…………………………………………………………………………………….……3
Introduction………………………………………………………………………………………4
Method……………………………………………………………………………………………5
Materials…….…………………………………………………………………………5
Procedures……………………………………………………………………………..5
Results…………………………………………………………………………………………..10
Discussion………………………………………………………………………………………24
References………………………………………………………………………………………27
Appendix………………………………………………………………………………………...28
Abstract
From the drastic change in our lives due to the COVID-19 pandemic to the recent spikecaused by the omicron variant, understanding the different protection measures of viruses can be crucial toslow down the spread of pandemics. The project aimed to create a program using Python that simulates thetransmission of any virus in various environments while comparing the transmission rates under differentparameters such as infection rate, mask rate, and population size. To accomplish this, the researcherscreated a simulation that demonstrated the spread of viruses and created a graph showing the numbers ofindividuals in different stages of diseases throughout the simulation with provided parameters, which makesit easier to simulate any type of virus. The simulation is able to show how diseases spread in a populationand the progression in individuals. By using this simulation, it allows for people to visualize the severityof a virus, compare the effectiveness of different protective measures, and understand or predict the virustransmission process. Future project applications include turning the program intoan app and adding more parameters that would affect the transmission of a virus so that the predictionaccuracy can be further improved.
Simulating the Transmission of Viruses
The ongoing COVID-19 pandemic has revealed the damage that a deadly viruscan cause. With more than 78 million total cases in the United States alone, the coronavirus is currentlyranked the seventh deadliest plague in history (LePan & Schell, 2021). COVID-19 has dramatically raisedthe awareness of viruses to the public. Although the coronavirus cases declined from January to June of 2021under the impact of the vaccines, the numbers rose notably again due to the current entrance of the omicronvariant to the United States. This signified that any slight change in a virus could have an extraordinaryimpact on human society. Considering the severe impact of small changes in viruses can cause, the publicshould be better informed about such impacts in advance.
Our goal is to create a model that would easily show the transmission of anyvirus within a general population. With the current pandemic, researchers have created graphs that show thetransmissivity of COVID-19 but many of these results have not accounted for the factors of the differentvariants of COVID-19. In a study done by Gressman and Peck, COVID-19 transmissionwas simulated within a university environment of 20,000 students and 2,500 teachers using an agent-basedmodel. An agent-based model is a simulation approach to model systems composed of autonomous interactingentities, i.e., “agents” (Macal & North, 2010; Gressman & Peck, 2020). In another study done by Tupper and Colijn, an agent-based simulationmodel was used to simulate the spread of COVID-19 between high-school and elementary environments (Tupper& Colijn, 2021). For their research, instead of having only the three phases of the SIR model, eachagent was in one of five phases: susceptible, exposed, presymptomatic, symptomatic, and recovered. Usingthis different approach benefitted the researchers because COVID-19 can be transmitted before developingsymptoms (McCrimmon, K. K. 2021).
However, both models only apply to the alpha COVID-19 variant and did notvisually simulate the virus, making it difficult for the readers to understand. With this in mind, the goalof our project is to create a program that not only can show the transmission of COVID-19 but can alsosimulate any viruses and illustrates their severity. The goal was achieved by creating a Python program,with changeable parameters, that can provide a visual model to show the spread of viruses among individualsusing the characteristics of a specific virus. The program can also be used to compare the effectiveness ofdifferent protection measures by changing the parameters.
Method
Materials
- Computer with an operating system supported by Python3.10.1 or higher version
- Python 3.10.1 or higher version
- NumPy Python library
- Matplotlib Python library
- xlwt Python library
- Tkinter Python library
- Basic Python library
- Visual Studio Code Integrated Development Environment(IDE)
Procedures
The researchers firstdownloaded Visual Studio Code, a text editor with programming-specific capabilities including auto-complete,custom debugging extensions, and overall customizability for a well-suited programming environment. Theresearchers then installed the following libraries: NumPy, Matplotlib, xlwt, tkinter. These libraries wereinstalled with the following command prompt commands:
python -m pip install numpy
python -m pip install matplotlib
python -m pip install xlwt
python -m pip install tkinter
The NumPy external library contains helpful data science tools and moretime-efficient data structures. Matplotlib is a plotting library that simplifies data visualization byallowing researchers to convert simple lists directly into intricate graphs. The xlwt library helps writedata into files. Tkinter was the main rendering engine used for this project and provides crucialfunctionality to render windows and images that display the simulation.
After installing the libraries as mentioned earlier, the researcherscreated a directory named “Virus_Simulation” including a folder named “src” whichdenotes where the code for the project will be located and is synonymous with “sourcecode.”
Inside the“src” folder, the researchers created a “main.py” (see Appendix A) file. Thisfile’s primary purpose is to start the simulation by calling the “start_ui” function,which starts the display window, and by calling the “sim_main” function that starts thesimulation:
def main():
ui.start_ui()
simulation.sim_main()
Within the same“src” folder, the researchers also created a “simulation.py” file (see Appendix B).This file mainly contains two “for loop” which initialize the simulation. The initializationpart includes setting the initial infected individual, mask, and vaccination status for everyindividual:
for i in range (variable.NUM_PEOPLE):
person.mask_check()
person.vaccine_check()
for i in range (variable.INITIAL_INFECTIONS):
people[i].symptomatic_check()
The first “for loop” repeats the process needed for thesimulation and collects simulation data for every hour:
for i in range (variable.SIM_HOURS)
The second “forloop” repeats through every individual in the simulation during each hour to check location, virusstage, and infection:
for p in people:
p.mobility_model.move()
p.progress_disease()
for p2 in people:
p.try_infect(p2)
Another file the researchers created was “variable.py”also located in the “src” directory (see Appendix E). This file contains all the parameters thatcan be changed in the simulation. Three main categories of the parameters include individual, virus, andenvironment variables. These parameters can be changed to simulate different situations. Other files in the“src” directory include:
- “person.py” includes the“person” class that defines all the functions for the “person” individual in thesimulation (see Appendix C).
- “location.py” with a“location” class that contains all the functions needed to simulate the location of anobject (see Appendix D).
- “mobility_model.py” determines howobjects move (see Appendix G).
- “pp_model.py” assigns the mobility modelused in this simulation, which generates 20 popular places where individuals would cluster to simulatecentral areas in real life (see Appendix F). The 20 popular places can be generated in two differentways, random or uniform, according to the needs.
- “ui.py” creates windows to demonstratethe simulation process and result. The process of simulation is presented through the “ball”class object used in the “ball.py”, which represents each simulated individual in a“popular place model”. The result of the simulation is graphed using“matplotlib” into a line graph which updates for every simulated date (see AppendixH).
- “ ball.py” creates balls in the“ui” window mentioned above to represent each “person” object which differentcolors to represent different stages of the disease (see Appendix I)
- “excel.py,” writes data collected fromthe simulation into an excel spreadsheet.
- “sir.py” has two main functions. Thefirst one is to calculate the infection rate based on data collected from the simulation. Then, there isa SIR class, which has the function to graph a SIR (susceptible, infected, and recovered) model, themost well-known epidemiological model, based on data collected from the simulation.
The primary calculation method in this simulation is to check theinteraction between each “person” based on his/her location in the “popular placemodel” in every simulation hour. Then based on the interaction, the “person’s” stagein disease will be changed according to probabilities and other given parameters. This essentially mimicsthe transmission of the virus in the population and the progression of disease in an individual in the realworld.
Based on the model and graph created by the simulation, theresearchers compared the model with the SIR model with a given transmission rate to test the significance ofthe simulation to predict real-life scenarios. The SIR model is recognized as one of the most accuratemodels in the field of virus transmission research. By comparing the two models (Figure 1-2), shown below,the simulation can be tested significantly with similarity observed mainly in the max value of infection.This proves the accuracy of the simulation model.
Different data was collected from the simulation result underdifferent parameters with uniformed popular places -- mainly by changing mask rate, vaccination rate,distancing probability, and home probability. Finally, the researchers recorded and compared the graphscollected from the simulation for each scenario.
Results
The researchers created a Python program that could simulate thetransmissivity of a virus through input parameters. The program allows users to input attributes for thesimulation, including the number of days to simulate, infection rate, recovery rate, and other parameterscommonly associated with viruses.
When running the program, allof the parameters within “variable.py” will be used in other parts of the code to create asimulation depending on those parameters. When testing the effectiveness of different protective measures,the data was recorded and graphed to compare the effectiveness of each measure.
In terms ofslowing down the transmission of the virus, the testing results prove the effectiveness of all four measuresrelating to how individuals could protect themselves from viruses: social distancing, self-quarantine,wearing masks, and taking vaccines.
Throughout all of the testing done with the four parameters related to theabove-mentioned four individual protection measures, the researchers noticed a clear decrease in theinfected population as the number of people using these protection measures increased. The following figuresshow the distancing parameter at 0%, 50%, and 100% of the population.
With these three graphs, itcan be seen that there is a high correlation between the increased percentage of the population followingdistancing and the number of infected individuals. As seen from the peak value of the purple line (thenumber of infected individuals) the maximum value for the 100% of the population distancing plot issignificantly lower than that of the 50% of the population distancing plot; this is also true with the 50%of the population distancing plot compared to the 0% of the population distancing plot. The decrease of themax infected number demonstrates the importance of distancing during a virus outbreak.
The percentage of thepopulation self-quarantining also has a significant impact on the number of individuals being infected whichis demonstrated in Figures 6-8.
As seen again by comparing the peak of purple lines, the increase in thepercentage of the population self-quarantining does in fact correlate with the decrease in the number ofinfected individuals. Furthermore, it is interesting to gauge the effectiveness of self-quarantine anddistancing by comparing Figure 3 and Figure 6 when the parameters are both at 100%. It shows that theself-quarantine graph (Figure 6) appears to have more individuals left as susceptible when the simulationended.
Simulation results also show that mask rate and vaccination rate also slowdown the transmission of the virus but are less significant than the other two measures. Figures 9-11 arecollected from simulation results when the mask rate is at 0%, 50%, and 100% of the population,respectively.
Figures 9-11 above compare thedifferences within different percentages of the population wearing masks. Looking at the maximum number ofinfected individuals as the mask rate increases, a decrease in the peak infection can beobserved. This same phenomenon can be observedwith the vaccination rate plots as shown in Figures 12-14 below.
Discussion
Inthis project, researchers created an application capable of simulating the transmissivity of any virus basedon given input parameters. These parameters were used in the simulation to simulate the virus transmissionprocess. Furthermore, graphs were created during the simulation to demonstrate the virus transmissionsituation day by day. The researchers tested how certain parameters would affect the outcome of thesimulation.
The graph below (Figure 15)shows the vertex of infection as a function of different parameters in their different percentages. It canbe seen that self-quarantining and distancing is the most effective way of preventing the spread of thevirus in this simulation. The decrease in masking and vaccinating is minimal compared to the decrease seenin distancing and self-quarantine parameters. This is most likely because the first two measures onlydecrease the chance of getting the virus when interacting with an infected individual, while the other twodecrease the amount of interaction of the individual in a period of time.
Another trend shown in the data collected from the simulation is that the number ofasymptomatic increases as the percentage of vaccination rate increases. The graph below demonstrates theasymptomatic number at different vaccination rates.
This is most likely becausebeing vaccinated can decrease the chance of having severe symptoms which leads to an increasing number ofasymptomatic. And since there is a smaller chance of decreasing with asymptomatic, a higher vaccination ratecan therefore be expected to have a lower death rate. The change in death number was not significant in thissimulation presumably because of the fatality rate, at an average of 1.4%, and the small population of 1000were used in the simulation.
References
Gressman, P. T., & Peck, J. R. (2020, August 3). Simulating covid-19in a university environment. Mathematical Biosciences, 328. Retrieved from https://dx.doi.org/10.1016%2Fj.mbs.2020.108436.
LePan, N., & Schell, H. (2021, September 2). Visualizing the history of pandemics. Visual Capitalist.Retrieved from https://www.visualcapitalist.com/history-of-pandemics-deadliest/.
Lordan, R., FitzGerald, G. A., & Grosser, T. (2020, September 4).Reopening schools during COVID-19. Science, 369(6508). 1146.Retrieved from https://www.science.org/doi/10.1126/science.abe5765.
Macal, C.M., & North, M.J. (2010). Tutorial on agent-based modelingand simulation. Journal of Simulation, 5, 151-162.Retrieved from https://link.springer.com/content/pdf/10.1057/jos.2010.3.pdf.
McCrimmon, K. K. (2021, September 7). The truthabout COVID-19 and asymptomatic spread:
It's common, so wear a mask and avoid large gatherings. UCHealth Today. Retrieved from
https://www.uchealth.org/today/the-truth-about-asymptomatic-spread-of-covid-19/
Tupper, P., & Colijn, C. (2021, July 8). Covid-19 in schools:Mitigating classroom clusters in the context of variable transmission. PLOSComputational Biology, 17(7). Retrieved fromhttps://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1009120#sec002.
Appendix A
“main.py” to start the program
import simulation
import ui
#start simulation
def main():
ui.start_ui()
simulation.sim_main()
main()
Appendix B
“Simulation.py” to start the simulation
import random
from time import sleep
from numpy importaverage
import variable
import person
import ui
import time
import sir
import excel
start_time = time.time()
def try_event(probability):
'''try event with givenprobability'''
rnum =(int(random.uniform(0,100))+1)/100
return rnum <= probability
def sim_main():
'''startsimulation'''
#set initial variables to storedata
vulnerable_history = []
incubation_history = []
asymptomatic_history = []
symptomatic_history = []
infected_history = []
immune_history = []
dead_history = []
max_infected_at_once = 0
hours_past =0
people =[]
#initialize population
for i inrange (variable.NUM_PEOPLE):
new_person=person.Person()
new_person.mask_check()
new_person.vaccine_check()
people.append(new_person)
#set initial infectionindividuals
for i inrange (variable.INITIAL_INFECTIONS):
people[i].symptomatic_check()
people[i].infection_level=0
#print lable
print("Day #\t\tVulnerable#\tIncubation #\tAsymptomatic #\tSymptomatic #\tTotal Infected#\tImmune #\tDead #\t(Death rate in %)\n")
#start simulation (i represent hourspassed)
for i inrange (variable.SIM_HOURS):
check_infected = True
if(not i == 0):
if(num_infected>num_vulnerable):
check_infected = False
hours_past+=1
num_infected = 0
num_symptomatic = 0
num_asymptomatic = 0
num_immune = 0
num_dead = 0
num_vulnerable = 0
num_incubation = 0
ui.ui_delete()
ui.draw_popularPlace()
#simulation for everyindividual
for p in people:
if (p.is_alive()):
p.mobility_model.move()
p.progress_disease()
if(check_infected):
if(p.status==variable.disease_status.INCUBATION or p.status==variable.disease_status.ASYMPTOMATIC or p.status==variable.disease_status.SYMPTOMATIC):
forp2 in people:
if (p2.status==variable.disease_status.VULNERABLE):
p.try_infect(p2)
else:
if(p.status==variable.disease_status.VULNERABLE):
forp2 in people:
if (p2.status==variable.disease_status.INCUBATION or p2.status==variable.disease_status.ASYMPTOMATIC or p2.status==variable.disease_status.SYMPTOMATIC):
p2.try_infect(p)
if (not p.is_alive()):
num_dead+=1
if (p.status == variable.disease_status.INCUBATION):
num_incubation+=1
num_infected+=1
if (p.status == variable.disease_status.ASYMPTOMATIC):
num_asymptomatic+=1
num_infected+=1
if (p.status == variable.disease_status.SYMPTOMATIC):
num_symptomatic+=1
num_infected+=1
if (p.status == variable.disease_status.IMMUNE):
num_immune+=1
if (p.status == variable.disease_status.VULNERABLE):
num_vulnerable+=1
if (not i==0):
ui.ui_redraw(p,int(i/24))
ui.ui_refresh()
if (num_infected > max_infected_at_once):
max_infected_at_once = num_infected
#print out data for everyday passed
if ((i % 24) == 0 or num_infected == 0):
ui.print_graph(hours_past,max_infected_at_once,vulnerable_history,incubation_history,asymptomatic_history,symptomatic_history,infected_history,immune_history,dead_history)
if (num_dead == 0):
prob = 0
else:
prob = num_dead * 100.0 / (num_immune + num_dead)
print("Day ",int(i / 24),"\t",num_vulnerable,"\t\t",num_incubation,"\t\t",num_asymptomatic,"\t\t",num_symptomatic,"\t\t",num_infected,"\t\t\t",num_immune,"\t\t",num_dead,"\t(",prob,"%)\n")
#store data for everyhour
dead_history.append(num_dead)
vulnerable_history.append(num_vulnerable)
incubation_history.append(num_incubation)
asymptomatic_history.append(num_asymptomatic)
symptomatic_history.append(num_symptomatic)
infected_history.append(num_infected)
immune_history.append(num_immune)
dead_history.append(num_dead)
#excel.write(i+1,0,i)
#excel.write(i+1,1,num_vulnerable)
#excel.write(i+1,2,num_infected)
#excel.write(i+1,3,num_immune)
if (num_infected == 0):
break
print("Hours ran: ",hours_past)
print("Peak infection: %i"% max_infected_at_once)
print("--- %s seconds---" % (time.time() - start_time))
sir.cal_infection_rate(people,hours_past)
ui.end()
Appendix C
“person.py” sets variables of each individual“person” class object
import random
import simulation
import variable
import ppmodel
import location
class Person():
def __init__(self):
self.mobility_model = ppmodel.PopularPlacesModel()
self.mobility_model.setPerson(self)
self.location = location.Location()
self.status = variable.disease_status.VULNERABLE
self.masked = False
self.vaccinated = False
self.disease_counter = 0
self.incubation_counter = random.randint(0,variable.MAX_INCUBATION_TIME)
self.infected = 0
self.infection_level = -1
def infect(self):
if(self.status==variable.disease_status.VULNERABLE):
self.status=variable.disease_status.INCUBATION
return True
else:
return False
def try_infect(self,other_person):
if(self.location.get_distance(other_person.location)>variable.INFECTION_PROXIMITY):
return False
if(other_person.location.at_location(other_person.mobility_model.home) or self.location.at_location(self.mobility_model.home)):
if(simulation.try_event(variable.HOME_INFECTTION_PROBABILTY)):
self.infected+=1
other_person.infection_level=self.infection_level + 1
return other_person.infect()
if(other_person.masked and other_person.vaccinated):
if(simulation.try_event(variable.MASKED_VACCINATED_INFECTTION_PROBABILTY)):
self.infected+=1
other_person.infection_level=self.infection_level + 1
return other_person.infect()
if(other_person.masked):
if(simulation.try_event(variable.MASKED_INFECTTION_PROBABILTY)):
self.infected+=1
other_person.infection_level=self.infection_level + 1
return other_person.infect()
if(other_person.vaccinated):
if(simulation.try_event(variable.VACCINATED_INFECTTION_PROBABILTY)):
self.infected+=1
other_person.infection_level=self.infection_level + 1
return other_person.infect()
if(simulation.try_event(variable.NORMAL_INFECTTION_PROBABILTY)):
self.infected+=1
other_person.infection_level=self.infection_level + 1
return other_person.infect()
return False
def symptomatic_check(self):
if(self.vaccinated):
if(simulation.try_event(variable.VACCINATED_ASYMPTOMATIC_PROBABILTY)):
self.status=variable.disease_status.ASYMPTOMATIC
self.disease_counter = random.randint(24*3,variable.MAX_ASYMPTOMATIC_INFECTION_TIME)
else:
self.status=variable.disease_status.SYMPTOMATIC
self.disease_counter = random.randint(24*3,variable.MAX_SYMPTOMATIC_INFECTION_TIME)
else:
if (simulation.try_event(variable.NORMAL_ASYMPTOMATIC_PROBABILTY)):
self.status=variable.disease_status.ASYMPTOMATIC
self.disease_counter = random.randint(24*3,variable.MAX_ASYMPTOMATIC_INFECTION_TIME)
else:
self.status=variable.disease_status.SYMPTOMATIC
self.disease_counter = random.randint(24*3,variable.MAX_SYMPTOMATIC_INFECTION_TIME)
def mask_check(self):
if(simulation.try_event(variable.MASKING_PERCENTAGE)):
self.masked = True
else:
self.masked = False
def vaccine_check(self):
if(simulation.try_event(variable.VACCINATION_PERCENTAGE)):
self.vaccinated = True
else:
self.vaccinated = False
def progress_disease(self):
if(self.status == variable.disease_status.INCUBATION):
self.incubation_counter-=1
if(self.incubation_counter<=0):
self.symptomatic_check()
if(self.status==variable.disease_status.ASYMPTOMATIC or self.status==variable.disease_status.SYMPTOMATIC):
self.disease_counter-=1
if(self.disease_counter<=0):
if(self.status==variable.disease_status.SYMPTOMATIC):
if(simulation.try_event(variable.NORMAL_FATALITY_RATE)):
self.status=variable.disease_status.DEAD
return
elif(self.status==variable.disease_status.ASYMPTOMATIC):
if(simulation.try_event(variable.ASYMPTOMATIC_FATALITY_RATE)):
self.status=variable.disease_status.DEAD
return
self.status=variable.disease_status.IMMUNE
def is_alive(self):
return not self.status ==variable.disease_status.DEAD
Appendix D
“location.py” includes “location” class wherelocation data is calculated
import math
import random
import variable
class Location():
def __init__(self):
self.x = 0
self.y = 0
def random_location(self):
self.x = int(random.uniform(0,variable.X_LIMIT))
self.y = int(random.uniform(0,variable.Y_LIMIT))
def location(self,nx,ny):
self.x = nx
self.y = ny
def move_toward(self,destination,howfar):
dx = destination.x - self.x
dy = destination.y - self.y
theta = math.atan2(dy,dx)
distance = math.sqrt((dx*dx)+(dy*dy))
if(distance < howfar):
self.x = destination.x
self.y = destination.y
return True
else:
self.x=self.x+howfar*math.cos(theta)
self.y=self.y+howfar*math.sin(theta)
return False
def get_distance(self,other_location):
dx = other_location.x - self.x
dy = other_location.y - self.y
#print(math.sqrt((dx*dx)+(dy*dy)))
return math.sqrt((dx*dx)+(dy*dy))
def at_location(self,destination):
return (self.get_distance(destination) < variable.CLOSE_ENOUGH)
def getX(self):
return self.x
def getY(self):
return self.y
def setX(self,nx):
self.x=nx
def setY(self,ny):
self.y=ny
Appendix E
“variable.py” is where parameters for the simulation issaved
import enum
#stages of disease
class disease_status(enum.Enum):
VULNERABLE =0
INCUBATION =1
ASYMPTOMATIC =2
SYMPTOMATIC =3
IMMUNE =4
DEAD =5
#simulation variables
X_LIMIT = 7500
Y_LIMIT = 7500
NUM_PEOPLE = 1000
SIM_HOURS = 5000
INITIAL_INFECTIONS = 5
SATURATION_THRESHOLD = (NUM_PEOPLE/5)
#disease variable
MAX_SYMPTOMATIC_INFECTION_TIME = (24*14)
MAX_ASYMPTOMATIC_INFECTION_TIME = (24*7)
MAX_INCUBATION_TIME = (24*7)
NORMAL_INFECTTION_PROBABILTY = 0.7
MASKED_INFECTTION_PROBABILTY = 0.3
VACCINATED_INFECTTION_PROBABILTY = 0.3
MASKED_VACCINATED_INFECTTION_PROBABILTY =0.1
HOME_INFECTTION_PROBABILTY = 0
NORMAL_FATALITY_RATE = 0.02
ASYMPTOMATIC_FATALITY_RATE = 0
# SATURATED_FATALITY_RATE = 0.06
INFECTION_PROXIMITY = 15
#population variables
NORMAL_ASYMPTOMATIC_PROBABILTY = 0.2
VACCINATED_ASYMPTOMATIC_PROBABILTY = 0.4
MASKING_PERCENTAGE = 0.5
VACCINATION_PERCENTAGE = 0.5
#"location" variables
CLOSE_ENOUGH = 0.05
#"ppmodel" variables
NUM_POPULAR_PLACES = 20
DISTANCING_PROBABILITY = 0.3
DISTANCING_HOME_PROBABILITY = 0.5
NOT_DISTANCING_HOME_PROBABILITY = 0.2
PP_TOP_SPEED = 20
MAX_STAY = 2*24
#variables to add in future
#temperture
Appendix F
“mobility_model.py” defines the parent class“MobilityModel” and basic functions for every movement model
import person
class MobilityModel():
def __init__ (self):
self.person=person.Person()
def setPerson(self,p):
self.person = p
Appendix G
“ppmodel.py” also known as the “popular place model”,a child class of “MobilityModel” defines where each “person” object would go
import random
import mobility_model
import simulation
import person
import location
import variable
popularPlaces = []
for i in range(variable.NUM_POPULAR_PLACES):
new_place =location.Location()
new_place.random_location()
popularPlaces.append(new_place)
# xi = 1
# yi = 1
# for xi in range(0, 5):
# for yi in range(0, 4):
# new_place = location.Location()
# new_place.location(250+xi*1750,250+yi*2333)
# popularPlaces.append(new_place)
class PopularPlacesModel(mobility_model.MobilityModel):
def __init__(self):
self.waypoint = location.Location()
self.waypoint.random_location()
self.speed = -1
self.stay = 0
self.home = location.Location()
self.home.random_location()
if(simulation.try_event(variable.DISTANCING_PROBABILITY)):
self.home_proabilty = variable.DISTANCING_HOME_PROBABILITY
else:
self.home_proabilty = variable.NOT_DISTANCING_HOME_PROBABILITY
def move(self):
if(self.speed < 0):
self.person.location.setX(self.home.getX())
self.person.location.setY(self.home.getY())
self.pick_new_waypoint()
elif(self.person.location.at_location(self.waypoint)):
self.stay-=1
if(self.stay<=0):
self.pick_new_waypoint()
else:
self.person.location.move_toward(self.waypoint,self.speed)
def pick_new_waypoint(self):
self.speed = random.uniform(10,variable.PP_TOP_SPEED)
self.stay = random.randint(0,variable.MAX_STAY)
if(simulation.try_event(self.home_proabilty)):
self.waypoint=self.home
else:
self.waypoint=popularPlaces[random.randint(0,variable.NUM_POPULAR_PLACES-1)]
Appendix H
“ui.py” draws UI including “person” object during thesimulation
from tkinter import*
from tkinter.ttk import *
from ball import Ball
import variable
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg,
NavigationToolbar2Tk)
import ppmodel
HEIGHT = variable.Y_LIMIT/10
WIDTH = variable.X_LIMIT/10
fig = Figure()
plot1 = fig.add_subplot()
window = Tk()
frame = Frame(window)
canvas = Canvas(window,width = WIDTH, height = HEIGHT, bg ="white")
graph = FigureCanvasTkAgg(fig, master = window)
window.title("Virus Simulation")
toolbar = NavigationToolbar2Tk(graph,frame)
def start_ui():
window.geometry(str(int(WIDTH)*2)+"x"+str(int(HEIGHT)+50))
frame.pack(side=BOTTOM)
graph.get_tk_widget().pack(side='right',anchor='nw',expand=True,fill='both')
canvas.pack(side='left',anchor='nw', expand = True, fill ='both')
toolbar.update()
def ui_redraw(person,day):
'''draw every"person" onto the canvas'''
if(person.status==variable.disease_status.VULNERABLE):
if(person.masked and person.vaccinated):
color="#00008b"
elif(person.masked):
color="#ADD8E6"
elif(person.vaccinated):
color="#4d4dff"
else:
color="white"
if(person.status==variable.disease_status.INCUBATION):
color="yellow"
if(person.status==variable.disease_status.ASYMPTOMATIC):
color="orange"
if(person.status==variable.disease_status.SYMPTOMATIC):
color="red"
if(person.status==variable.disease_status.IMMUNE):
color="green"
if(person.status==variable.disease_status.DEAD):
color="black"
Ball(canvas,person.location.getX()/10,person.location.getY()/10,5,color)
canvas.create_text(55,20, text="Day "+str(day),fill="black", font=('Helvetica 24'))
def draw_popularPlace():
'''draw the popular placesin canvas'''
for place inppmodel.popularPlaces:
Ball(canvas, place.getX()/10,place.getY()/10, 10, 'pink')
def ui_refresh():
'''refreshcanvas'''
window.update()
def ui_delete():
'''clearcanvas'''
canvas.delete("all")
def print_graph(hours_past,max_infected_at_once,vulnerable_history,incubation_history,asymptomatic_history,symptomatic_history,infected_history,immune_history,dead_history):
'''graph the simulation fromgiven data'''
plot1.clear()
plot1.set_xlim([0,hours_past])
plot1.set_ylim([0,variable.NUM_PEOPLE])
plot1.set_xlabel("Hours #")
plot1.set_ylabel("Population #")
plot1.axhline(y=max_infected_at_once,color="red",linestyle="--",label="MaxInfection")
plot1.plot(vulnerable_history,label="Vulnerable #",lw=3,color='blue')
plot1.plot(incubation_history,label="Incubation #",color="yellow")
plot1.plot(asymptomatic_history,label="Asymptomatic#",color="orange")
plot1.plot(symptomatic_history,label="Sysptomatic#",color="red")
plot1.plot(infected_history,label="Total Infected#",lw=3,color="purple")
plot1.plot(immune_history,label="Immune #",lw=3,color="green")
plot1.plot(dead_history,label="Dead #",color="black")
plot1.legend(loc='lower center', bbox_to_anchor=(0.5, 1), ncol=3,fancybox=True, shadow=True)
graph.draw()
def end():
'''end page forui'''
window.mainloop()
Appendix I
“ball.py” creates balls in “ui” to represent each“person” object
class Ball:
def __init__(self,canvas,x,y,diameter,color):
self.canvas = canvas
self.image = canvas.create_oval(x-diameter,y-diameter,x+diameter,
y+diameter,fill=color)
Appendix J
“sir.py” can calculate the infection rate and graph a SIR modelbased on data collected from the simulation
import excel
import matplotlib.pyplot as plt
import numpy as np
import variable
def Average(lst):
return sum(lst) / len(lst)
def cal_sir(S, I, R):
infection_rates = []
recovery_rates = []
for i inrange(0,len(S)-1):
infection_rate = (S[i]-S[i+1])/I[i]
#excel.write(i+1,4,infection_rate)
recovery_rate = (R[i+1]-R[i])/I[i]
#excel.write(i+1,5,recovery_rate)
if(infection_rate != 0):
infection_rates.append(infection_rate)
if(recovery_rate != 0):
recovery_rates.append(recovery_rate)
# print("infectionrate is in hour ",i," is: ",infection_rates[i],"recovery rate is in hour ",i,"is: ",recovery_rates[i])
avg_infection_rate = Average(infection_rates)
avg_recovery_rate = Average(recovery_rates)
print("Average infection rate is: ",avg_infection_rate,", Averagerecovery rate is: ",avg_recovery_rate)
def cal_infection_rate(people,hours):
'''calculate the infectionrate for a given population'''
average_infect = 0
for p inpeople:
average_infect+=p.infected
average_infect=average_infect/len(people)
# print(average_infect)
levels =[]
for p inpeople:
if(p.infection_level != -1):
if(len(levels) -1 < p.infection_level):
levels.append(1)
else:
levels[p.infection_level] += 1
# for i in range(len(levels)):
# print("Level",i," has ",levels[i])
infection_rates = []
for i inrange(len(levels)-1):
infection_rates.append(levels[i+1]/levels[i])
infection_rate = Average(infection_rates)
# print(infection_rate)
average_infection_rate = (average_infect+infection_rate)/2
print("The average infection rate of two method is ",average_infection_rate)
SIR.graph_SIR(hours,average_infection_rate,1/7.5)
class SIR():
'''graph the SIRmodel'''
def __init__(self, days,infection_rate, recovery_rate, starting_infected_porportion = 0.005):
self.DAYS_NUMBER = days
self.dt = 1 # time steps in day
self.BETA = infection_rate
self.GAMMA = recovery_rate
self.S = [1] # susceptible
self.I = [starting_infected_porportion] #infected
self.R = [0] # recovered
self.time = np.arange((self.DAYS_NUMBER + 1) * 24) * self.dt
def model(self):
for hour in range(self.DAYS_NUMBER * 24):
self.S.append(self.S[hour] - (self.BETA / 24) *(self.S[hour] * self.I[hour]) * self.dt)
self.I.append(self.I[hour] + ((self.BETA / 24) *self.S[hour] * self.I[hour] - (self.GAMMA / 24) * self.I[hour]) * self.dt)
self.R.append(self.R[hour] + ((self.GAMMA / 24) *self.I[hour]) * self.dt)
def plot(self):
fig = plt.figure(1)
fig.clf()
plt.plot(self.S,'b', lw=3, label = 'Susceptible')
plt.plot(self.I,'r', lw=3, label = 'Infected')
plt.plot(self.R,'g', lw=3, label = 'Recovered')
fig.legend()
plt.xlabel('Hours')
plt.xlim([0, 24 *(self.DAYS_NUMBER)])
plt.ylabel('Fraction of Population')
plt.show()
def graph_SIR(hours,infection_rate,recovery_rate):
sir = SIR(int(hours/24), infection_rate,recovery_rate)
sir.model()
peak = 0
for i in sir.I:
peak=max(i,peak)
print("SIR peak infection: ",int(peak*variable.NUM_PEOPLE))
sir.plot()
Appendix K
“excel.py” include the function to create and write excelfiles
import xlwt
wb = xlwt.Workbook()
sheet1 = wb.add_sheet('Data')
def start():
write(0,0,"Hour #")
write(0,1,"S #")
write(0,2,"I #")
write(0,3,"R #")
write(0,4,"infection rate")
write(0,5,"recovery rate")
def write(row,column,context):
sheet1.write(row, column, context)
wb.save('Data.xls')
Appendix L
SIR model formula