visualization of a virus spreading considering everything going on right.
Now with the corona virus pandemic we want to use programming as a way to dig into what factors can make a virus like covin 19 so deadly many outlets are creating informative graphs and visualizations right.
Now using data science and we were particularly inspired by the one in The Washington Post we definitely recommend you check that out and the links in the description below today we’ll walk through how to build and run this data visualization using the most current statistics on the corona virus we’ll be coding in Python using.
Numpy and matplotlib and all of our code will go into a file called virus dot pi a link to the completed project repo is in the description of this video so definitely check that out and follow along our hope is that by watching this video you’ll learn something about programming and pandemics with that let’s get started so let’s start off by importing all the libraries and data that we’ll.
Need today first we import matplotlib PI plot as p LT and matplotlib dot animation as a.
Nice that kite gives us completions there we’ll be using these for our data visualization we then import.
Numpy as NP and that’s what we’ll.
Need for some mathematical functions on the erase let’s also create RGB tuples to represent the colors will use to encode health status as uninfected infected recovered and unfortunately dead will use the dictionary to hold information specific to codon 19 this will make it so that we can easily repurpose our animation for other contagious diseases by passing in a different dictionary with the relevant information in fact we’ll have a video comparing Co vid to other contagious diseases so make sure to subscribe to our channel so you don’t miss that first we create and virus class which will hold all of our functionality the constructor for our class will take one argument grams which will be a dictionary with information about the virus in question such as its basic reproduction.
Number its incubation period the distribution of mild and severe cases this is among many other parameters as well so we’ll cover this more in detail later.
Next let’s make our plot we’re going to use a polar plot which has a circular graph that allows our visualization to show the virus spreading from the center outwards this is like plotting points on a coordinate plane but instead of using x and y coordinates to specify any point we use the theta or our coordinate pairs to specify points within a unit circle where theta corresponds to the angle in radians above the positive x-axis and our corresponds to the distance from the origin first we create an empty matplotlib figure then we instantiate a polar plot by calling add subplot with 1 1 1 and projection equals polar the 1 1 1 just means a 1 by 1 grid using the first sub lot this function call returns on axes object let’s modify the axes to remove the grid lines and the tick marks let’s then set the radius of our plot to 1 by calling set Y lim 0 1.
Next we create our annotations which display the.
Need to text that gets updated throughout the program’s duration let’s first create the date X which we do by calling self access annotate let’s display day 0 centered at the top of our plot this corresponds to a theta value of PI over 2 which specifies the y-axis and an hour value of 1 which specifies the top of our unit circle we set the horizontal alignment to Center and the vertical alignment to bottom it may seem counterintuitive that we place text at the top of our plot by specifying vertical alignment at the bottom but this means that the bottom of our text will align with the point we specified thus placing the text above our plot as desired then let’s create 3 annotations below our plot to display the.
Number of infected people the.
Number of deaths and the.
Number of people who have recovered we create these the same way as the day annotation but alter the values to position at the bottom let’s make the text color of each of these category annotations correspond with the.
Note colors in our animation.
Now we create the member variables that we’ll be updating throughout our calculations we.
Need the day.
Number recovered and.
Number of deaths all initialized to zero we create two variables to track the.
Number of infections one to track the current.
Number of infections which we’ll use for the infected annotation and one to track the total.
Number of infections which we’ll use in various ways such as the logic for stopping the simulation.
Next we store values from our input params dictionary in variables the basic reproduction.
Number denoted R.
Naught is a measure of the contagiousness of a disease so that means it represents the expected.
Number of cases directly generated by a single infection in a hypothetical population that is entirely susceptible to the disease we also store values for the rates of mild cases severe cases and fatalities as well as the serial integral which is the average time between successive cases in a chain transmission for each infected person there is some amount of time between the emergence of symptoms and the outcome of the disease whether they recover or whether they die this interval depends on the severity of the symptoms and tends to be longer for those who ultimately died the various ranges represented as days are stored in params we add these ranges to the viruses incubation period to reflect the entire animal of the disease from infection to recovery or death here we can see there are three different durations for this virus those with mild symptoms will ultimately recover and the time it takes to do so is represented on the low end as mild fast and on the high end is mild slow those with severe symptoms who ultimately recover will do so within the interval bound by severe fast and severe slow and those with severe symptoms who ultimately succumb to the disease will do so within the interval bound by death fast and death slow.
Now let’s create a dictionary called mild to track our mild cases over the.
Next year hopefully our pandemic won’t last that long and our simulation suggests that it won’t but we’re just using a year as the upper bound of our time here in the mild dictionary the keys signify the recovery time in days for infected people with mild symptoms ranging from mild fast to 365 the value of each key is another dictionary with two key value pairs one for Thetas and another for ours both of these values are initialized to empty lists but they will get populated with theta and R values that when taken together specify the individuals with mild symptoms that recover on that given day this means the X element of the theta list combined with the X element of the our list specifies a point on our plot that gets updated to recovered let’s.
Now create a severe dictionary which will have two keys recovery and death here we take the same approach to complete the severe dictionary as we just did with the mild dictionary for a last addition to the constructor we.
Need to put restrictions on the extent to which our virus can spread on a given wave since a single infected person will.
Not come into contact with an entire population of 4,500 people in one single day we.
Need to restrict the potential spread of the virus to just a subset of this population we do this by creating two member variables exposed before and exposed after initialized to 0 and 1 respectively exposed before represents the amount of people that have been exposed to the virus already and exposed after represents the total.
Number of people who will be exposed to the virus by the end of the current wave the effect of all this is that our virus will spread in waves from the center outward to a subset of our population.
Now we create a function called initial population that initializes our plot with a population of 4,500 let’s set.
Num currently infected and total.
Num to 1 representing patient zero we.
Need two lists cell Fatah’s and self dot ours which we’ll use to plot points in our visualization and to keep track of each person in our population these are just like the list we created for mild severe and fatal cases but they represent the whole population rather than a particular segment these two lists will comprise our 4,500 data points each defined by a theta R coordinate pair let’s do this using the golden spiral method explained on stackoverflow by CR drost and the link to that thread is available in the description below here so.
Now we have all of our 4,500 data points let’s use the scatter function to plot them making the size of the points 5 and the color gray then let’s update the color of patient zeros point to red four infected will call scatter on the first data point in our two arrays which is at the center of our plot let’s give patient zero mild symptoms with the quickest recovery so we append the zeroth data point in our mild dictionary at mild fast.
Now let’s make sure to call initial population to back up in our constructor let’s run our code and take a look at what we’ve got we create a temporary instance of our virus class with the Cova 19 parameters and call PLT show right.
Now we’re just looking at a snapshot of our simulation just check that everything is working as expected and soon we’ll be able to run the whole simulation from a main function before we get into the main part of the simulation let’s take a quick break so I can tell you how to code this faster with kite the AI coding assistant that I’m using in this video whether you’re.
New to Python or already a pro you should try out kite as you’re autocomplete to reduce your keystrokes and save time programming I use a free plugin for your code editor that uses machine learning to save you keystrokes while you’re programming so if you’re using atom vyas code spider pycharm sublime or vim kite will seamlessly integrate into your coding workflow kite can complete entire lines of code and it has a feature called intelligent snippets that will help you fill in arguments and Method calls with variables defined earlier in your script the window on the right side of my screen here is also a kite feature called the kite copilot it automatically shows you relevant Python documentation while you type based on your cursor location this saves you time from having to Google search for docs the best part of kite is that it’s free and you can download it from the link in the description below all right.
Now let’s get back to our code.
Next let’s create a function spread virus that calculates the.
Newly infected people using a serial interval of seven days remember that we’re spreading the virus in waves the.
Number of people exposed in a given wave is the difference between exposed before and exposed after so at the beginning of a given wave we set exposed before to the value of exposed after of the last wave that we saw and we check whether the current day is a multiple of our serial interval and whether our exposed population is less than our total population of 4,500 if day is a multiple of our serial interval then we know to spread the disease and if the.
Number of exposed people equals our total population then we know there is.
No one left to infect so inside our conditional we calculate the.
Newly infected people by multiplying the R.
Naught value by the.
Number of people who are already infected then round to the.
Number we store this as the variable.
New infected since.
Not everyone who is exposed to the virus ultimately contracts the disease we.
Need to increment exposed after by 1.1 times.
New infected meaning 10% of our population is.
Not susceptible to the contagion for the last wave we.
Need to ensure that our process of assigning exposure doesn’t surpass our total population of 4,500 so when exposed after is greater than 4500 that is when the logic of our expanding waves overshoots our population limit we subtract exposed before from 4500 and multiply the result by 0.9 to obtain.
New infected then we set exposed after to 4,500 after this conditional we add.
New infected to.
Num currently infected and to total Naaman fected.
Now we randomly select our.
Newly infected people let’s call em P dot random choice and we can look to our kite copilot for reference on its arguments let’s pass in the range from exposed before to exposed after.
Noonim infected and replace equals false so that it doesn’t give us the same values multiple times then we use self dot Fatah’s and self that ours with.
New infected indices and list comprehensions to get the theta and our values for these indices after this conditional block we increment day by one after identifying our.
Newly infected people we have to sign them symptoms so that means mild or severe and that will determine how long the disease will last for them let’s create a function assign symptoms where we calculate the.
Number of mild cases and severe cases in this.
New wave of people using the information stored in params we randomly choose a set of indices from.
New infected indices that gets assigned mild symptoms using NPR and my sand call this mild indices we then use list comprehension to get the remaining indices by finding the set difference between.
New infected indices and mild indices to calculate the percentage of severe cases that recovered we use one minus the fatality rate divided by the percentage of severe cases we use this value to sort our severe cases into two groups severe cases that end in recovery and those that unfortunately don’t let’s create two empty lists called severe indices and death indices if there are any severe cases in a given wave as revealed in remaining indices we use the percentage we just calculated to sort severe cases in the correct proportion to our two.
New lists severe indices and death indices this is done the same way as we did with mild indices with an umpire random choice function and list comprehension.
Now that we’ve randomly assigned data points with symptoms and outcomes it’s time to assign the exact day each case will reach its outcome let’s start with mild cases first we calculate the lower and upper bound for the day of their recovery we do this by adding self dot day to self dot mild fast for the low end of our range and adding self dot day to self dot mild slow for the high end then we loop over mild indices and for each iteration randomly choose a recovery day within this range using.
Numpy random R and int we then retrieve the theta and R values of this particular data point using the index with self dot Fatah’s and self dot RS of our total population finally we update our self dot mild dictionary with this information for the key that corresponds to the recovery day in question we append the theta in our coordinates to the lists that are sorted as values to the respective keys we use the same logic to determine the duration of severe cases that end in recovery and severe cases that unfortunately don’t that’s it for this function so let’s just make sure to call it back up in spread virus.
Next we make a function called update status that will update the color of plot points when a recovery or death occurs let’s first do the mild cases we retrieve the lists of theta our coordinates from the mild dictionary for the current day which represents those with mild symptoms who recover today then we pass these lists to the scatter function and set the color to green to denote recovery after that we add the.
Number of recovered patients which we can get by taking the length of either list and we add that to self dot.
Numb recovered we then subtract this.
Number from self.
Numb currently infected.
Now we do the same thing for people with severe cases that end in recovery and likewise color than green and finally we do the same thing for people with severe cases that end in death but we set the color of these data points to black.
Now let’s return to spread virus function and call update status right after we increment self dot day along with updating the color of our plot points we.
Need to update the annotations that we created in our constructor so let’s create a function called update text for this we use the function set text on each of our text member variables which track the day as well as the amount of infections recoveries and deaths let’s begin with the day variable we set the text of the day variable by calling self dot day text dot set text we pass in the string day formatted to be concatenated with self dot day which is the dynamic part of this text variable that increments with each passing day we set the infected text variable in the same way we call self dot infected text dot set text and pass in the string infected formatted to be concatenated with self dot.
Num currently infected same with the deaths text variable we passed the string deaths formatted to be concatenated with self dot.
Num deaths and into self dot deaths text dot set text and again same with the recovery text variable we passed the string recovered formatted to be concatenated with self dot.
Num recovered into self dot recovered text dot set text that’s it for this function so let’s return to spread virus and call it right after update status and.
Now we get to start the star of the show matplotlib animate class particularly we’re going to use the function func animation the animation shows our plot to update continuously while the program is running so let’s create a function called animate for this we create an animation called self annum by calling an e dot func animation and passing it to our figure the spread virus function the keyword argument frames with.
No value for.
Now and repeat equals true if we look over at the kite co-pilots documentation for func animation and scroll down we see that frames can be a generator an iterable or a.
Number of frames the value we pass for frames determines the iteration in which we terminate the repeated calls to spread virus so let’s create a function called gen4 generator which we will pass to frames in our animation we know that the virus has run its course once every infected person has either recovered or died from it so let’s say while self.
Numbs deaths plus self dot.
Num recovered is less than self dot total Naumann fected yield then we return to our func animation call and set frames equal to self dot yen so we have our animation that will repeatedly call spread virus until every infecting case has reached its outcome in each wave we update the color of points for.
New cases of infection and existing ones that have reached an outcome we’ll implement one more animation so that the.
New case statuses of a.
New wave get updated gradually which is more aesthetically pleasing rather than appearing all at once let’s go back up to spread virus we left off by making lists of the Thetas and R’s for all the.
Newly infected data points on a given day we’re going to make another animation to make our plot points get updated in a more appealing way these animations run in separate threads which means our other animation for spread virus will keep running until we pause it we pause it by calling self anime vent source stop we’ll.
Need two functions to get this visual effect the first is our function for plotting points individually which we call one by one it takes several parameters AI fait des ours and color then we call self axis scatter and pass the Thetas at AI ours at I set the size equal to five and the color equals color the other one is a generator function called chunks this divides a given list into chunks of equal size we.
Need this function because some waves are too large to plot point by point it take forever so we’re going to plot them by chunk and chunk instead we do this with a for loop over the range of our population yielding each chunk from i to i plus.
N let’s return to spread virus we create a conditional that determines how we want to animate based on how many points we.
Need to plot for an if statement let’s say that if the length of.
New infected indices is greater than 24 create a variable called size list that’s the length divided by 24 rounded to the.
Nearest integer feel free to play around with this value we decided to use 24 is our threshold because that makes the updates to our animations.
Nice and smooth let’s then create theta chunks using our chunk function passing it Thetas and size lists and casting the result to a list let’s do the same for the our chunks time for the animation let’s call this one self-tan two and once again call an e dot func animation with our figure and this time passing it one by one with the following arguments interval equals 50 and this means 50 milliseconds between each frame frames equals the length of theta chunks and Fargas equals theta chunks are chunks and read in our else statement which runs the length of the.
New infected indices is less than 24 we do the same as our if statement except we set frames to lengths of Thetas and Fargas Thetas ours and read.
Now all we.
Need to do is pause annum to when we call one to one and resume annum let’s go back to the 101 function and let’s add a condition that once we’ve plotted all the points in a given wave we stop an M 2 and we start anam the last step of our project is creating a main function we create a coronavirus instance of virus by passing it kovat 19 params defined at the top of our file then we call coronavirus animate to start our animation and plot that show to display our plot finally we can add this code fragment so our program runs directly from the command line and we’re finally done let’s run our coronavirus simulation [Music] that’s how to make a visualization of a virus spreading using Python I don’t know about you but for me after digging through all this data it’s definitely a bit scary taking a look at how quickly and vastly a virus like this can spread so it’s important that we really take that into consideration and we respect what our governments locally or.
Nationally are advising to slow this contagion all in all from all of us at kite we wish you get health and safety so please be careful and smart thank you for taking the time to watch this video hopefully it’s helped you learn a lot about Python and especially about pandemics again check out the link in the description below for the github repo hope you get that running and check it out even further if you haven’t yet already in an upcoming video we’ll run this simulation on a handful more of well-known epidemics that we’ve seen in the past so make sure to subscribe to our channel so you don’t miss it also make sure to download Kight because you’ll code faster and smarter and finally thanks for watching see you on the.