arinbjorn commited on
Commit
8860bd4
·
1 Parent(s): 1ddf964
Files changed (1) hide show
  1. app.py +247 -2
app.py CHANGED
@@ -1,4 +1,249 @@
1
  import streamlit as st
 
 
 
2
 
3
- x = st.slider('Select a value')
4
- st.write(x, 'squared is', x * x)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import altair as alt
3
+ import numpy as np
4
+ import pandas as pd
5
 
6
+ st.markdown(
7
+ """
8
+ <style>
9
+ @font-face {
10
+ font-family: 'Tangerine';
11
+ font-style: normal;
12
+ font-weight: 400;
13
+ src: url(https://fonts.gstatic.com/s/tangerine/v12/IurY6Y5j_oScZZow4VOxCZZM.woff2) format('woff2');
14
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
15
+ }
16
+
17
+ html, body, [class*="css"] {
18
+ font-family: 'Public Sans', sans-serif;
19
+ # font-size: 1rem;
20
+ }
21
+ </style>
22
+
23
+ """,
24
+ unsafe_allow_html=True,
25
+ )
26
+
27
+
28
+ # Define params
29
+ st.subheader("Configuration")
30
+ col1, col2 = st.columns(2)
31
+
32
+ # Chances of developing symptoms (per day)
33
+ with col1:
34
+ symptoms_chance = st.slider(
35
+ 'Chances of developing symptoms if infected (per day)', min_value=0.0, max_value=1.0, value=0.5, step=0.01)
36
+
37
+ # Days spent inf asympt
38
+ with col1:
39
+ mean_days_inf_asympt = st.slider(
40
+ 'Mean number of days as infectious asymptomatic (without routine testing)', min_value=1, max_value=14, value=4, step=1)
41
+ base_p00 = 1-(1/mean_days_inf_asympt)
42
+ base_p01 = (1-symptoms_chance)*(1/mean_days_inf_asympt)
43
+ base_p03 = (symptoms_chance)*(1/mean_days_inf_asympt)
44
+
45
+ # Days spent inf asympt
46
+ with col2:
47
+ mean_days_inf_sympt = st.slider(
48
+ 'Mean number of days as infectious symptomatic (when testing on symptoms only)', min_value=1, max_value=14, value=2, step=1)
49
+ base_p11 = 1-(1/mean_days_inf_sympt)
50
+ base_p12 = (1/mean_days_inf_sympt)
51
+
52
+ # Wearable efficiency
53
+ efficiency = st.radio(
54
+ "Performance of device",
55
+ ('Standard', 'Conservative'))
56
+ # with col2:
57
+ # wear_efficiency = st.slider(
58
+ # 'Sensitivity of device', min_value=0.0, max_value=1.0, value=0.2, step=0.01) # 👈 this is a widget
59
+
60
+
61
+
62
+ # # Calculate
63
+ # test_efficiency = np.linspace(1, 30, 30)
64
+ # days_inf = np.zeros((len(test_efficiency)))
65
+ # temp_df = []
66
+ # for tau_count, t_e in enumerate(test_efficiency):
67
+ # tau = 1/t_e
68
+ # pi = wear_efficiency
69
+ # # Transition matrix
70
+ # p = np.array([
71
+ # [base_p00*(1-tau)*(1-pi), base_p01*(1-tau) *
72
+ # (1-pi), 1-(1-tau)*(1-pi), base_p03*(1-tau)*(1-pi)],
73
+ # [0, base_p11*(1-tau)*(1-pi), base_p12*(1+tau+pi-tau*pi), 0.0],
74
+ # [0, 0, 1.0, 0.0],
75
+ # [0, 0, 0.0, 1.0]
76
+ # ])
77
+
78
+ # m1 = 1/(1-p[0,0])
79
+ # m2 = 1/(1-p[1,1])
80
+ # p2 = p[0,1]/(p[0,1]+p[0,2]+p[0,3])
81
+ # days_inf[int(tau_count)] = m1 + p2*m2
82
+ # routine_tests_required = 30 * days_inf[2]
83
+
84
+ # Cost case
85
+ sens_list_standard = {0.0: 0.0,
86
+ 0.005: 0.05,
87
+ 0.014: 0.1,
88
+ 0.021: 0.15,
89
+ 0.05: 0.295,
90
+ 0.1: 0.434,
91
+ 0.2: 0.6,
92
+ 0.3: 0.72,
93
+ 0.4: 0.79,
94
+ 0.5: 0.86,
95
+ 0.6: 0.9,
96
+ 0.7: 0.925,
97
+ 0.8: 0.97,
98
+ 0.9: 0.99,
99
+ 1.0: 1.0}
100
+
101
+ sens_list_conservative = {
102
+ 0: 0,
103
+ 0.012: 0.050,
104
+ 0.026: 0.105,
105
+ 0.049: 0.149,
106
+ 0.072: 0.198,
107
+ 0.096: 0.248,
108
+ 0.120: 0.297,
109
+ 0.146: 0.347,
110
+ 0.184: 0.396,
111
+ 0.222: 0.446,
112
+ 0.255: 0.495,
113
+ 0.300: 0.545,
114
+ 0.349: 0.594,
115
+ 0.401: 0.644,
116
+ 0.467: 0.693,
117
+ 0.547: 0.743,
118
+ 0.621: 0.792,
119
+ 0.699: 0.842,
120
+ 0.787: 0.891,
121
+ 0.868: 0.941,
122
+ 1: 1
123
+ }
124
+
125
+ if efficiency == 'Standard':
126
+ sens_list = sens_list_standard
127
+ else:
128
+ sens_list = sens_list_conservative
129
+
130
+ def roc_func(x):
131
+ return sens_list[x]
132
+
133
+ def roc_random(x):
134
+ return x
135
+
136
+ test_efficiency = np.array([7, 30, 10000])
137
+ # FPR = np.linspace(0, 1, 11)
138
+ # FPR = [0.0, 0.005, 0.016, 0.021, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
139
+ # FPR = list(sens_list.keys())
140
+ # days_inf = np.zeros((len(test_efficiency), len(FPR)))
141
+
142
+ # for tau_count, t_e in enumerate(test_efficiency):
143
+ # tau = 1/t_e
144
+ # for fi_count, fi in enumerate(FPR):
145
+ # pi = roc_func(fi)
146
+ # alpha = tau + pi - (tau*pi)
147
+ # m1 = 4/(1+3*alpha)
148
+ # m2 = 2/(1 + alpha)
149
+ # p2 = 1/2 * (1 - alpha) / (1 + 3 * alpha)
150
+ # days_inf[int(tau_count), int(fi_count)] = m1 + p2*m2
151
+
152
+ # Calculate
153
+ test_efficiency = np.array([7, 30, 10000])
154
+ FPR = list(sens_list.keys())
155
+ days_inf = np.zeros((len(test_efficiency), len(FPR)))
156
+ temp_df = []
157
+ for tau_count, t_e in enumerate(test_efficiency):
158
+ tau = 1/t_e
159
+ for fi_count, fi in enumerate(FPR):
160
+ pi = roc_func(fi)
161
+ # Transition matrix
162
+ p = np.array([
163
+ [base_p00*(1-tau)*(1-pi), base_p01*(1-tau) *
164
+ (1-pi), 1-(1-tau)*(1-pi), base_p03*(1-tau)*(1-pi)],
165
+ [0, base_p11*(1-tau)*(1-pi), base_p12*(1+tau+pi-tau*pi), 0.0],
166
+ [0, 0, 1.0, 0.0],
167
+ [0, 0, 0.0, 1.0]
168
+ ])
169
+
170
+ m1 = 1/(1-p[0, 0])
171
+ m2 = 1/(1-p[1, 1])
172
+ p2 = p[0, 1]/(p[0, 1]+p[0, 2]+p[0, 3])
173
+ days_inf[int(tau_count), int(fi_count)] = m1 + p2*m2
174
+ routine_tests_required = 30 * days_inf[2]
175
+ # print(routine_tests_required)
176
+
177
+ # No wearable case
178
+ no_wearables = []
179
+ tau = 1/10000
180
+ for fi_count, fi in enumerate(FPR):
181
+ pi = roc_random(fi)
182
+ # Transition matrix
183
+ p = np.array([
184
+ [base_p00*(1-tau)*(1-pi), base_p01*(1-tau) *
185
+ (1-pi), 1-(1-tau)*(1-pi), base_p03*(1-tau)*(1-pi)],
186
+ [0, base_p11*(1-tau)*(1-pi), base_p12*(1+tau+pi-tau*pi), 0.0],
187
+ [0, 0, 1.0, 0.0],
188
+ [0, 0, 0.0, 1.0]
189
+ ])
190
+
191
+ m1 = 1/(1-p[0, 0])
192
+ m2 = 1/(1-p[1, 1])
193
+ p2 = p[0, 1]/(p[0, 1]+p[0, 2]+p[0, 3])
194
+ no_wearables.append(m1 + p2*m2)
195
+
196
+ cost = np.array(FPR)*30
197
+ no_wearable_cost = cost
198
+ # for i in range(len(test_efficiency)):0
199
+
200
+ wearable_cost = (1-(1-np.array(FPR))*(1-1/test_efficiency[2]))*30
201
+ wearable_days_inf = days_inf[2]
202
+
203
+ # Create chart
204
+ chart_data = pd.DataFrame(
205
+ {'Tests required per month': no_wearable_cost,
206
+ 'Routine testing': no_wearables,
207
+ 'Wearable-triggered testing': wearable_days_inf})
208
+
209
+ # st.line_chart(chart_data)
210
+
211
+ chart_data_melted = chart_data.melt('Tests required per month')
212
+ print(chart_data_melted)
213
+ chart = (
214
+ alt.Chart(
215
+ data=chart_data_melted,
216
+ title="",
217
+ height=400,
218
+ )
219
+ .mark_line()
220
+ # .encode(
221
+ # x=alt.X('Tests required per month',
222
+ # scale=alt.Scale(domain=[0, 30])),
223
+ # y=alt.Y('Average case infectious days',
224
+ # scale=alt.Scale(domain=[0, 6])),
225
+ # # color=alt.value("#162d88"),
226
+ # color=alt.Color("name:N"),
227
+ # strokeWidth=alt.value(6),
228
+ # )
229
+ .encode(
230
+ x='Tests required per month',
231
+ y=alt.Y('value:Q', axis=alt.Axis(title='Average case infectious days')),
232
+ # y='value:Q',
233
+ color='variable:N',
234
+ strokeWidth=alt.value(6)
235
+ )
236
+ .configure_axis(
237
+ labelFontSize=20,
238
+ titleFontSize=20
239
+ )
240
+
241
+ )
242
+
243
+ st.subheader("Outcome")
244
+ st.altair_chart(chart, use_container_width=True)
245
+
246
+ # col1, col2, col3 = st.columns(3)
247
+ # col1.metric("Tests required per month", int(routine_tests_required), "1.2")
248
+ # col2.metric("Tests saved", "9", "-8%")
249
+ # col3.metric("Humidity", "86%", "4%")