@@ -13,12 +13,17 @@ scenario <- function(
13
13
pcr_lod = 300.0 ,
14
14
pcr_sens = .975 ,
15
15
pcr_spec = 1.0 ,
16
- gamma = 0.0 ,
17
- eta = 1.0 ,
18
16
lfd_spec = 0.998 ,
17
+ lfd_ranef = 0.0 ,
19
18
ar_window = 3L ,
20
19
ar_coefficient = 0.0 ,
21
20
days = as.integer(6 * 7 ),
21
+ scale = 0.0 ,
22
+ l = 2.5 ,
23
+ df = 3.0 ,
24
+ gamma_min = 0.0 , gamma_max = 0.1 ,
25
+ rzero = 3.0 ,
26
+ mean_sensitivity = 0.6 ,
22
27
...
23
28
) {
24
29
res <- as.list(environment())
@@ -56,80 +61,143 @@ scenario <- function(
56
61
57
62
res
58
63
}
59
-
60
- sensitivity <- function (vl , params ) {
61
- lfd <- julia_call(" LogRegTest" , " lfd" , params $ lfd_slope , params $ lfd_intercept , params $ lfd_spec , need_return = " Julia" )
62
- julia_call(" sensitivity." , lfd , vl , need_return = " R" )
63
- }
64
64
65
65
n_class <- function (params ) with(params , n_bubble * bubbles_per_class )
66
66
n_school <- function (params ) with(params , classes_per_school * n_class(params ))
67
67
n_weekly_infections <- function (params ) with(params , 7 * n_school(params )* pr_external_infection )
68
68
69
69
schooldays <- function (params ) with(params , sum(((1 : days ) %% 7 ) %in% 1 : 5 ))
70
70
71
+ disease_model <- function (params , gamma = NULL ) {
72
+ if (is.null(gamma ))
73
+ gamma <- gamma(params $ rzero , params )
74
+ dm <- julia_call(" LarremoreModel" ,
75
+ gamma , frac_symptomatic = params $ frac_symptomatic ,
76
+ l10vl_clearance = log10(params $ lli ),
77
+ need_return = " Julia"
78
+ )
79
+ if (params $ scale > 1 ) {
80
+ dm <- julia_call(" HeavyTailsModel" ,
81
+ dm ,
82
+ l = params $ l ,
83
+ scale = params $ scale ,
84
+ df = params $ df
85
+ )
86
+ }
87
+ return (dm )
88
+ }
89
+
71
90
pcr <- function (params ) with(params , julia_call(" FixedTest" , " pcr" , pcr_sens , pcr_spec , lod = pcr_lod , need_return = " Julia" ))
72
91
73
- lfd <- function (params ) {
74
- with(params ,
75
- julia_call(" LogRegTest" , " lfd" ,
76
- eta * params $ lfd_slope , params $ lfd_intercept , lfd_spec ,
77
- ar_window = ar_window , ar_coefficient = ar_coefficient
78
- )
92
+ lfd <- function (params , eta = NULL ) {
93
+ if (is.null(eta ))
94
+ eta <- eta(params $ mean_sensitivity , params )
95
+ julia_call(" LogRegTest" , " lfd" ,
96
+ eta * params $ lfd_slope , params $ lfd_intercept , params $ lfd_spec ,
97
+ ar_window = params $ ar_window , ar_coefficient = params $ ar_coefficient ,
98
+ ranef = params $ lfd_ranef
79
99
)
80
100
}
81
101
82
- fit_rzero_ <- function (params , gamma_min = 0 , gamma_max = .1 ) {
102
+ fit_rzero <- memoise :: memoise(function (
103
+ n_bubble , bubbles_per_class , classes_per_school , pr_meet_class , pr_meet_school ,
104
+ frac_symptomatic , pr_noncovid_symptoms , l , scale , df , lli , gamma_min , gamma_max
105
+ ) {
106
+ get_school <- function (gamma ) {
107
+ julia_call(" school" ,
108
+ n_bubble , bubbles_per_class , classes_per_school , pr_meet_class , pr_meet_school ,
109
+ gamma ,
110
+ frac_symptomatic , pr_noncovid_symptoms , l , scale , df ,
111
+ Inf , 1 , lli , # test specific values do not affect r0
112
+ julia_call(" DoNothing" )
113
+ )
114
+ }
83
115
tbl_rzero <- tibble(
84
116
gamma = seq(gamma_min , gamma_max , length.out = 100 ),
85
- R = map(gamma , ~ {
86
- params $ gamma <- .
87
- sample_rzero(do.call(school , params ), n = 10L )
88
- })
117
+ R = map(gamma , ~ sample_rzero(get_school(. ), n = 10L ))
89
118
) %> %
90
119
unnest(R )
91
120
fit <- lm(formula = R ~ gamma - 1 , data = tbl_rzero )
92
121
list (fit = fit , data = tbl_rzero )
93
- }
94
- fit_rzero <- memoise :: memoise(fit_rzero_ )
95
- rzero <- function (gamma , params , gamma_min = 0 , gamma_max = .1 ) {
96
- fit <- fit_rzero(params , gamma_min , gamma_max )$ fit
122
+ }, cache = mcache )
123
+ rzero <- memoise :: memoise(function (gamma , params ) {
124
+ fit <- with(params , fit_rzero(
125
+ n_bubble , bubbles_per_class , classes_per_school , pr_meet_class , pr_meet_school ,
126
+ frac_symptomatic , pr_noncovid_symptoms , l , scale , df , lli , gamma_min , gamma_max
127
+ ))$ fit
97
128
as.numeric(predict(fit , newdata = tibble(gamma = gamma ), type = " response" ))
98
- }
99
- gamma <- function (R , params , gamma_min = 0 , gamma_max = .1 ) {
100
- as.numeric(uniroot(function (x ) rzero(x , params , gamma_min , gamma_max ) - R , interval = c(gamma_min , gamma_max ))$ root )
101
- }
129
+ }, cache = mcache )
130
+ gamma <- memoise :: memoise(function (R , params ) {
131
+ uniroot(
132
+ function (x ) rzero(x , params ) - R ,
133
+ interval = c(params $ gamma_min , params $ gamma_max )
134
+ )$ root %> %
135
+ as.numeric()
136
+ }, cache = mcache )
102
137
103
- sample_presymptomatic_vl <- function (params , n = 1e5 ) {
104
- dm <- julia_call(" LarremoreModel" , params $ gamma , frac_symptomatic = params $ frac_symptomatic , need_return = " Julia" )
105
- individuals <- julia_call(" Individual." , dm , rep(params $ pr_noncovid_symptoms , n ), need_return = " Julia" )
138
+ sample_presymptomatic_vl <- function (
139
+ disease_model ,
140
+ pr_noncovid_symptoms ,
141
+ pcr_lod
142
+ ) {
143
+ individuals <- julia_call(" Individual." ,
144
+ disease_model ,
145
+ rep(pr_noncovid_symptoms , 1e4 ),
146
+ need_return = " Julia"
147
+ )
106
148
julia_call(" infect!." , individuals , need_return = " Julia" )
107
149
julia_call(" steps!." , individuals , 21L , need_return = " Julia" )
150
+ tbl_u <- tibble(
151
+ uuid = julia_call(" string." ,
152
+ julia_call(" getproperty." ,
153
+ individuals , julia_call(" Symbol" , " uuid" )
154
+ )
155
+ ),
156
+ u = julia_call(" getproperty." ,
157
+ individuals , julia_call(" Symbol" , " u_sensitivity" , need_return = " Julia" )
158
+ )
159
+ )
108
160
julia_call(" get_status_logs" , individuals ) %> %
109
161
as_tibble() %> %
162
+ left_join(tbl_u , by = " uuid" ) %> %
110
163
arrange(uuid , day ) %> %
111
164
group_by(uuid ) %> %
112
165
filter(
113
- row_number() > = which(viral_load > params $ pcr_lod )[1 ],
114
- row_number() < which(symptomatic )[1 ]
166
+ row_number() > = which(viral_load > pcr_lod )[1 ],
167
+ row_number() < which(symptomatic )[1 ] % > % {if_else(is.na( . ), Inf , as.numeric( . ))}
115
168
) %> %
116
169
sample_n(1 ) %> %
117
170
ungroup() %> %
118
- select(uuid , day , viral_load )
171
+ select(
172
+ uuid ,
173
+ day ,
174
+ u ,
175
+ viral_load
176
+ )
119
177
}
120
- sample_presymptomatic_vl_ <- memoise :: memoise(sample_presymptomatic_vl )
121
- mean_sensitivity <- function (params , eta , ... ) {
122
- sample_presymptomatic_vl_(params , ... ) %> %
123
- mutate(
124
- sensitivity = sensitivity(viral_load ^ eta , params )
178
+ sample_presymptomatic_vl_ <- memoise :: memoise(sample_presymptomatic_vl , cache = mcache )
179
+ mean_sensitivity <- memoise :: memoise(function (eta , params ) {
180
+ lfd <- lfd(params , eta = eta )
181
+ sample_presymptomatic_vl_(
182
+ disease_model(params , gamma = 0 ),
183
+ params $ pr_noncovid_symptoms ,
184
+ params $ pcr_lod
125
185
) %> %
126
- pull(sensitivity ) %> %
127
- summary() %> %
186
+ mutate(
187
+ sensitivity = map2_dbl(viral_load , u ,
188
+ ~ julia_call(" get_probability_positive" , lfd , ..1 , u = ..2 )
189
+ )
190
+ ) %> %
191
+ pull(sensitivity ) %> %
128
192
mean()
129
- }
130
- eta <- function (params , target , ... ) {
131
- as.numeric(uniroot(function (x ) mean_sensitivity(params , x , ... ) - target , interval = c(0 , 5 ))$ root )
132
- }
193
+ }, cache = mcache )
194
+ eta <- memoise :: memoise(function (target , params ) {
195
+ uniroot(
196
+ function (x ) mean_sensitivity(x , params ) - target ,
197
+ interval = c(0 , 3 )
198
+ )$ root %> %
199
+ as.numeric()
200
+ }, cache = mcache )
133
201
134
202
expand_scenario <- function (params = scenario(), ... ) {
135
203
tbl <- if (length(list (... )) == 0 ) {
@@ -163,20 +231,27 @@ evaluate_performance_ <- function(params, policy, n = 1L) {
163
231
`% schooldays missed (cumulative)` = workdays_missed / n_school(params )/ schooldays(params )
164
232
)
165
233
}
166
- evaluate_performance <- function (policies , params = scenario(), n = if (! is.null(n_resample )) {n_resample } else {25L }, ... ) {
167
- gamma2rs <- memoise :: memoise(function (gamma ) round(rzero(gamma , params ), 1 ) )
168
- eta2mean_sensitivity <- memoise :: memoise(function (eta ) round(mean_sensitivity(params , eta ), 2 ) )
234
+ evaluate_performance_mem <- memoise :: memoise(evaluate_performance_ , cache = mcache )
235
+ evaluate_performance <- function (
236
+ policies ,
237
+ params = scenario(),
238
+ .gamma_min = 0.0 , .gamma_max = 0.1 ,
239
+ n = if (! is.null(n_resample )) {n_resample } else {25L },
240
+ ...
241
+ ) {
169
242
expand_scenario(params , ... ) %> %
170
243
expand_grid(tibble(policy = policies )) %> %
171
244
mutate(
172
245
policy_name = names(policy ),
173
- results = map2(params , policy , evaluate_performance_ , n )
246
+ results = map2(params , policy , evaluate_performance_mem , n )
174
247
) %> %
175
248
unnest(results ) %> %
176
- select(- params ) %> %
177
249
mutate(
178
- policy_name = factor (policy_name , levels = names(lst_policies )),
179
- Rs = map_dbl(.data $ gamma , gamma2rs ),
180
- `mean sensitivity` = map_dbl(.data $ eta , eta2mean_sensitivity )
181
- )
250
+ policy_name = factor (policy_name , levels = names(lst_policies ))
251
+ ) %> %
252
+ rename(
253
+ Rs = rzero ,
254
+ `mean sensitivity` = mean_sensitivity
255
+ ) %> %
256
+ select(- params )
182
257
}
0 commit comments