In previous posts, we've looked at the probabilistic math behind estimating the spread of infection, and also estimated the chances of acquiring COVID-19 under various conditions given daily exposure. In this post, we will finally look at how it all comes together, and some initial results from some more intricate modeling. We're not taking the approach many epidimiologists use that involves choosing an R value (how many people, on average does one spread it to) and then propagating the numbers from there. Rather, as in prior posts, we're looking at the probabilities: how mask wearing and social distancing decrease the probability of acquiring COVID-19, and then starting our model with the probabilities implied by the rate of infection in the community at large. Ultimately, for the many campuses which are opening shortly, the surrounding community infection rate is the most relevant factor in success or failure of any mitigation strategy. If students are routinely mixing with the outside community, campus strategies in limiting the spread will be marginal at best.
Another factor that we will include in our model this time is the possibility of airborne transmission such that poor ventilation which does not bring in fresh air, and which is directed improperly (for example, it flows from a potential sick person towards healthy individuals) can spread the virus. This has been demonstrated previously with Legionaire's disease and was a concern with the H1N1 pandemic in 2008-2009. A recent paper from Morawska et al (May 27, 2020) confirms the possibility of indoor transmission in this manner, stating:
"Multiple studies provide strong evidence for indoor airborne transmission of viruses, particularly in crowded, poorly ventilated environments (Coleman et al., 2018, Distasio and Trump, 1990, Knibbs et al., 2012, Li et al., 2005, Moser et al., 1979, Nishiura et al., 2020)."
In particular, recirculating air is to be avoided. Considering that many places are simply "updating their filters" and turning the air on higher, it's not clear that this type of mitigation will be effective. Furthermore, most universities have HVAC systems that are relatively haphazard. Some are brand new and state of the art, and others, not so much. It's pretty much a crapshoot regarding which building you are in and which classroom. Some classrooms, such as organic chem labs, have fume hoods with suction. One would presume that such areas are safer that the generic classroom.Our model today treats ventilation as a variable. If ventilation is correctly implemented (adequate), then social distancing is considered to be effective. If, on the other hand, air is being recirculated, you can be far away from someone who is sick, but for all you know, you're being hit with virus particles from ANOTHER classroom when the vent blows on you. Many HVAC systems have downward blowing rather than upward sucking air vents. (But this is the subject of another post later.) So if you're in one of those improperly ventilated rooms, we model that social distancing is ineffective, and all you have is your mask. It is likely that the truth lies somewhere in between.
This model is much more sophisticated the prior modeling shown on this site. It accounts for social distancing and masking as before, but now also includes ventilation, when someone is contagious, and also if they are asymptomatic. In this model, we presume that someone is contagious between 2-20 days after acquiring the virus, and that if they are symptomatic, the symptoms will show up on day 5. In reality, contagion is not a step function (yes or no over a period). Rather it is something like a Poisson distribution with low lambda (as shown on Wikipedia) where you are most contagious at the start of it all. This sort of complexity may make it into the model later.
Other assumptions of this model is that everyone enters class everyday with the possibility of community based infection. When you go home, you re-enter the community cesspool, and you have the possibility of coming back infected based on the community infection rate. Likewise, we assume that if you are infected, you have a 40% chance of being asymptomatic (if you are a young person), and as such, you might just stay in class because you don't know you're sick. For those who are symptomatic, day 5 is when they are ejected from class because they have either been told to leave ("stop sneezing everywhere!") or they have realized that they are sick in some way, and have chosen to do the right thing. While they would, in theory just be out for 2-3 weeks, in practice, as an educator, very few students in my teaching past have been able to catch up in physics after missing 2-3 weeks. Therefore, once they are out, they are OUT, and we no longer consider them in our probabilities. Also, unlike prior models, this one can keep track of class days and weekends. It's assumed that classes meet only Monday, Wednesday, and Friday, and that weekends are off.
Here's what the configuration file for the simulation looks like:
/***************************** Initial Parameters **********************************************/
var daysTillVisiblyContagious = 5; // Days until you KNOW you have COVID after being infected
// Note that this can be changed to a higher number in case people are waiting for test
// confirmation before taking steps (Yes this has happened, especially when symptoms seem mild.)
var dayContagious = 2; // Day you are contagious after being infected
var dayNotContagious = 20; // Day you stop being contagious
var sympRate = 0.60; // 60% chance of being symptomatic (find source)
var dailyModel = false; // Run classes daily (for example to consider a dorm);
// https://www.medrxiv.org/content/10.1101/2020.03.24.20042606v1.full.pdf
// p = 0.022 // 18-45 years, it goes up as you get older, also, this is just initial data
var pSpread = 0.022; // risk of infection if exposed -
// this is probably low as there are multiple contact points not considered
// Additionally, it does not consider time of contact
var pInf = 0.001049; // 1662/1.586e6 (those infected over last 14 days/ Philly population)
// Real infection rate may be 6-24 times greater - here go with 10x greater
// https://jamanetwork.com/journals/jamainternalmedicine/fullarticle/2768834?guestAccessKey=7a5c32e6-3c27-41b3-b46c-43c4a38bbe00&utm_source=For_The_Media&utm_medium=referral&utm_campaign=ftm_links&utm_content=tfl&utm_term=072120
pInf = 10*pInf;
// Mask wearing
// https://www.thelancet.com/journals/lancet/article/PIIS0140-6736(20)31142-9/fulltext
// Reduction due to mask wearing: OR = 0.15 [0.07-0.34]
// Reduction due to 1m distancing: OR = 0.18 [0.09-0.38]
var pMask = 0.15; // Will adjust these with slider later. Build the model first
var pDist = 0.18;
This gives you a sense of the assumptions going in. There is also, in this model, the ability to assign a student to a cohort and a class so as to track where they are infected, if infected. So when a student is created using the makeStudent() function, they have all kinds of properties one can keep track of:
function makeStudent(myClasses,isInfected,day) {
this.isInfected = isInfected;
this.infectArr = []; // Is infected or not
this.daysInfected = day;
this.whereInfected = ''; // Which class student was infected in
this.whereInfectedVent = 'NA'; // Was ventilation effective where infected?
this.isInClass = true;
this.isSymptomatic = false;
this.isContagious = false;
if (isInfected) {
// if isInfected, and daysInfected > 2 & <= 20 then is contagious
if (day > dayContagious && day <= dayNotContagious) {
this.isContagious = true;
}
this.whereInfectedVent = 'Unknown';
var ran = rand(); // Generate the random number between 0-1
if (ran < sympRate) {
//console.log(ran);
//console.log('I am symptomatic!');
this.isSymptomatic = true;
if (day <= daysTillVisiblyContagious ) {
this.isInClass = true;
} else {
this.isInClass = false;
}
} else {
this.isSymptomatic = false; // They will not be symptomatic
this.isInClass = true;
}
}
// if isAsymptomatic, then will remain in class as a spreader
this.wearsMask = true; // In class only
this.socialDistances = true; // In class only
// Presume that if they don't wear masks at home, then they aren't doing the pod thing
// and have a higher probability of having COVID <- Not yet implemented
// https://pittsburgh.cbslocal.com/2020/07/17/where-are-people-wearing-masks/
// Presume 60-90% are wearing masks in public and are likewise social distancing
// average is 75%
var ran = rand(); // Generate the random number between 0-1
if (ran < 0.75) {
this.inPod = true; // Social distances at home
} else {
this.inPod = false;
}
this.myClasses = myClasses; // Five myClasses
this.dropEndOfDay = false; // Drop the student at the end of the day
// could also have age, gender, severity, etc here.
// Also define which myClasses they are in??? or use separate object/array?
return this;
}
Likewise, stats for a given class can be tracked as well:
function makeClassArr(name, number, sdEffective ) {
this.name = name;
this.initialNumber = number; // initial number of students in class
this.number = number; // current number of students in class
this.propInfected = []; // daily array of proportion of class infected based on current numbers
this.currentInClass = [];
this.NinfectedHere = 0; // Number of cumulative infections starting in this class
this.sdEffective = sdEffective; // Is social distancing effective or not due to poor ventilation?
return this;
}
At this point, I'm going to skip to some results. I ran two major takes of the model, first involving nearly 60 classes (more small ones) and 180 students divided amongst those classes. In this case, I wanted to separate out the effects of class size and classroom ventilation. So the large number of classes for the small number of students was done to ensure that class sizes could be kept low, and I could track the cohorts separately. The model was run 100 times over the first 60 days of the semester. First, let's look at where people get infected.
The above graph shows the averages for the 100 models that were run. After 60 days, on average 60.2% of students were infected. However, 65.3% of these came from the community at large, NOT from the the campus. This doesn't let the campus off the hook. 28.1% of infections on campus came from larger classes whereas only 6.4% of infections came from smaller classes. Divided by ventilation type, of all the infections, 82.3% of on campus infections were in areas with poor ventilation and 17.7% were in areas with good ventilation.
Looking at mean growth rate within classes regardless of infection source:
we see that larger classes have a higher rate of spread than do smaller classes IF the ventilation is inadequate. [Note: please excuse the error bars going below zero!]. However, even with adequate ventilation, after 60 days (end of October-ish), we can count on 5% of a given class to be infected. Given that in this model there were 60 classes, this is still an appreciable number.
What happens if we just let students mix and match classes without separating out students who are in large and small classes, and equally, allowing them into classrooms that are both well and poorly ventilated? Here's the first graph again:
In this case, an average 58.7% of students were infected. This is probably not significantly different from the prior scenario, but I haven't run the stats yet. In any event, the results are very close. Of these, 62.7% came from the community and not from the campus, 24.8% of infections came from larger classes, and 12.4% of infections came from smaller classes. The division by ventilation type is, actually the same as in the prior model: 82.3% of on campus infections were in areas with poor ventilation and 17.7% were in areas with good ventilation. I suspect that where we would see significant differences in the models when they are ultimately tested, is the ratio of infections coming from larger vs smaller classes.
Let's follow that up looking at the time data:
Okay, so we have more class sizes here, with the largest class (60 students) having adequate ventilation. The rates of infection are a bit lower in this case, but that may be due to a lower total number of students (120 vs 180 in the prior simulation). Most interestingly, in these results, as the class sizes get larger, the ventilation outcomes converge implying that if you don't do ventilation right everywhere, it probably doesn't matter that you're doing it at all.
Now, to be perfectly clear - these results are due to a quick (about a week to write and test) model and the structure of the inputs matters. For example, the mixed model should probably have been limited to class sizes of 15 and 60 as with the earlier model. However, the way the code is set up, it's difficult to do this easily. One wants to compare apples to apples. Before these results are ready for publication in a journal, a great deal more work involving examination of model stability should be done.
Nonetheless... I believe that there are a few key points that this early work indicates:
- Surrounding community spread is ultimately quite important. If you are in an endemic area, and your students and faculty are not isolated, that endemic spread will spread to your campus. Remember that one of the initial inputs to this model is the community infection rate. If it's higher, then we expect more infection to come back to campus every day when there is class - and then the campus becomes a vehicle for further spread.
- When cohorts of students stay together, smaller classes and better ventilation systems are probably better for preventing spread.
- When cohorts of students mix, mitigating measures like ventilation may not be as effective.
- When compared to other work of this nature,(which I've hosted on niiler.com since the authors from a big university wish to remain anonymous), the results seem reasonable. In this paper which considers only on-campus propagation of the virus (but also a latency period and asymptomatic infection), at the end of 60 days, nearly a quarter of the campus population is infected. When we look at the bar graphs above indicating campus spread, this is quite close to our numbers. (Again, there is some nuance, but given that we're starting with completely different codes and methods, the fact that we are within each others error bars is comforting).
If you are hankering for a better look at the JavaScript code (post-processing was done in R after harvesting the information in the "studentResults" and "classNumbersResults" variables from the JavaScript console), you can find it here. It's assumed that you have some JavaScript and HTML experience. As time permits, I will try to craft a more user friendly simulation online.
In the meantime, wear a mask when you go out, social distance and avoid crowds, and remember to take this thing seriously. There are a lot of otherwise healthy individuals who have had COVID and are not so healthy afterwards. We still don't know the long-term side effects.