During the coronavirus outbreak I was at home and I decided to review some of the things about object-oriented programming that I had learned some time ago. I didn't find anything worth coding untiI watched this 3blue1brown video (highly recommended) modelling the spread of a disease, evaluating the effect of different experiment setups and the effectiveness of different containment measures on the behavior of the cases over time.
I decided to code a far more simple animation with Python and Matplotlib also using a SIR model, which divides a population in Susceptible, Infected and Recovered individuals in each particular time. The simulation consists of an array of dots moving randomly through a 100x100px box. A susceptible individual has a given probability of getting the disease from an infected individual if he gets within a certain radius (this probability can be determined in the real world by how often do we wash our hand or touch our face), and after a certain amount time being sick he recovers and can no longer be infected.
As you can see in the picture, the model behavior reassembles the real behavior of the virus. At the beginning there is a phase of exponential growth, which is gradually substituted by a phase of linear growth until the peak is reached. Then, as more people start to heal and less people is left to infect, the number of infected starts to drop until it finally gets to zero. When this happens, the recovered curve stops growing, as there is no one left to heal.
The model includes parameters that can be modified to play around with the simulation, such as the number of individuals, the distance of transmission, the probability of transmission, etc. It also features a "quarantine mode" in which is possible to fix some of the points in its initial position through the whole simulation (as if they stayed home). As you will see at the end, this actually has the effect of "flattening the curve".
You can download the code and try it yourself!
Step 1: Creating a Python Class representing an individualAs the main objective of my project was to review some concepts of object-oriented programming, I started by creating a class to represent an individual taking part in the simulation. Each individual has the following attributes:
- ID and name: a unique number and name used for identification purposes.
- Status: three Boolean variables representing if the individual is Susceptible, Infected or Recovered.
- Position: two coordinates representing the position of the individual in each time.
- Speed: the speed with which the individual will move through the simulation area.
- Recover time: time that the individual takes to recover.
- Infection time: the moment of the simulation in which the individual got infected.
- Fixed?: a Boolean that tells if the individual is quarantined.
I also defined some methods to be used throughout the simulation. They allow to change the status of the individual, get and set its position, animate the movement frame by frame, calculate the Euclidean distance to another point, etc. They can be found commented in the code.
Finally, I saved this class on a separated file to be imported in the code that runs the simulation.
Step 2: Coding the simulationAfter creating the class, I coded the simulation in a different file. The first step is, as usual, importing the necessary packages including the class created in step 1 (both files must be saved in the same folder so the code can work).
Then the following simulation parameters are defined (the ones you can play with):
- Number of individuals. if it's too high (>500 in my PC) simulation will run very slowly.
- Percentage of infected individuals at the beginning of the simulation.
- Radius of transmission in pixels.
- Probability of transmission in percentage.
- Recover time in number of frames
- Percentage of the population not able to move (in quarantine).
Later all the individuals are created. A scatter plot is created and configured to host the dots moving and a 2D line plot is created and configured to display the curves showing amount of infected and the recovered at each time.
Finally, I coded the function that is continuously executed to generate each frame of the animation. It checks how much time has each individual been sick, and if it's currently infected it search for susceptible people within the transmission radius to infect them given the transmission probability. It also calculates the new position of each dot in the box, counts the number of infected and recovered people, and updates the information on the line plot.
You can find the code to run this simulation in your computer at the end of the page, if something doesn't work out of the box write me a message. The variable names are written in Spanish but the code is commented in English, however if you would like to get deeper into how the code works you can also reach me.
Step 3: Analyzing the resultsI anticipated most of the results at the beginning, which can be summarized saying that the simulation does represent partly the real behavior of the Coronavirus, although this is still a very limited model.
As I said, in the model the quarantine does have the effect of flattening the curve, reducing its peak magnitude. The two images below were generated by the simulation running with the exact same parameters, but in the second one 70% of the individuals remained fixed in their initial position, and as you can see the difference is significant.
I hope this encourages you stay home and download the code to try it yourself, maybe changing parameters and running the simulation over and over you can discover new things that I missed.
PD: I'm a spanish speaker, so if you find any mistakes in the text please let me know!
Comments