Skip to content

Commit 5dc08ee

Browse files
mattiesansevRadhika Ahujalaurelrwoodsahujaradhikakandrewz
authored
Covid model (#97)
* added unclean datasets * added d3network graph * minor change * initial map + LA county boundary * fixed position of graph * neighborhood boundaries * interactivity on map * python scraping script * added a cron job * added script to add confirmed cases field to map * add hospitals, put cases on map * turned on scheduler with commented out jobs * Delete schedule_scraper.yml * updated scraper workflow * temporary change for testing * Update schedule_scraper.yml * add per capita toggle. add LB & pasadena cases * switched dataset for hospitals, fixed typo. * add layer control * process data in python script - write directly to geojson * fix bug * base line chart * added beds lines * updated line chart * changed colors * hospital icon attempt * changed call to L.marker to include modified icons * fixed path * updated map styling + hospitals chart * removed scale change * UCLA icon added * tracked png files * fixed some mobile issues for chart * show ucla icon, add tooltip for markers * css style fixes * increased width of map * change icon color * Update schedule_scraper.yml * Update schedule_scraper.yml * Rename 2020-04-19-covid-hospitals.md to 2020-04-20-covid-hospitals.md * update py script, latest data * 4/19 data * updated cover photo * updated cover photo * added custom legend * removed model text clarification * updated scraper for radhika * added simulation code * updated simulation files * changed structure of code * some tests * moved constraints to different file * generate nodes/links * best case scenarios * changed landing page * Revert "changed landing page" This reverts commit 5054451. * add infection * changes + comments * viz stuff * prettierignore file * more viz updates * nodes and edges by case * styling but still ugly on mobile :( * loading graphic * cleaning * add 2nd viz * added code to run simulation w/o viz * colors * play button, r0 slider * button styling * r0 slider styling * addDepartmentData * renamed post * best case full file * Revert "best case full file" This reverts commit e63b050. * best case file * stochastic block model case * added connections field, removed edges * slider * added written content to post * added cover photo * added chart explainer line * cosmetic fixes * slider range * line chart * move stuff * grammatical error fixed * updated cover photo * r0 styling, update line chart * c sesh online * new cover photo * new cover photo * cover photo * pretty chart * code to run simulation and calc averages, update text, cleaning up code * css for mobile * updated general case * new data in chart & graph * text, color changes * cover photo * renamed + purple text * Update 2020-05-10-covid-model.md * key takeaway * buttons * slider width * Update 2020-05-12-covid-model.md * finals -> 11 * custom legend * unhide legend * added x-axis title * x-axis title * text updates * div tag Co-authored-by: Radhika Ahuja <[email protected]> Co-authored-by: Laurel Woods <[email protected]> Co-authored-by: Radhika Ahuja <[email protected]> Co-authored-by: Andrew <[email protected]> Co-authored-by: sydneyekovach <[email protected]> Co-authored-by: Charlotte Huang <[email protected]>
1 parent 6b748bd commit 5dc08ee

File tree

23 files changed

+1655
-30
lines changed

23 files changed

+1655
-30
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ Gemfile.lock
88
*.env
99
auth.yaml
1010
__pycache__
11+
.jekyll-cache/
1112

1213
.vscode/settings.json

.prettierignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
js/posts/covid-model/model.js
2+
js/posts/covid-model/spread.js

_posts/2020-05-12-covid-model.md

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
---
2+
title: Modeling the Spread of COVID-19 in UCLA Classrooms
3+
teaser: What would happen if UCLA students returned in the fall to take in-person classes? We explore the potential spread of COVID-19 among students on UCLA’s campus.
4+
authors:
5+
- radhika_ahuja
6+
- charlotte_huang
7+
- sydney_kovach
8+
- laurel_woods
9+
key_takeaways:
10+
- According to our model of the undergraduate student network, each UCLA student shares a class with 228 other students on average.
11+
- Our simulation shows that with an R<sub>0</sub> value of 5.7, 94% of UCLA undergraduates could be infected by the end of fall quarter.
12+
featured_image:
13+
url: covid-model/cover_photo.png
14+
og_image: covid-model/cover_photo.png
15+
stylesheets:
16+
- /css/posts/covid-model/app.css
17+
scripts:
18+
- //d3js.org/d3.v5.min.js
19+
- //cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js
20+
- //unpkg.com/d3-simple-slider
21+
- /js/posts/covid-model/spread.js
22+
- /js/posts/covid-model/model.js
23+
- /js/posts/covid-model/linechart.js
24+
---
25+
26+
# Introduction
27+
28+
In the middle of a global pandemic, uncertainty has become the new normal. Many states across the country are now beginning to lift restrictions, but colleges must weigh the difficult decision of how to keep students and staff safe while still providing a quality education. While UCLA has already decided to [move summer sessions A and C online](https://dailybruin.com/2020/05/11/ucla-to-hold-summer-session-c-online-considering-selective-in-person-instruction/), the fate of fall quarter is still up in the air. Crowded lecture halls and dorm rooms make it nearly impossible for students to practice social distancing without a disruption to normal college life. As UCLA grapples with whether to welcome students back to campus in the fall, The Stack examines how quickly COVID-19 could spread through the undergraduate student body. Inspired by professor Kim Weeden's [model of course enrollment networks](https://twitter.com/weedenkim/status/1258894522127396866?s=21) at Cornell University, we created our own model of how connected UCLA students are based on the classes they enroll in.
29+
30+
# Methods and Assumptions
31+
32+
Our model looks solely at the spread of COVID-19 through classes and does not take into account interactions students may have through dorm rooms, dining halls, campus organizations or other social aspects of student life. We assume that any student who shares a class with an infected student is exposed to the virus and could become infected. Additionally, the model only takes undergraduate students into consideration. In particular, a realistic picture of the campus includes many more affected groups, like graduate students, faculty, administrative staff, on-campus and dining workers, many of whom are more likely to be in a higher risk category than undergraduate students. However, to keep the model simple and its implementation feasible given the available data, we only factor in undergraduate students. It should also be noted that, although the studies referenced in this article have not yet been peer-reviewed, this is common for coronavirus-related studies because of their newness.
33+
34+
The incubation period for COVID-19 is typically five to six days, though it can take anywhere between one to 14 days to develop symptoms after exposure, if symptoms do develop. LA County offers free COVID-19 testing to all residents, including three testing sites within five miles of UCLA, but same-day and next-day appointments are prioritized for front-line workers and symptomatic patients. We assume that UCLA students will get tested seven days after exposure on average.
35+
36+
Ideally, once someone tests positive, they will self-isolate either the same day or the next day; therefore, we assume that infected students that become symptomatic will be contagious and spread COVID-19 for about a week. However, asymptomatic spread is also significant; according to an [NPR interview with Robert Redfield](https://www.npr.org/sections/health-shots/2020/03/31/824155179/cdc-director-on-models-for-the-months-to-come-this-virus-is-going-to-be-with-us), director of the Centers for Disease Control and Prevention, up to 25% of people with COVID-19 may never show symptoms and are therefore less likely to seek testing and self-isolate. Moreover, [a study](https://www.medrxiv.org/content/10.1101/2020.04.13.20063529v1) stated that 40% to 80% of transmissions could occur from individuals who have not shown symptoms.
37+
38+
R<sub>0</sub>, pronounced “R-naught” and referred to as the “basic reproduction number,” measures how many others an infected individual will infect. An R<sub>0</sub> below one means that the virus will die out over time whereas an R<sub>0</sub> above one means there will be exponential growth, as has been seen in the United States. The value of R0 can vary across regions as it depends on population density and the amount of human contact, so the more social interactions that take place, the higher R0 will be. In California, social distancing and shelter-at-home orders have helped to reduce R0 below the nation-wide levels and to flatten the curve of new infections. However, if in-person classes take place in the fall, the infection rate at UCLA would be higher than the current R0 in a locked-down Los Angeles. For our model, we used 5.7, the median R<sub>0</sub> value [calculated](https://wwwnc.cdc.gov/eid/article/26/7/20-0282_article) by a study posted on the CDC website, as our default. It should be noted that these calculations were based on data from China’s CDC. We started with a single infected student at UCLA. An infected student will infect an average of 5.7 of their classmates over the period of one week. Each classmate has a certain probability of being infected based on the R0 and the number of classmates the original infected student has. Although research is still being done on immunity to COVID-19, we assumed that once a student has recovered, they will not be infected again.
39+
40+
# Modeling the Student Network
41+
42+
The graph below models a typical quarter at UCLA, with each node representing an undergraduate student. Using fall 2019 data provided by the Office of Academic Planning and Budget of how many students are in each major, each student was placed in one of 76 departments and randomly assigned to three courses that were either within their department or were GEs, using a [stochastic block model](#more-on-stochastic-block-models). Each student is then assumed to be connected to every other student they share a class with, and the virus can be transmitted between connected students.
43+
44+
Interdepartmental connectivity in this model arises primarily from degree/school-level requirements like general education, diversity and language. Some other cases like interdepartmental requirements and cross-listing for individual majors, minors, and double majors are not taken into account. In general, these factors are likely to make the model more interconnected and as such our version is a more conservative picture. Some other niche cases like students coming in with transfer credit or students who waive out of certain requirements using diagnostic tests are not considered, i.e., it is assumed that every student takes all their required courses at UCLA.
45+
46+
To explore the visualization, drag the time slider forward through the weeks of fall 2020 or press play to automate it. Each week, an infected student will infect an average of R<sub>0</sub> students. The value of R<sub>0</sub>, [set to 5.7](https://wwwnc.cdc.gov/eid/article/26/7/20-0282_article) by default, can also be adjusted with the slider above the graph to explore different rates of infection.
47+
48+
UCLA could decrease the R<sub>0</sub> if the university implements mandatory social distancing in classrooms, requires the wearing of masks or provides ample sanitizing products to all classrooms and lecture halls. Any combination of these measures would decrease the spread of the virus.
49+
50+
<h3>Student Network Graph</h3>
51+
<div class="loader-wrapper">
52+
<div class="loader"></div>
53+
</div>
54+
<div id="viz">
55+
<div class="r0-slider-wrapper">
56+
<p class="slider-title r0-title">Drag the slider to change the value of R<sub>0</sub></p>
57+
<input class="r0slider" type="range" min="0.1" max="18" value="5.7" step="0.1">
58+
<p class="r0val">R<sub>0</sub> = 5.7</p>
59+
</div>
60+
<div class="graph-wrapper">
61+
<div class="graph"></div>
62+
</div>
63+
<div class="row">
64+
<div class="column stats">
65+
<p class="healthy"></p>
66+
<p class="infected"></p>
67+
<p class="recovered"></p>
68+
</div>
69+
<div class="column slider-wrapper">
70+
<div class="slider"></div>
71+
<p class="slider-title">week of fall quarter</p>
72+
</div>
73+
<div class="column button-div">
74+
<button class="play button" type="button">Play</button>
75+
<button class="restart button" type="button">Restart</button>
76+
</div>
77+
</div>
78+
</div>
79+
80+
In our model network, students had an average of 228 connections. We ran the simulation 100 times from week 0 to finals week with an R<sub>0</sub> value of 5.7, and found that on average, 94% of students were infected by the end of fall quarter. The peak of new cases occurred at week 6 with over 11,000 new cases.
81+
82+
We also calculated the average number of infections over 100 runs for several different values of R<sub>0</sub>. The following chart shows the number of people infected on average through the 11 weeks, for varying values of R<sub>0</sub>:
83+
84+
<div id="linechart-wrapper">
85+
<canvas id="linechart"></canvas>
86+
</div>
87+
<div id="custom-legend">
88+
<div class="legend-marker" id="total"></div><span class="legend-label">Total Undergrads</span> <br>
89+
<div class="legend-marker" id="1"></div><span class="legend-label">R0 = 1</span> <br>
90+
<div class="legend-marker" id="2"></div><span class="legend-label">R0 = 2</span> <br>
91+
<div class="legend-marker" id="2.5"></div><span class="legend-label">R0 = 2.5</span> <br>
92+
<div class="legend-marker" id="3"></div><span class="legend-label">R0 = 3</span> <br>
93+
<div class="legend-marker" id="4"></div><span class="legend-label">R0 = 4</span> <br>
94+
<div class="legend-marker" id="5.7"></div><span class="legend-label">R0 = 5.7</span> <br>
95+
</div>
96+
97+
# Conclusion
98+
99+
The potential spread of the virus depicted above does not take into account interactions in shared spaces such as Bruin Walk, libraries, dining halls, etc. or the fact that the same lecture hall is used, i.e., the same chairs are reused and such surfaces might be a source of infection. These models also do not show the potential spread through shared living spaces such as dorms and apartments. Consequently, COVID-19 could be much more infectious through the UCLA community than the models above show. In fear of outbreaks, [California State University campuses will remain closed](https://www2.calstate.edu/csu-system/news/Pages/CSU-Chancellor-Timothy-P-Whites-Statement-on-Fall-2020-University-Operational-Plans.aspx) for the Fall 2020 semester, and the 23 universities in this system will proceed with primarily virtual instruction. UCLA has yet to make a decision on whether the Fall 2020 quarter will be held virtually or whether there will be some in-person instruction.
100+
101+
As of May 11, there are over 1.3 million confirmed cases and over 80,000 deaths in the U.S. In LA County, there are over 32,00 confirmed cases and over 1,500 deaths. LA County is offering free coronavirus tests for all residents and working to test up to 10,000 people every day, with each site capable of running 100 to 500 tests per day. Up to one in four COVID-19 patients may remain asymptomatic and never quarantine. Asymptomatic carriers may therefore be more likely to spread the virus than those who show symptoms, get tested and quarantine themselves. It is crucial to practice social distancing, wash hands and wear a cloth mask to prevent the virus from spreading, according to the CDC.
102+
103+
UCLA is a large school with a very well-connected student network posing numerous challenges for reopening the university in Fall.
104+
105+
For more updates on coronavirus news relevant to UCLA, visit the [Daily Bruin’s coronavirus dashboard](https://features.dailybruin.com/2020/covid-19/). For more information about how students have been affected by the pandemic, visit the Daily Bruin’s “[Unfinished Stories](https://covidstories.dailybruin.com/)” project. To schedule a free COVID-19 test in LA County or learn more about testing, [click here](https://lacovidprod.service-now.com/rrs?id=rrs_apply). More information about the coronavirus and COVID-19 from [UCLA Health](https://www.uclahealth.org/coronavirus) can be found here.
106+
107+
# More on Stochastic Block Models
108+
109+
A stochastic block model considers a set of student communities, grouped by department, such as mathematics, art history or psychology. So for example, consider a three-department school: Sciences with 200 students, Business with 150 students and Humanities with 170 students. The student communities set is then [200, 150, 170].
110+
111+
Then a matrix A defines the probabilities to randomly select students from each community/department to other communities/departments. The ith row represents the probability of a student from the ith community taking courses with people in each of the 3 departments.
112+
113+
So A = [[0.7, 0.1, 0.2] → probability of a sciences students in each department
114+
[0.1, 0.8, 0.1]→ probability of a business student in each department
115+
[0.1, 0.2, 0.7]] → probability of a humanities student in each department]
116+
117+
This example has simulated probabilities, but the real probabilities in our model are based on the number of GE, diversity and language courses in each major. So if a College of Letters and Science student in the mathematics department takes 140 units of major courses and 40 units of GEs, then the probability of the student being enrolled in the mathematics department is 140/180, and, in the other GE-offering departments, is 40/180, which in turn are distributed by department. So if there are three GE courses offered in total, with two of them being offered in department A and one being offered in department B, department A will have probability ⅔ _ 40/180, and department B will have probability ⅓ _ 40/180.

css/posts/covid-model/app.css

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#viz {
2+
display: none;
3+
}
4+
5+
.stats {
6+
width: 30%;
7+
}
8+
9+
.stats p {
10+
text-align: center;
11+
}
12+
13+
.slider-wrapper {
14+
width: 60%;
15+
text-align: center;
16+
}
17+
.slider {
18+
display: inline-block;
19+
width: 100%;
20+
}
21+
.slider-title {
22+
color: gray;
23+
font-size: small;
24+
}
25+
26+
.r0slider {
27+
display: inline;
28+
}
29+
30+
.r0-title {
31+
display: inline;
32+
}
33+
34+
.r0val {
35+
display: inline;
36+
font-weight: bold;
37+
}
38+
39+
.r0-slider-wrapper {
40+
text-align: center;
41+
}
42+
43+
.button-div {
44+
width: 10%;
45+
text-align: center;
46+
}
47+
48+
.button {
49+
background-color: #4CAF50; /* Green */
50+
border: none;
51+
color: white;
52+
padding: 8px 15px;
53+
text-align: center;
54+
text-decoration: none;
55+
display: inline-block;
56+
font-size: 14px;
57+
margin: 4px 2px;
58+
transition-duration: 0.4s;
59+
cursor: pointer;
60+
border-radius: 5px;
61+
}
62+
63+
.restart {
64+
background-color: white;
65+
color: black;
66+
border: 2px solid #4CAF50;
67+
}
68+
69+
.restart:hover {
70+
background-color: #4CAF50;
71+
color: white;
72+
}
73+
74+
.play {
75+
background-color: white;
76+
color: black;
77+
border: 2px solid #008CBA;
78+
}
79+
80+
.play:hover {
81+
background-color: #008CBA;
82+
color: white;
83+
}
84+
85+
/* Clear floats after the columns */
86+
.row:after {
87+
content: "";
88+
display: table;
89+
clear: both;
90+
}
91+
92+
93+
.column {
94+
float: left;
95+
}
96+
97+
.loader-wrapper {
98+
text-align: center;
99+
}
100+
101+
.loader {
102+
display: inline-block;
103+
width: 150px;
104+
height: 150px;
105+
border: 16px solid #f3f3f3;
106+
border-radius: 50%;
107+
border-top: 16px solid #3498db;
108+
width: 120px;
109+
height: 120px;
110+
-webkit-animation: spin 2s linear infinite;
111+
animation: spin 2s linear infinite;
112+
}
113+
114+
@-webkit-keyframes spin {
115+
0% { -webkit-transform: rotate(0deg); }
116+
100% { -webkit-transform: rotate(360deg); }
117+
}
118+
119+
@keyframes spin {
120+
0% { transform: rotate(0deg); }
121+
100% { transform: rotate(360deg); }
122+
}
123+
124+
#linechart-wrapper {
125+
margin: 0 auto;
126+
}
127+
128+
129+
/* #custom-legend,
130+
.legend-marker,
131+
.legend-label {
132+
display: none;
133+
} */
134+
135+
/* Phone Level */
136+
@media only screen and (min-device-width: 320px) and (max-device-width: 480px) and (-webkit-min-device-pixel-ratio: 2) {
137+
.button {
138+
display: inline-block;
139+
}
140+
.button-div {
141+
width: 100%;
142+
}
143+
144+
.column {
145+
float: none;
146+
}
147+
148+
.slider-wrapper {
149+
width: 100%;
150+
text-align: center;
151+
}
152+
.stats {
153+
width: 90%;
154+
}
155+
156+
#custom-legend {
157+
border: solid #000;
158+
border-width: 1px;
159+
margin-bottom: 2vh;
160+
margin-top: 1vh;
161+
margin: auto;
162+
}
163+
164+
.legend-marker {
165+
border: solid #000;
166+
border-width: 1px;
167+
display: inline-block;
168+
width: 1em;
169+
line-height: 0.6em;
170+
margin: 0.5em;
171+
}
172+
.legend-label {
173+
display: inline-block;
174+
}
175+
}
13.8 MB
Binary file not shown.
14.1 MB
Binary file not shown.

datasets/class-fill-ups/parsing/class_parser.py

+18-7
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
sec = time.localtime().tm_sec
2626

2727
print("Starting script")
28-
file = open('data/{}-{}-{}.csv'.format(day, hour, sec), 'w')
28+
file = open('radhikas_data/{}-{}-{}.csv'.format(day, hour, sec), 'w')
2929
file_writer = csv.writer(file, delimiter=',')
3030
"""
3131
chrome_options = Options()
@@ -34,12 +34,13 @@
3434
chrome_options.add_argument('--disable-dev-shm-usage')
3535
driver = webdriver.Chrome('./chromedriver', chrome_options=chrome_options)
3636
"""
37-
driver = webdriver.Chrome('./chromedriver')
37+
driver = webdriver.Chrome('./chromedriver_81')
3838
wait = WebDriverWait(driver, timeout)
3939

4040
# have selenium get the department website
41+
quarter = "20S"
4142
dep_file = open('departments.txt', 'r')
42-
link1 = "https://sa.ucla.edu/ro/Public/SOC/Results?t=20W&sBy=subject&sName="
43+
link1 = "https://sa.ucla.edu/ro/Public/SOC/Results?t="+quarter+"&sBy=subject&sName="
4344
link2 = "%28"
4445
link3 = "%29&subj="
4546
link4 = "&crsCatlg=Enter+a+Catalog+Number+or+Class+Title+%28Optional%29&catlg=&cls_no=&btnIsInIndex=btn_inIndex"
@@ -121,16 +122,26 @@
121122
for s in status:
122123
status_text = s.find('p').text
123124
if (status_text != "Status"):
125+
number_text = re.findall("[0-9]+", status_text)
126+
enrolled = 0
127+
classSize = 0
128+
arr_text = []
124129
if (status_text.find('Closed') == 0):
125-
file_writer.writerow([0, 0, 0])
130+
for i in number_text:
131+
arr_text.append(i)
132+
enrolled += int(i)
133+
classSize = int(arr_text[0])
134+
file_writer.writerow([enrolled, classSize, 0])
126135
if (status_text.find('Open') == 0):
127-
number_text = re.findall("[0-9]+", status_text)
128-
arr_text = []
129136
for i in number_text:
130137
arr_text.append(i)
131138
file_writer.writerow(arr_text)
132139
if (status_text.find('Waitlist') == 0):
133-
file_writer.writerow([-1, -1, -1])
140+
for i in number_text:
141+
arr_text.append(i)
142+
enrolled += int(i)
143+
classSize = int(arr_text[0])
144+
file_writer.writerow([enrolled, classSize, 0])
134145
except:
135146
pass
136147
page_num += 1

datasets/covid-model/best_case.json

+1
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)