Skip to content

Commit

Permalink
Merge pull request #1 from kkmann/refactor
Browse files Browse the repository at this point in the history
refactor, 2nd preprint release
  • Loading branch information
kkmann committed Mar 5, 2021
2 parents 82c488b + 9924a3e commit f27cd34
Show file tree
Hide file tree
Showing 21 changed files with 847 additions and 751 deletions.
30 changes: 15 additions & 15 deletions .julia/Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[Distributions]]
deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns"]
git-tree-sha1 = "0fc424e725eaec6ea3e9fa8df773bee18a1ab503"
git-tree-sha1 = "e64debe8cd174cc52d7dd617ebc5492c6f8b698c"
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
version = "0.24.14"
version = "0.24.15"

[[DocStringExtensions]]
deps = ["LibGit2", "Markdown", "Pkg", "Test"]
Expand All @@ -104,9 +104,9 @@ version = "0.8.3"

[[Documenter]]
deps = ["Base64", "Dates", "DocStringExtensions", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"]
git-tree-sha1 = "21fb992ef1b28ff8f315354d3808ebf4a8fa6e45"
git-tree-sha1 = "3ebb967819b284dc1e3c0422229b58a40a255649"
uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
version = "0.26.2"
version = "0.26.3"

[[FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays"]
Expand Down Expand Up @@ -191,9 +191,9 @@ uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[OffsetArrays]]
deps = ["Adapt"]
git-tree-sha1 = "f64fbf703e7f5af5d82ea7b7385b443bb7765ce9"
git-tree-sha1 = "b3dfef5f2be7d7eb0e782ba9146a5271ee426e90"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.6.1"
version = "1.6.2"

[[OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
Expand All @@ -207,26 +207,26 @@ uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.0"

[[PDMats]]
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse", "Test"]
git-tree-sha1 = "95a4038d1011dfdbde7cecd2ad0ac411e53ab1bc"
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
git-tree-sha1 = "f82a0e71f222199de8e9eb9a09977bd0767d52a0"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.10.1"
version = "0.11.0"

[[Parsers]]
deps = ["Dates"]
git-tree-sha1 = "50c9a9ed8c714945e01cd53a21007ed3865ed714"
git-tree-sha1 = "223a825cccef2228f3fdbf2ecc7ca93363059073"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "1.0.15"
version = "1.0.16"

[[Pkg]]
deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[PooledArrays]]
deps = ["DataAPI"]
git-tree-sha1 = "0e8f5c428a41a81cd71f76d76f2fc3415fe5a676"
deps = ["DataAPI", "Future"]
git-tree-sha1 = "cde4ce9d6f33219465b55162811d8de8139c0414"
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
version = "1.1.0"
version = "1.2.1"

[[PrettyTables]]
deps = ["Crayons", "Formatting", "Markdown", "Reexport", "Tables"]
Expand Down Expand Up @@ -367,7 +367,7 @@ version = "0.5.3"

[[cov19sim]]
deps = ["DataFrames", "DataFramesMeta", "Distributed", "Distributions", "Documenter", "Interpolations", "Random", "Statistics", "Test", "UUIDs"]
git-tree-sha1 = "788fc38f4969992275a76e179e8bf713c412c9ed"
git-tree-sha1 = "d200e3affaab6a4b371ef354dcb94797992c56c0"
repo-rev = "main"
repo-url = "https://github.com/kkmann/cov19sim"
uuid = "7070818b-bc4a-4efc-9908-1d2131e194b1"
Expand Down
49 changes: 12 additions & 37 deletions code/evaluate_performance.jl
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
function evaluate_performance_(
n_per_bubble, bubbles_per_class, m_classes, pr_meet_class, pr_meet_school,
gamma, frac_symptomatic, pr_external_infections, pr_noncovid_symptoms,
pcr,
eta, slope, intercept, ar_window, ar_coefficient,
policy_name, a, b
)
lfd = LogRegTest("lfd", eta*slope, intercept, .998; ar_window = ar_window, ar_coefficient = ar_coefficient)
s = school(
n_per_bubble, bubbles_per_class, m_classes, pr_meet_class, pr_meet_school,
gamma, frac_symptomatic, pr_noncovid_symptoms, a, b;
policy = get_policy(policy_name, lfd)
)
for i in 1:(6*7)
for indv in s.individuals
if rand(Bernoulli(pr_external_infections))
infect!(indv)
function f(school, pr_external_infections, days; n = 1L)
function g(x)
for i in 1:(days)
for indv in x.individuals
if rand(Bernoulli(pr_external_infections))
infect!(indv)
end
end
end
step!(s)
end
evaluate(s)
step!(x)
end
return evaluate(x)
end
return vcat(pmap(g, [resample(school) for i = 1:n])...)
end

function evaluate_performance(
n_per_bubble, bubbles_per_class, m_classes, pr_meet_class, pr_meet_school,
gamma, frac_symptomatic, pr_external_infections, pr_noncovid_symptoms,
pcr,
eta, slope, intercept, ar_window, ar_coefficient,
policy_name, a, b
)
vcat(pmap(evaluate_performance_,
n_per_bubble, bubbles_per_class, m_classes, pr_meet_class, pr_meet_school,
gamma, frac_symptomatic, pr_external_infections, pr_noncovid_symptoms,
pcr,
eta, slope, intercept, ar_window, ar_coefficient,
policy_name, a, b
)...)
end
35 changes: 0 additions & 35 deletions code/expand_scenarios.R

This file was deleted.

182 changes: 182 additions & 0 deletions code/scenario.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
scenario <- function(
n_bubble = 9L,
bubbles_per_class = 3L,
classes_per_school = 12L,
expected_class_contacts = 3,
expected_school_contacts = 1,
frac_symptomatic = 0.5,
pr_noncovid_symptoms = 0.01,
expected_weekly_external_infections = 1,
a = Inf,
b = 1,
lli = 1e6,
pcr_lod = 300.0,
pcr_sens = .975,
pcr_spec = 1.0,
gamma = 0.0,
eta = 1.0,
lfd_spec = 0.998,
ar_window = 3L,
ar_coefficient = 0.0,
days = as.integer(6*7),
...
) {
res <- as.list(environment())

res$pr_meet_class <- expected_class_contacts/(n_class(res) - 1)
res$expected_class_contacts <- NULL
res$pr_meet_school <- expected_school_contacts/(n_school(res) - 1)
res$expected_school_contacts <- NULL
res$pr_external_infection <- max(0, min(1, expected_weekly_external_infections / n_school(res) / 7))
res$expected_weekly_external_infections <- NULL

tbl_innova_data <- tibble(
`viral load` = 10^(2:7),
sensitivity = 1 - (c(621, 521, 344, 207, 144, 123) - 114) / (684 - 114)
)
sensitivity <- function(vl, slope, intercept) {
lfd <- julia_call("LogRegTest", "lfd", slope, intercept, lfd_spec, need_return = "Julia")
julia_call("sensitivity.", lfd, vl, need_return = "R")
}
innova <- optim(
c(.76, -5),
function(x) {
sum((
tbl_innova_data$sensitivity -
sensitivity(tbl_innova_data$`viral load`, slope = x[1], intercept = x[2])
)^2)
},
method = "L-BFGS-B",
lower = c(.1, -10),
upper = c(2.5, 5),
control = list(maxit = 1e4)
)
res$lfd_slope <- innova$par[1]
res$lfd_intercept <- innova$par[2]

res
}

sensitivity <- function(vl, params) {
lfd <- julia_call("LogRegTest", "lfd", params$lfd_slope, params$lfd_intercept, params$lfd_spec, need_return = "Julia")
julia_call("sensitivity.", lfd, vl, need_return = "R")
}

n_class <- function(params) with(params, n_bubble * bubbles_per_class)
n_school <- function(params) with(params, classes_per_school * n_class(params))
n_weekly_infections <- function(params) with(params, 7*n_school(params)*pr_external_infection)

schooldays <- function(params) with(params, sum(((1:days) %% 7) %in% 1:5))

pcr <- function(params) with(params, julia_call("FixedTest", "pcr", pcr_sens, pcr_spec, lod = pcr_lod, need_return = "Julia"))

lfd <- function(params) {
with(params,
julia_call("LogRegTest", "lfd",
eta*params$lfd_slope, params$lfd_intercept, lfd_spec,
ar_window = ar_window, ar_coefficient = ar_coefficient
)
)
}

fit_rzero_ <- function(params, gamma_min = 0, gamma_max = .1) {
tbl_rzero <- tibble(
gamma = seq(gamma_min, gamma_max, length.out = 100),
R = map(gamma, ~{
params$gamma <- .
sample_rzero(do.call(school, params), n = 10L)
})
) %>%
unnest(R)
fit <- lm(formula = R ~ gamma - 1, data = tbl_rzero)
list(fit = fit, data = tbl_rzero)
}
fit_rzero <- memoise::memoise(fit_rzero_)
rzero <- function(gamma, params, gamma_min = 0, gamma_max = .1) {
fit <- fit_rzero(params, gamma_min, gamma_max)$fit
as.numeric(predict(fit, newdata = tibble(gamma = gamma), type = "response"))
}
gamma <- function(R, params, gamma_min = 0, gamma_max = .1) {
as.numeric(uniroot(function(x) rzero(x, params, gamma_min, gamma_max) - R, interval = c(gamma_min, gamma_max))$root)
}

sample_presymptomatic_vl <- function(params, n = 1e5) {
dm <- julia_call("LarremoreModel", params$gamma, frac_symptomatic = params$frac_symptomatic, need_return = "Julia")
individuals <- julia_call("Individual.", dm, rep(params$pr_noncovid_symptoms, n), need_return = "Julia")
julia_call("infect!.", individuals, need_return = "Julia")
julia_call("steps!.", individuals, 21L, need_return = "Julia")
julia_call("get_status_logs", individuals) %>%
as_tibble() %>%
arrange(uuid, day) %>%
group_by(uuid) %>%
filter(
row_number() >= which(viral_load > params$pcr_lod)[1],
row_number() < which(symptomatic)[1]
) %>%
sample_n(1) %>%
ungroup() %>%
select(uuid, day, viral_load)
}
sample_presymptomatic_vl_ <- memoise::memoise(sample_presymptomatic_vl)
mean_sensitivity <- function(params, eta, ...) {
sample_presymptomatic_vl_(params, ...) %>%
mutate(
sensitivity = sensitivity(viral_load^eta, params)
) %>%
pull(sensitivity) %>%
summary() %>%
mean()
}
eta <- function(params, target, ...) {
as.numeric(uniroot(function(x) mean_sensitivity(params, x, ...) - target, interval = c(0, 5))$root)
}

expand_scenario <- function(params = scenario(), ...) {
tbl <- if (length(list(...)) == 0) {
as_tibble(params)
} else {
for (name in names(list(...))) {
params[[name]] <- NULL
}
expand_grid(do.call(expand_grid, list(...)), as_tibble(params))
}
tbl %>%
group_by(row_number()) %>%
nest() %>%
mutate(data = map(data, as.list)) %>%
pull(data) %>%
enframe(value = "params") %>%
select(params) %>%
mutate(
tmp = map(params, ~as_tibble(.))
) %>%
unnest(tmp)
}

julia_eval('@everywhere include("code/evaluate_performance.jl")')
evaluate_performance_ <- function(params, policy, n = 1L) {
school <- do.call(school, c(params, list(policy = policy(params))))
julia_call("f", school, params$pr_external_infection, params$days, n = n) %>%
as_tibble() %>%
mutate(
`% infected (cumulative)` = n_infected/n_school(params),
`% schooldays missed (cumulative)` = workdays_missed/n_school(params)/schooldays(params)
)
}
evaluate_performance <- function(policies, params = scenario(), n = if (!is.null(n_resample)) {n_resample} else {25L}, ...) {
gamma2rs <- memoise::memoise(function(gamma) round(rzero(gamma, params), 1) )
eta2mean_sensitivity <- memoise::memoise(function(eta) round(mean_sensitivity(params, eta), 2) )
expand_scenario(params, ...) %>%
expand_grid(tibble(policy = policies)) %>%
mutate(
policy_name = names(policy),
results = map2(params, policy, evaluate_performance_, n)
) %>%
unnest(results) %>%
select(-params) %>%
mutate(
policy_name = factor(policy_name, levels = names(lst_policies)),
Rs = map_dbl(.data$gamma, gamma2rs),
`mean sensitivity` = map_dbl(.data$eta, eta2mean_sensitivity)
)
}
16 changes: 16 additions & 0 deletions code/school.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
julia_eval('@everywhere include("code/school.jl")')

school <- function(policy = julia_call("DoNothing", need_return = "Julia"), ...){
params <- scenario(...)
with(params,
julia_call("school",
n_bubble, bubbles_per_class, classes_per_school, pr_meet_class, pr_meet_school,
gamma,
frac_symptomatic, pr_noncovid_symptoms,
a, b,
lli,
policy
))
}

sample_rzero <- function(school, days = 21L, n = 1L) julia_call("sample_rzero", school, days, n)

0 comments on commit f27cd34

Please sign in to comment.