| Title: | Estimating Infection Rates from Serological Data |
|---|---|
| Description: | Translates antibody levels measured in cross-sectional population samples into estimates of the frequency with which seroconversions (infections) occur in the sampled populations. Replaces the previous `seroincidence` package. |
| Authors: | Kristina Lai [aut, cre], Chris Orwa [aut], Kwan Ho Lee [ctb], Peter Teunis [aut, cph] (Author of the method and original code.), Kristen Aiemjoy [aut], Douglas Ezra Morrison [aut] |
| Maintainer: | Kristina Lai <[email protected]> |
| License: | GPL-3 |
| Version: | 1.4.1.9046 |
| Built: | 2026-10-09 02:46:42 UTC |
| Source: | https://github.com/ucd-serg/serocalculator |
Analyze simulation results
analyze_sims(data)analyze_sims(data)
data |
a tibble::tbl_df with columns:
|
a sim_results object (extends tibble::tbl_df)
dmcmc <- typhoid_curves_nostrat_100 n_cores <- 2 nclus <- 20 # cross-sectional sample size nrep <- c(50, 200) # incidence rate in e lambdas <- c(.05, .8) antibodies <- c("HlyE_IgA", "HlyE_IgG") lifespan <- c(0, 10) dlims = rbind( "HlyE_IgA" = c(min = 0, max = 0.5), "HlyE_IgG" = c(min = 0, max = 0.5) ) sim_df <- sim_pop_data_multi( n_cores = n_cores, lambdas = lambdas, nclus = nclus, sample_sizes = nrep, age_range = lifespan, antigen_isos = antibodies, renew_params = FALSE, add_noise = TRUE, curve_params = dmcmc, noise_limits = dlims, format = "long" ) cond <- tibble::tibble( antigen_iso = c("HlyE_IgG", "HlyE_IgA"), nu = c(0.5, 0.5), # Biologic noise (nu) eps = c(0, 0), # M noise (eps) y.low = c(1, 1), # low cutoff (llod) y.high = c(5e6, 5e6) ) ests <- est_seroincidence_by( pop_data = sim_df, sr_params = dmcmc, noise_params = cond, num_cores = n_cores, strata = c("lambda.sim", "sample_size", "cluster"), curve_strata_varnames = NULL, noise_strata_varnames = NULL, verbose = FALSE, build_graph = FALSE, # slows down the function substantially antigen_isos = c("HlyE_IgG", "HlyE_IgA") ) ests |> summary() |> analyze_sims()dmcmc <- typhoid_curves_nostrat_100 n_cores <- 2 nclus <- 20 # cross-sectional sample size nrep <- c(50, 200) # incidence rate in e lambdas <- c(.05, .8) antibodies <- c("HlyE_IgA", "HlyE_IgG") lifespan <- c(0, 10) dlims = rbind( "HlyE_IgA" = c(min = 0, max = 0.5), "HlyE_IgG" = c(min = 0, max = 0.5) ) sim_df <- sim_pop_data_multi( n_cores = n_cores, lambdas = lambdas, nclus = nclus, sample_sizes = nrep, age_range = lifespan, antigen_isos = antibodies, renew_params = FALSE, add_noise = TRUE, curve_params = dmcmc, noise_limits = dlims, format = "long" ) cond <- tibble::tibble( antigen_iso = c("HlyE_IgG", "HlyE_IgA"), nu = c(0.5, 0.5), # Biologic noise (nu) eps = c(0, 0), # M noise (eps) y.low = c(1, 1), # low cutoff (llod) y.high = c(5e6, 5e6) ) ests <- est_seroincidence_by( pop_data = sim_df, sr_params = dmcmc, noise_params = cond, num_cores = n_cores, strata = c("lambda.sim", "sample_size", "cluster"), curve_strata_varnames = NULL, noise_strata_varnames = NULL, verbose = FALSE, build_graph = FALSE, # slows down the function substantially antigen_isos = c("HlyE_IgG", "HlyE_IgA") ) ests |> summary() |> analyze_sims()
Antibody decay curve with natural parameters
antibody_decay_curve( t, y0 = 0.74916052, b0 = 1, mu_b = 0.18432798, mu_y = 0.36853621, gamma = 0.0013040664, alpha = 2.192627e-05, rho = 2 )antibody_decay_curve( t, y0 = 0.74916052, b0 = 1, mu_b = 0.18432798, mu_y = 0.36853621, gamma = 0.0013040664, alpha = 2.192627e-05, rho = 2 )
t |
time since infection |
y0 |
initial antibody concentration |
b0 |
initial bacteria concentration |
mu_b |
pathogen reproduction rate |
mu_y |
antibody reproduction rate |
gamma |
bacteria destruction rate per antibody |
alpha |
antibody decay rate |
rho |
antibody decay rate power function parameter |
a numeric() vector
library(ggplot2) ggplot() + geom_function(fun = antibody_decay_curve) + xlim(1, 100)library(ggplot2) ggplot() + geom_function(fun = antibody_decay_curve) + xlim(1, 100)
Load noise parameters
as_noise_params(data, antigen_isos = NULL)as_noise_params(data, antigen_isos = NULL)
data |
|
antigen_isos |
|
a noise_params object (a tibble::tbl_df with
extra attribute antigen_isos)
library(magrittr) noise_data <- serocalculator_example("example_noise_params.csv") %>% read.csv() %>% as_noise_params() print(noise_data)library(magrittr) noise_data <- serocalculator_example("example_noise_params.csv") %>% read.csv() %>% as_noise_params() print(noise_data)
Load a cross-sectional antibody survey data set
as_pop_data( data, antigen_isos = NULL, age = "Age", value = "result", id = "index_id", standardize = TRUE )as_pop_data( data, antigen_isos = NULL, age = "Age", value = "result", id = "index_id", standardize = TRUE )
data |
|
antigen_isos |
|
age |
a |
value |
a |
id |
a |
standardize |
a |
a pop_data object (a tibble::tbl_df
with extra attribute antigen_isos)
library(magrittr) xs_data <- serocalculator_example("example_pop_data.csv") |> read.csv() |> as_pop_data() print(xs_data)library(magrittr) xs_data <- serocalculator_example("example_pop_data.csv") |> read.csv() |> as_pop_data() print(xs_data)
Load longitudinal seroresponse parameters
as_sr_params(data, antigen_isos = NULL)as_sr_params(data, antigen_isos = NULL)
data |
|
antigen_isos |
a |
a curve_data object
(a tibble::tbl_df with extra attribute antigen_isos)
library(magrittr) curve_data <- serocalculator_example("example_curve_params.csv") %>% read.csv() %>% as_curve_params() print(curve_data)library(magrittr) curve_data <- serocalculator_example("example_curve_params.csv") %>% read.csv() %>% as_curve_params() print(curve_data)
Graph antibody decay curves by antigen isotype
## S3 method for class 'curve_params' autoplot( object, method = c("graph.curve.params", "graph_seroresponse_model_1"), ... )## S3 method for class 'curve_params' autoplot( object, method = c("graph.curve.params", "graph_seroresponse_model_1"), ... )
object |
a |
method |
a character string indicating whether to use
|
... |
additional arguments passed to the sub-function
indicated by the |
Currently, the backend for this method is graph.curve.params().
Previously, the backend for this method was graph_seroresponse_model_1().
That function is still available if preferred.
a ggplot2::ggplot() object
library(dplyr) library(ggplot2) library(magrittr) curve <- serocalculator_example("example_curve_params.csv") |> read.csv() |> as_sr_params() |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) |> autoplot() curvelibrary(dplyr) library(ggplot2) library(magrittr) curve <- serocalculator_example("example_curve_params.csv") |> read.csv() |> as_sr_params() |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) |> autoplot() curve
autoplot() method for pop_data objects
## S3 method for class 'pop_data' autoplot(object, log = FALSE, type = "density", strata = NULL, ...)## S3 method for class 'pop_data' autoplot(object, log = FALSE, type = "density", strata = NULL, ...)
object |
A |
log |
whether to show antibody responses on logarithmic scale |
type |
an option to choose type of chart:
the current options are |
strata |
the name of a variable in |
... |
unused |
a ggplot2::ggplot object
library(dplyr) library(ggplot2) library(magrittr) xs_data <- serocalculator_example("example_pop_data.csv") |> read.csv() |> as_pop_data() xs_data |> autoplot(strata = "catchment", type = "density") xs_data |> autoplot(strata = "catchment", type = "age-scatter")library(dplyr) library(ggplot2) library(magrittr) xs_data <- serocalculator_example("example_pop_data.csv") |> read.csv() |> as_pop_data() xs_data |> autoplot(strata = "catchment", type = "density") xs_data |> autoplot(strata = "catchment", type = "age-scatter")
Plot the log-likelihood curve for the incidence rate estimate
## S3 method for class 'seroincidence' autoplot(object, log_x = FALSE, ...)## S3 method for class 'seroincidence' autoplot(object, log_x = FALSE, ...)
object |
a |
log_x |
should the x-axis be on a logarithmic scale ( |
... |
unused |
library(dplyr) library(ggplot2) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est1 <- est_seroincidence( pop_data = xs_data, sr_param = curve, noise_param = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), build_graph = TRUE ) # Plot the log-likelihood curve autoplot(est1)library(dplyr) library(ggplot2) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est1 <- est_seroincidence( pop_data = xs_data, sr_param = curve, noise_param = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), build_graph = TRUE ) # Plot the log-likelihood curve autoplot(est1)
seroincidence.by log-likelihoodsPlots log-likelihood curves by stratum, for seroincidence.by objects
## S3 method for class 'seroincidence.by' autoplot(object, ncol = min(3, length(object)), ...)## S3 method for class 'seroincidence.by' autoplot(object, ncol = min(3, length(object)), ...)
object |
a '"seroincidence.by"' object (from |
ncol |
number of columns to use for panel of plots |
... |
Arguments passed on to
|
a "patchwork" object: a single or list() of ggplot2::ggplot()s
library(dplyr) library(ggplot2) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est2 <- est_seroincidence_by( strata = c("catchment"), pop_data = xs_data, sr_params = curve, curve_strata_varnames= NULL, noise_strata_varnames = NULL, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), #num_cores = 8, #Allow for parallel processing to decrease run time build_graph = TRUE ) # Plot the log-likelihood curve autoplot(est2)library(dplyr) library(ggplot2) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est2 <- est_seroincidence_by( strata = c("catchment"), pop_data = xs_data, sr_params = curve, curve_strata_varnames= NULL, noise_strata_varnames = NULL, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), #num_cores = 8, #Allow for parallel processing to decrease run time build_graph = TRUE ) # Plot the log-likelihood curve autoplot(est2)
autoplot() method for sim_results objectsPlot simulation results
autoplot() method for sim_results objects
## S3 method for class 'sim_results' autoplot( object, statistic = "Empirical_SE", x_var = "sample_size", group_var = "lambda.sim", color_var = group_var, ... )## S3 method for class 'sim_results' autoplot( object, statistic = "Empirical_SE", x_var = "sample_size", group_var = "lambda.sim", color_var = group_var, ... )
object |
a data.frame
containing the columns expected
for a |
statistic |
which column of |
x_var |
character: which column in |
group_var |
character: which column in |
color_var |
character: which column in |
... |
unused |
dmcmc <- typhoid_curves_nostrat_100 n_cores <- 2 nclus <- 20 # cross-sectional sample size nrep <- c(50, 200) # incidence rate in e lambdas <- c(.05, .8) lifespan <- c(0, 10) antibodies <- c("HlyE_IgA", "HlyE_IgG") dlims <- rbind( "HlyE_IgA" = c(min = 0, max = 0.5), "HlyE_IgG" = c(min = 0, max = 0.5) ) sim_df <- sim_pop_data_multi( n_cores = n_cores, lambdas = lambdas, nclus = nclus, sample_sizes = nrep, age_range = lifespan, antigen_isos = antibodies, renew_params = FALSE, add_noise = TRUE, curve_params = dmcmc, noise_limits = dlims, format = "long" ) cond <- tibble::tibble( antigen_iso = c("HlyE_IgG", "HlyE_IgA"), nu = c(0.5, 0.5), # Biologic noise (nu) eps = c(0, 0), # M noise (eps) y.low = c(1, 1), # low cutoff (llod) y.high = c(5e6, 5e6) ) ests <- est_seroincidence_by( pop_data = sim_df, sr_params = dmcmc, noise_params = cond, num_cores = n_cores, strata = c("lambda.sim", "sample_size", "cluster"), curve_strata_varnames = NULL, noise_strata_varnames = NULL, verbose = FALSE, build_graph = FALSE, # slows down the function substantially antigen_isos = c("HlyE_IgG", "HlyE_IgA") ) ests |> summary() |> analyze_sims() |> autoplot() # customize which columns map to the x-axis, group, and color aesthetics ests |> summary() |> analyze_sims() |> autoplot(x_var = "lambda.sim", group_var = "sample_size")dmcmc <- typhoid_curves_nostrat_100 n_cores <- 2 nclus <- 20 # cross-sectional sample size nrep <- c(50, 200) # incidence rate in e lambdas <- c(.05, .8) lifespan <- c(0, 10) antibodies <- c("HlyE_IgA", "HlyE_IgG") dlims <- rbind( "HlyE_IgA" = c(min = 0, max = 0.5), "HlyE_IgG" = c(min = 0, max = 0.5) ) sim_df <- sim_pop_data_multi( n_cores = n_cores, lambdas = lambdas, nclus = nclus, sample_sizes = nrep, age_range = lifespan, antigen_isos = antibodies, renew_params = FALSE, add_noise = TRUE, curve_params = dmcmc, noise_limits = dlims, format = "long" ) cond <- tibble::tibble( antigen_iso = c("HlyE_IgG", "HlyE_IgA"), nu = c(0.5, 0.5), # Biologic noise (nu) eps = c(0, 0), # M noise (eps) y.low = c(1, 1), # low cutoff (llod) y.high = c(5e6, 5e6) ) ests <- est_seroincidence_by( pop_data = sim_df, sr_params = dmcmc, noise_params = cond, num_cores = n_cores, strata = c("lambda.sim", "sample_size", "cluster"), curve_strata_varnames = NULL, noise_strata_varnames = NULL, verbose = FALSE, build_graph = FALSE, # slows down the function substantially antigen_isos = c("HlyE_IgG", "HlyE_IgA") ) ests |> summary() |> analyze_sims() |> autoplot() # customize which columns map to the x-axis, group, and color aesthetics ests |> summary() |> analyze_sims() |> autoplot(x_var = "lambda.sim", group_var = "sample_size")
summary.seroincidence.by objectsPlot method for summary.seroincidence.by objects
## S3 method for class 'summary.seroincidence.by' autoplot(object, type, ...)## S3 method for class 'summary.seroincidence.by' autoplot(object, type, ...)
object |
a |
type |
character string indicating which type of plot to generate. The implemented options are:
|
... |
Arguments passed on to
|
a ggplot2::ggplot() object
library(dplyr) library(ggplot2) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est2 <- est_seroincidence_by( strata = c("catchment", "ageCat"), pop_data = xs_data, sr_params = curve, noise_params = noise, curve_strata_varnames= NULL, noise_strata_varnames = NULL, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), num_cores = 2 # Allow for parallel processing to decrease run time ) est2sum <- summary(est2) est2sum |> autoplot( type ="scatter", xvar = "ageCat", color_var = "catchment", CIs = TRUE, group_var = "catchment") est2sum |> autoplot( type = "bar", yvar = "ageCat", color_var = "catchment", CIs = TRUE)library(dplyr) library(ggplot2) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est2 <- est_seroincidence_by( strata = c("catchment", "ageCat"), pop_data = xs_data, sr_params = curve, noise_params = noise, curve_strata_varnames= NULL, noise_strata_varnames = NULL, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), num_cores = 2 # Allow for parallel processing to decrease run time ) est2sum <- summary(est2) est2sum |> autoplot( type ="scatter", xvar = "ageCat", color_var = "catchment", CIs = TRUE, group_var = "catchment") est2sum |> autoplot( type = "bar", yvar = "ageCat", color_var = "catchment", CIs = TRUE)
Check the formatting of a cross-sectional antibody survey dataset.
check_pop_data(pop_data, verbose = FALSE)check_pop_data(pop_data, verbose = FALSE)
pop_data |
dataset to check |
verbose |
whether to print an "OK" message when all checks pass |
NULL (invisibly)
library(magrittr) xs_data <- serocalculator_example("example_pop_data.csv") |> read.csv() |> as_pop_data() check_pop_data(xs_data, verbose = TRUE)library(magrittr) xs_data <- serocalculator_example("example_pop_data.csv") |> read.csv() |> as_pop_data() check_pop_data(xs_data, verbose = TRUE)
Perform a two-sample z-test to compare seroincidence rates between two groups. Since we use maximum likelihood estimation (MLE) for each seroincidence estimate and estimates from different strata or data sets are uncorrelated, we can use a simple two-sample z-test using the Gaussian distribution. The standard error for the difference is computed by adding the estimated variances and taking the square root.
compare_seroincidence(x, y = NULL, coverage = 0.95, verbose = FALSE, ...) ## S3 method for class 'seroincidence' compare_seroincidence(x, y = NULL, coverage = 0.95, verbose = FALSE, ...) ## S3 method for class 'seroincidence.by' compare_seroincidence(x, y = NULL, coverage = 0.95, verbose = FALSE, ...)compare_seroincidence(x, y = NULL, coverage = 0.95, verbose = FALSE, ...) ## S3 method for class 'seroincidence' compare_seroincidence(x, y = NULL, coverage = 0.95, verbose = FALSE, ...) ## S3 method for class 'seroincidence.by' compare_seroincidence(x, y = NULL, coverage = 0.95, verbose = FALSE, ...)
x |
A |
y |
A |
coverage |
Desired confidence interval coverage probability (default = 0.95) |
verbose |
Logical indicating whether to print verbose messages (default = FALSE) |
... |
Additional arguments (currently unused) |
When comparing two single "seroincidence" objects, this function performs a
two-sample z-test and returns results in the standard htest format.
When applied to a "seroincidence.by" object (stratified estimates),
the function compares all pairs of strata and returns a nicely formatted
table with point estimates for the difference in seroincidence, p-values,
and confidence intervals.
The test statistic is computed as:
where and are the estimated incidence rates,
and and are their standard errors.
When comparing two "seroincidence" objects: An object of class
"htest" containing the test statistic, p-value, confidence interval,
and estimates.
When applied to a "seroincidence.by" object: A tibble::tibble()
with columns for each pair of strata, the difference in incidence rates,
standard error, z-statistic, p-value, and confidence interval bounds.
compare_seroincidence(seroincidence): Compare two single seroincidence
estimates
compare_seroincidence(seroincidence.by): Compare all pairs of stratified
seroincidence estimates
## Not run: # See inst/examples/exm-compare_seroincidence.R for complete examples ## End(Not run)## Not run: # See inst/examples/exm-compare_seroincidence.R for complete examples ## End(Not run)
Launch the interactive Shiny app for the antigen-antibody kinetics model
curve_app()curve_app()
NULL (invisibly)
## Not run: curve_app() ## End(Not run)## Not run: curve_app() ## End(Not run)
This function models seroincidence using maximum likelihood estimation; that is, it finds the value of the seroincidence parameter which maximizes the likelihood (i.e., joint probability) of the data.
est_seroincidence( pop_data, sr_params, noise_params, antigen_isos = get_biomarker_names(pop_data), lambda_start = 0.1, stepmin = 1e-08, stepmax = 3, verbose = FALSE, build_graph = FALSE, print_graph = build_graph & verbose, cluster_var = NULL, stratum_var = NULL, sampling_weights = NULL, method = c("composite", "joint"), ... )est_seroincidence( pop_data, sr_params, noise_params, antigen_isos = get_biomarker_names(pop_data), lambda_start = 0.1, stepmin = 1e-08, stepmax = 3, verbose = FALSE, build_graph = FALSE, print_graph = build_graph & verbose, cluster_var = NULL, stratum_var = NULL, sampling_weights = NULL, method = c("composite", "joint"), ... )
pop_data |
a data.frame with cross-sectional serology data per antibody and age, and additional columns |
sr_params |
a
|
noise_params |
a
|
antigen_isos |
Character vector with one or more antibody names.
Must match |
lambda_start |
starting guess for incidence rate, in events/year. |
stepmin |
A positive scalar providing the minimum allowable relative step length. |
stepmax |
a positive scalar which gives the maximum allowable
scaled step length. |
verbose |
logical: if TRUE, print verbose log information to console |
build_graph |
whether to graph the log-likelihood function across a range of incidence rates (lambda values) |
print_graph |
whether to display the log-likelihood curve graph
in the course of running |
cluster_var |
optional name(s) of the variable(s) in |
stratum_var |
optional name of the variable in |
sampling_weights |
optional data.frame containing sampling weights with columns for cluster/stratum identifiers and their sampling probabilities. Currently not implemented; reserved for future use. |
method |
how to combine several biomarkers into one likelihood;
see |
... |
Arguments passed on to
|
a "seroincidence" object, which is a stats::nlm() fit object
with extra metadata attributes lambda_start, antigen_isos, and ll_graph
library(dplyr) xs_data <- sees_pop_data_pk_100 sr_curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk # Basic usage without clustering est1 <- est_seroincidence( pop_data = xs_data, sr_params = sr_curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), ) summary(est1) # Usage with clustered sampling design # Standard errors will be adjusted for within-cluster correlation est2 <- est_seroincidence( pop_data = xs_data, sr_params = sr_curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), cluster_var = "cluster" ) summary(est2) # With both cluster and stratum variables est3 <- est_seroincidence( pop_data = xs_data, sr_params = sr_curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), cluster_var = "cluster", stratum_var = "catchment" ) summary(est3) # Shared-latent-time (joint) likelihood across the two biomarkers est4 <- est_seroincidence( pop_data = xs_data, sr_params = sr_curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), method = "joint" ) summary(est4)library(dplyr) xs_data <- sees_pop_data_pk_100 sr_curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk # Basic usage without clustering est1 <- est_seroincidence( pop_data = xs_data, sr_params = sr_curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), ) summary(est1) # Usage with clustered sampling design # Standard errors will be adjusted for within-cluster correlation est2 <- est_seroincidence( pop_data = xs_data, sr_params = sr_curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), cluster_var = "cluster" ) summary(est2) # With both cluster and stratum variables est3 <- est_seroincidence( pop_data = xs_data, sr_params = sr_curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), cluster_var = "cluster", stratum_var = "catchment" ) summary(est3) # Shared-latent-time (joint) likelihood across the two biomarkers est4 <- est_seroincidence( pop_data = xs_data, sr_params = sr_curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), method = "joint" ) summary(est4)
Function to estimate seroincidences based on cross-sectional serology data and longitudinal response model.
est_seroincidence_by( pop_data, sr_params, noise_params, strata, curve_strata_varnames = strata, noise_strata_varnames = strata, antigen_isos = unique(pull(pop_data, "antigen_iso")), lambda_start = 0.1, build_graph = FALSE, num_cores = 1L, verbose = FALSE, print_graph = FALSE, cluster_var = NULL, stratum_var = NULL, method = c("composite", "joint"), ... )est_seroincidence_by( pop_data, sr_params, noise_params, strata, curve_strata_varnames = strata, noise_strata_varnames = strata, antigen_isos = unique(pull(pop_data, "antigen_iso")), lambda_start = 0.1, build_graph = FALSE, num_cores = 1L, verbose = FALSE, print_graph = FALSE, cluster_var = NULL, stratum_var = NULL, method = c("composite", "joint"), ... )
pop_data |
a data.frame with cross-sectional serology data per
antibody and age, and additional columns corresponding to
each element of the |
sr_params |
a
|
noise_params |
a
|
strata |
a character vector of stratum-defining variables.
Values must be variable names in |
curve_strata_varnames |
A subset of |
noise_strata_varnames |
A subset of |
antigen_isos |
Character vector with one or more antibody names.
Must match |
lambda_start |
starting guess for incidence rate, in events/year. |
build_graph |
whether to graph the log-likelihood function across a range of incidence rates (lambda values) |
num_cores |
Number of processor cores to use for calculations when computing by strata. If set to more than 1 and package parallel is available, then the computations are executed in parallel. Default = 1L. |
verbose |
logical: if TRUE, print verbose log information to console |
print_graph |
whether to display the log-likelihood curve graph
in the course of running |
cluster_var |
optional name(s) of the variable(s) in |
stratum_var |
optional name of the variable in |
method |
how to combine several biomarkers into one likelihood;
see |
... |
Arguments passed on to
|
If strata is left empty, a warning will be produced,
recommending that you use est_seroincidence() for unstratified analyses,
and then the data will be passed to est_seroincidence().
If for some reason you want to use est_seroincidence_by()
with no strata instead of calling est_seroincidence(),
you may use NA, NULL, or "" as the strata
argument to avoid that warning.
if strata has meaningful inputs:
An object of class "seroincidence.by"; i.e., a list of
"seroincidence" objects from est_seroincidence(), one for each stratum,
with some meta-data attributes.
if strata is missing, NULL, NA, or "":
An object of class "seroincidence".
library(dplyr) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est2 <- est_seroincidence_by( strata = "catchment", pop_data = xs_data, sr_params = curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), # num_cores = 8 # Allow for parallel processing to decrease run time iterlim = 5 # limit iterations for the purpose of this example ) print(est2) summary(est2)library(dplyr) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est2 <- est_seroincidence_by( strata = "catchment", pop_data = xs_data, sr_params = curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), # num_cores = 8 # Allow for parallel processing to decrease run time iterlim = 5 # limit iterations for the purpose of this example ) print(est2) summary(est2)
A caching wrapper around est_seroincidence_by(). The first call estimates
and saves; later calls with the same arguments load the saved result.
est_seroincidence_by_cached( ..., cache_path = "cache/", cache_id = "est_seroincidence_by", cache_rerun = FALSE, cache_verbose = TRUE, cache_extra = NULL )est_seroincidence_by_cached( ..., cache_path = "cache/", cache_id = "est_seroincidence_by", cache_rerun = FALSE, cache_verbose = TRUE, cache_extra = NULL )
... |
Arguments passed on to
|
cache_path |
a |
cache_id |
a |
cache_rerun |
a |
cache_verbose |
a |
cache_extra |
an object folded into the cache key alongside the
arguments. |
The cache is keyed on the arguments, with the same scope and the same
caveat about implementation changes described in
sim_pop_data_multi_cached().
Note that build_graph = TRUE attaches a log-likelihood plot to every
stratum, which makes the returned object far larger on disk than the same
fit without graphs. When caching many strata, prefer build_graph = FALSE
and re-fit the handful of strata you actually plot.
a "seroincidence.by" object, as returned by
est_seroincidence_by().
library(dplyr) antibodies <- c("HlyE_IgA", "HlyE_IgG") curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% antibodies) # Examples must not write into the user's working directory, so send the # cache to a temporary one. cache_dir <- file.path(tempdir(), "serocalculator-example-cache") ests <- est_seroincidence_by_cached( pop_data = sees_pop_data_pk_100, sr_params = curve, noise_params = example_noise_params_pk, strata = "catchment", antigen_isos = antibodies, build_graph = FALSE, num_cores = 1, iterlim = 5, # limit iterations for the purpose of this example cache_path = cache_dir ) summary(ests)library(dplyr) antibodies <- c("HlyE_IgA", "HlyE_IgG") curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% antibodies) # Examples must not write into the user's working directory, so send the # cache to a temporary one. cache_dir <- file.path(tempdir(), "serocalculator-example-cache") ests <- est_seroincidence_by_cached( pop_data = sees_pop_data_pk_100, sr_params = curve, noise_params = example_noise_params_pk, strata = "catchment", antigen_isos = antibodies, build_graph = FALSE, num_cores = 1, iterlim = 5, # limit iterations for the purpose of this example cache_path = cache_dir ) summary(ests)
A subset of noise parameter estimates from the SEES study, for examples and testing, for Pakistan
example_noise_params_pkexample_noise_params_pk
example_noise_params_pkA curve_params object (from as_sr_params()) with 4 rows and 7 columns:
which antigen and isotype are being measured (data is in long format)
Location for which the noise parameters were estimated
Lower limit of detection
Measurement noise: the bound on the relative measurement
error. The relative error is modeled as uniform on the interval from
-eps to eps, so eps is the largest relative deviation a
measurement can have from its true value. Assay precision is often
reported as a coefficient of variation (CV), the ratio of the standard
deviation to the mean for replicates, ideally measured across plates
rather than within the same plate; under this uniform model the CV
equals eps / sqrt(3), so a measured CV corresponds to
eps = sqrt(3) * CV.
Biological noise: error from cross-reactivity to other antibodies. It is defined as the 95th percentile of the distribution of antibody responses to the antigen-isotype in a population with no exposure.
Upper limit of detection
Lab for which noise was estimated.
A subset of noise parameter estimates from the SEES study, for examples and testing.
example_noise_params_seesexample_noise_params_sees
example_noise_params_pkA curve_params object (from as_sr_params()) with 4 rows and 7 columns:
which antigen and isotype are being measured (data is in long format)
Location for which the noise parameters were estimated
Lower limit of detection
Measurement noise: the bound on the relative measurement
error. The relative error is modeled as uniform on the interval from
-eps to eps, so eps is the largest relative deviation a
measurement can have from its true value. Assay precision is often
reported as a coefficient of variation (CV), the ratio of the standard
deviation to the mean for replicates, ideally measured across plates
rather than within the same plate; under this uniform model the CV
equals eps / sqrt(3), so a measured CV corresponds to
eps = sqrt(3) * CV.
Biological noise: error from cross-reactivity to other antibodies. It is defined as the 95th percentile of the distribution of antibody responses to the antigen-isotype in a population with no exposure.
Upper limit of detection
Lab for which noise was estimated.
Extract biomarker levels
get_biomarker_levels(object, ...)get_biomarker_levels(object, ...)
object |
a |
... |
unused |
the biomarker levels in object
sees_pop_data_100 |> get_biomarker_levels()sees_pop_data_100 |> get_biomarker_levels()
Get biomarker variable name
get_biomarker_names_var(object, ...)get_biomarker_names_var(object, ...)
object |
a |
... |
unused |
a character string identifying the biomarker names column in object
sees_pop_data_100 |> get_biomarker_names_var()sees_pop_data_100 |> get_biomarker_names_var()
Get antibody measurement values
get_values(object, ...)get_values(object, ...)
object |
a |
... |
unused |
a numeric vector of antibody measurement values
sees_pop_data_100 |> get_values()sees_pop_data_100 |> get_values()
Extract antibody measurement values
get_values_var(object, ...)get_values_var(object, ...)
object |
a |
... |
unused |
the name of the column in object specified as containing
antibody abundance measurements
sees_pop_data_100 |> get_values_var()sees_pop_data_100 |> get_values_var()
Graph log-likelihood of data
graph_loglik( pop_data, curve_params, noise_params, antigen_isos = pop_data %>% get_biomarker_levels(), x = 10^seq(-3, 0, by = 0.1), highlight_points = NULL, highlight_point_names = "highlight_points", log_x = FALSE, previous_plot = NULL, curve_label = paste(antigen_isos, collapse = " + "), ... )graph_loglik( pop_data, curve_params, noise_params, antigen_isos = pop_data %>% get_biomarker_levels(), x = 10^seq(-3, 0, by = 0.1), highlight_points = NULL, highlight_point_names = "highlight_points", log_x = FALSE, previous_plot = NULL, curve_label = paste(antigen_isos, collapse = " + "), ... )
pop_data |
a |
curve_params |
a
|
noise_params |
a
|
antigen_isos |
Character vector listing one or more antigen isotypes.
Values must match |
x |
sequence of lambda values to graph |
highlight_points |
a possible highlighted value |
highlight_point_names |
labels for highlighted points |
log_x |
should the x-axis be on a logarithmic scale ( |
previous_plot |
if not NULL, the current data is added to the existing graph |
curve_label |
if not NULL, add a label for the curve |
... |
Arguments passed on to
|
library(dplyr) library(tibble) # Load cross-sectional data xs_data <- sees_pop_data_pk_100 # Load curve parameters and subset for the purposes of this example curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) # Load noise parameters cond <- tibble( antigen_iso = c("HlyE_IgG", "HlyE_IgA"), nu = c(0.5, 0.5), # Biologic noise (nu) eps = c(0, 0), # M noise (eps) y.low = c(1, 1), # Low cutoff (llod) y.high = c(5e6, 5e6)) # High cutoff (y.high) # Graph the log likelihood lik_HlyE_IgA <- # nolint: object_name_linter graph_loglik( pop_data = xs_data, curve_params = curve, noise_params = cond, antigen_isos = "HlyE_IgA", log_x = TRUE ) lik_HlyE_IgA # nolint: object_name_linterlibrary(dplyr) library(tibble) # Load cross-sectional data xs_data <- sees_pop_data_pk_100 # Load curve parameters and subset for the purposes of this example curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) # Load noise parameters cond <- tibble( antigen_iso = c("HlyE_IgG", "HlyE_IgA"), nu = c(0.5, 0.5), # Biologic noise (nu) eps = c(0, 0), # M noise (eps) y.low = c(1, 1), # Low cutoff (llod) y.high = c(5e6, 5e6)) # High cutoff (y.high) # Graph the log likelihood lik_HlyE_IgA <- # nolint: object_name_linter graph_loglik( pop_data = xs_data, curve_params = curve, noise_params = cond, antigen_isos = "HlyE_IgA", log_x = TRUE ) lik_HlyE_IgA # nolint: object_name_linter
Graph estimated antibody decay curves
graph.curve.params( object, antigen_isos = unique(object$antigen_iso), verbose = FALSE, quantiles = c(0.1, 0.5, 0.9), alpha_samples = 0.3, chain_color = TRUE, log_x = FALSE, log_y = TRUE, n_curves = 100, iters_to_graph = head(unique(object$iter), n_curves), ... )graph.curve.params( object, antigen_isos = unique(object$antigen_iso), verbose = FALSE, quantiles = c(0.1, 0.5, 0.9), alpha_samples = 0.3, chain_color = TRUE, log_x = FALSE, log_y = TRUE, n_curves = 100, iters_to_graph = head(unique(object$iter), n_curves), ... )
object |
a |
antigen_isos |
antigen isotypes to analyze
(can subset |
verbose |
verbose output |
quantiles |
Optional numeric vector of point-wise (over time)
quantiles to plot (e.g., 10%, 50%, and 90% = |
alpha_samples |
|
chain_color |
logical: if TRUE (default), MCMC chain lines are colored by chain. If FALSE, all MCMC chain lines are black. |
log_x |
should the x-axis be on a logarithmic scale ( |
log_y |
should the Y-axis be on a logarithmic scale
(default, |
n_curves |
how many curves to plot (see details). |
iters_to_graph |
which MCMC iterations in |
... |
not currently used |
... argumentsThe arguments fun, n, and args are set internally and cannot be
overridden via .... Passing them will trigger an informative error.
n_curves and iters_to_graph
In most cases, object will contain too many rows of MCMC
samples for all of these samples to be plotted at once.
Setting the n_curves argument to a value smaller than the
number of rows in curve_params will cause this function to select
the first n_curves rows to graph.
Setting n_curves larger than the number of rows in ' will
result all curves being plotted.
If the user directly specifies the iters_to_graph argument,
then n_curves has no effect.
a ggplot2::ggplot() object showing the antibody dynamic
kinetics of selected antigen/isotype combinations, with optional posterior
distribution quantile curves.
# Load example dataset curve <- typhoid_curves_nostrat_100 |> dplyr::filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) # Plot quantiles without showing all curves plot1 <- graph.curve.params(curve, n_curves = 0) print(plot1) # Plot with additional quantiles and show all curves plot2 <- graph.curve.params( curve, n_curves = Inf, quantiles = c(0.1, 0.5, 0.9) ) print(plot2) # Plot with MCMC chains in black plot3 <- graph.curve.params( curve, n_curves = Inf, quantiles = c(0.1, 0.5, 0.9), chain_color = FALSE ) print(plot3)# Load example dataset curve <- typhoid_curves_nostrat_100 |> dplyr::filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) # Plot quantiles without showing all curves plot1 <- graph.curve.params(curve, n_curves = 0) print(plot1) # Plot with additional quantiles and show all curves plot2 <- graph.curve.params( curve, n_curves = Inf, quantiles = c(0.1, 0.5, 0.9) ) print(plot2) # Plot with MCMC chains in black plot3 <- graph.curve.params( curve, n_curves = Inf, quantiles = c(0.1, 0.5, 0.9), chain_color = FALSE ) print(plot3)
Load noise parameters
load_noise_params(file_path, antigen_isos = NULL)load_noise_params(file_path, antigen_isos = NULL)
file_path |
path to an RDS file containing biologic
and measurement noise of antibody decay curve parameters
|
antigen_isos |
|
a noise object (a tibble::tbl_df
with extra attribute antigen_isos)
noise <- load_noise_params( serocalculator_example("example_noise_params.rds") ) print(noise)noise <- load_noise_params( serocalculator_example("example_noise_params.rds") ) print(noise)
Load a cross-sectional antibody survey data set
load_pop_data(file_path, ...)load_pop_data(file_path, ...)
file_path |
path to an RDS file containing a cross-sectional antibody
survey data set, stored as a |
... |
Arguments passed on to
|
a pop_data object (a tibble::tbl_df with extra attributes)
xs_data <- load_pop_data(serocalculator_example("example_pop_data.rds")) print(xs_data)xs_data <- load_pop_data(serocalculator_example("example_pop_data.rds")) print(xs_data)
Load longitudinal seroresponse parameter samples
load_sr_params(file_path, antigen_isos = NULL)load_sr_params(file_path, antigen_isos = NULL)
file_path |
path to an RDS file containing MCMC samples of antibody
seroresponse parameters |
antigen_isos |
|
a curve_params object (a tibble::tbl_df
with extra attribute antigen_isos)
curve <- load_sr_params(serocalculator_example("example_curve_params.rds")) print(curve)curve <- load_sr_params(serocalculator_example("example_curve_params.rds")) print(curve)
Calculates the log-likelihood of a set of cross-sectional antibody response
data, for a given incidence rate (lambda) value.
log_likelihood( lambda, pop_data, curve_params, noise_params, antigen_isos = get_biomarker_levels(pop_data), verbose = FALSE, method = c("composite", "joint"), ... )log_likelihood( lambda, pop_data, curve_params, noise_params, antigen_isos = get_biomarker_levels(pop_data), verbose = FALSE, method = c("composite", "joint"), ... )
lambda |
a numeric vector of incidence parameters, in events per person-year |
pop_data |
a |
curve_params |
a
|
noise_params |
a
|
antigen_isos |
Character vector listing one or more antigen isotypes.
Values must match |
verbose |
logical: if TRUE, print verbose log information to console |
method |
how to combine several biomarkers into one likelihood:
With a single biomarker the two methods coincide. See issues #637 and #646. |
... |
additional arguments passed to |
the log-likelihood of the data with the current parameter values
library(dplyr) library(tibble) # Load cross-sectional data xs_data <- sees_pop_data_pk_100 # Load curve parameters and subset for the purposes of this example curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) # Load noise params cond <- tibble( antigen_iso = c("HlyE_IgG", "HlyE_IgA"), nu = c(0.5, 0.5), # Biologic noise (nu) eps = c(0, 0), # M noise (eps) y.low = c(1, 1), # low cutoff (llod) y.high = c(5e6, 5e6) ) # high cutoff (y.high) # Calculate log-likelihood ll_AG <- log_likelihood( pop_data = xs_data, curve_params = curve, noise_params = cond, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), lambda = 0.1 ) %>% print() # The same data under the shared-latent-time (joint) likelihood ll_joint <- log_likelihood( pop_data = xs_data, curve_params = curve, noise_params = cond, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), lambda = 0.1, method = "joint" ) %>% print()library(dplyr) library(tibble) # Load cross-sectional data xs_data <- sees_pop_data_pk_100 # Load curve parameters and subset for the purposes of this example curve <- typhoid_curves_nostrat_100 %>% filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) # Load noise params cond <- tibble( antigen_iso = c("HlyE_IgG", "HlyE_IgA"), nu = c(0.5, 0.5), # Biologic noise (nu) eps = c(0, 0), # M noise (eps) y.low = c(1, 1), # low cutoff (llod) y.high = c(5e6, 5e6) ) # high cutoff (y.high) # Calculate log-likelihood ll_AG <- log_likelihood( pop_data = xs_data, curve_params = curve, noise_params = cond, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), lambda = 0.1 ) %>% print() # The same data under the shared-latent-time (joint) likelihood ll_joint <- log_likelihood( pop_data = xs_data, curve_params = curve, noise_params = cond, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), lambda = 0.1, method = "joint" ) %>% print()
Pathogen decay curve
pathogen_decay_curve( t, y0 = 0.74916052, b0 = 1, mu_b = 0.18432798, mu_y = 0.36853621, gamma = 0.0013040664 )pathogen_decay_curve( t, y0 = 0.74916052, b0 = 1, mu_b = 0.18432798, mu_y = 0.36853621, gamma = 0.0013040664 )
t |
time since infection |
y0 |
initial antibody concentration |
b0 |
initial bacteria concentration |
mu_b |
pathogen reproduction rate |
mu_y |
antibody reproduction rate |
gamma |
bacteria destruction rate per antibody |
library(ggplot2) ggplot() + geom_function( fun = pathogen_decay_curve, args = list( y0 = 0.74916052, b0 = 1, mu_b = 0.18432798, mu_y = 0.36853621, gamma = 0.0013040664 ) ) + xlim(0, 100)library(ggplot2) ggplot() + geom_function( fun = pathogen_decay_curve, args = list( y0 = 0.74916052, b0 = 1, mu_b = 0.18432798, mu_y = 0.36853621, gamma = 0.0013040664 ) ) + xlim(0, 100)
Plot a decay function
plot_decay_curve( decay_function = antibody_decay_curve, ..., xmax = 100, ymax = NA, title = "" )plot_decay_curve( decay_function = antibody_decay_curve, ..., xmax = 100, ymax = NA, title = "" )
decay_function |
a function with first argument |
... |
parameters passed to |
xmax |
upper limit of x axis |
ymax |
upper limit of y axis |
title |
plot title |
plot_decay_curve(antibody_decay_curve)plot_decay_curve(antibody_decay_curve)
Companion to est_seroincidence_by_cached(). Caching a fit built with
build_graph = TRUE is impractical over many strata, because a
log-likelihood plot is attached to each one; the usual pattern is to cache
the whole fit with build_graph = FALSE and then re-fit, with graphs, only
the handful of strata you actually want to plot.
refit_strata(pop_data, strata_ids, strata = names(strata_ids), ...)refit_strata(pop_data, strata_ids, strata = names(strata_ids), ...)
pop_data |
a |
strata_ids |
a |
strata |
a |
... |
Arguments passed on to
|
Strata are selected by the columns that define them rather than by index or
by label, because count_strata() names strata positionally
(paste("Stratum", row_number())). A subset therefore renumbers them, so
labels and positions from the full fit do not carry over.
a "seroincidence.by" object covering only the selected strata,
with graphs attached, or NULL if strata_ids has no rows.
ests <- est_seroincidence_by( pop_data = sees_pop_data_pk_100, sr_params = typhoid_curves_nostrat_100, noise_params = example_noise_params_pk, strata = "catchment", antigen_isos = c("HlyE_IgG", "HlyE_IgA"), build_graph = FALSE, iterlim = 5 ) # Re-fit just the strata whose optimizer flagged a possible problem. problem_ids <- ests |> summary() |> tibble::as_tibble() |> dplyr::filter(.data$nlm.convergence.code > 2) |> dplyr::select("catchment") refit_strata( pop_data = sees_pop_data_pk_100, strata_ids = problem_ids, sr_params = typhoid_curves_nostrat_100, noise_params = example_noise_params_pk, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), iterlim = 5 )ests <- est_seroincidence_by( pop_data = sees_pop_data_pk_100, sr_params = typhoid_curves_nostrat_100, noise_params = example_noise_params_pk, strata = "catchment", antigen_isos = c("HlyE_IgG", "HlyE_IgA"), build_graph = FALSE, iterlim = 5 ) # Re-fit just the strata whose optimizer flagged a possible problem. problem_ids <- ests |> summary() |> tibble::as_tibble() |> dplyr::filter(.data$nlm.convergence.code > 2) |> dplyr::select("catchment") refit_strata( pop_data = sees_pop_data_pk_100, strata_ids = problem_ids, sr_params = typhoid_curves_nostrat_100, noise_params = example_noise_params_pk, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), iterlim = 5 )
A subset of data from the SEES data, for examples and testing.
sees_pop_data_100sees_pop_data_100
sees_pop_data_100A pop_data object (from as_pop_data()) with 1000 rows and 8 columns:
Pseudonymous participant ID, shared across biomarker rows
Country where the participant was living
survey sampling cluster
survey catchment area
participant's age when sampled, in years
which antigen and isotype are being measured (data is in long format)
concentration of antigen isotype, in ELISA units
A subset of data from the SEES data, for examples and testing, data from Pakistan only.
sees_pop_data_pk_100sees_pop_data_pk_100
sees_pop_data_pk_100A pop_data object (from as_pop_data()) with 200 rows and 8 columns:
Pseudonymous participant ID, shared across biomarker rows
Country where the participant was living
survey sampling cluster
survey catchment area
participant's age when sampled, in years
which antigen and isotype are being measured (data is in long format)
concentration of antigen isotype, in ELISA units
"seroincidence.by" objectTyphoid seroconversion rate estimates by country and age category from the SEES study.
sees_typhoid_ests_stratsees_typhoid_ests_strat
An object of class seroincidence.by (inherits from list) of length 9.
serocalculator/data-raw/sees_typhoid_ests_strat.R
The serocalculator package comes bundled with a number of sample files
in its inst/extdata directory.
This serocalculator_example() function make those sample files
easy to access.
serocalculator_example(file = NULL)serocalculator_example(file = NULL)
file |
Name of file. If |
Adapted from readr::readr_example() following the guidance in
https://r-pkgs.org/data.html#sec-data-example-path-helper.
a character string providing
the path to the file specified by file,
or a vector or available files if file = NULL.
serocalculator_example() serocalculator_example("example_pop_data.csv")serocalculator_example() serocalculator_example("example_pop_data.csv")
Makes a cross-sectional data set (age, y(t) set) and adds noise, if desired.
sim_pop_data( lambda = 0.1, n_samples = 100, age_range = c(0, 20), age_fixed = NA, antigen_isos = intersect(get_biomarker_levels(curve_params), rownames(noise_limits)), n_mcmc_samples = 0, renew_params = FALSE, add_noise = FALSE, curve_params, noise_limits, format = "wide", verbose = FALSE, ... )sim_pop_data( lambda = 0.1, n_samples = 100, age_range = c(0, 20), age_fixed = NA, antigen_isos = intersect(get_biomarker_levels(curve_params), rownames(noise_limits)), n_mcmc_samples = 0, renew_params = FALSE, add_noise = FALSE, curve_params, noise_limits, format = "wide", verbose = FALSE, ... )
lambda |
a |
n_samples |
number of samples to simulate |
age_range |
age range of sampled individuals, in years |
age_fixed |
specify the curve parameters to use by age (does nothing at present?) |
antigen_isos |
Character vector with one or more antibody names.
Values must match |
n_mcmc_samples |
how many MCMC samples to use:
|
renew_params |
whether to generate a new parameter set for each infection
|
add_noise |
a |
curve_params |
a |
noise_limits |
biologic noise distribution parameters |
format |
a
|
verbose |
verbosity level for console logging. Accepts a logical scalar or a non-negative whole number:
|
... |
Arguments passed on to |
a tibble::tbl_df containing simulated cross-sectional serosurvey data, with columns:
age: age (in years)
one column for each element in the antigen_isos input argument
# Load curve parameters dmcmc <- typhoid_curves_nostrat_100 # Specify the antibody-isotype responses to include in analyses antibodies <- c("HlyE_IgA", "HlyE_IgG") # Set seed to reproduce results set.seed(54321) # Simulated incidence rate per person-year lambda <- 0.2 # Range covered in simulations lifespan <- c(0, 10) # Cross-sectional sample size nrep <- 100 # Biologic noise distribution dlims <- rbind( "HlyE_IgA" = c(min = 0, max = 0.5), "HlyE_IgG" = c(min = 0, max = 0.5) ) # Generate cross-sectional data csdata <- sim_pop_data( curve_params = dmcmc, lambda = lambda, n_samples = nrep, age_range = lifespan, antigen_isos = antibodies, n_mcmc_samples = 0, renew_params = TRUE, add_noise = TRUE, noise_limits = dlims, format = "long" )# Load curve parameters dmcmc <- typhoid_curves_nostrat_100 # Specify the antibody-isotype responses to include in analyses antibodies <- c("HlyE_IgA", "HlyE_IgG") # Set seed to reproduce results set.seed(54321) # Simulated incidence rate per person-year lambda <- 0.2 # Range covered in simulations lifespan <- c(0, 10) # Cross-sectional sample size nrep <- 100 # Biologic noise distribution dlims <- rbind( "HlyE_IgA" = c(min = 0, max = 0.5), "HlyE_IgG" = c(min = 0, max = 0.5) ) # Generate cross-sectional data csdata <- sim_pop_data( curve_params = dmcmc, lambda = lambda, n_samples = nrep, age_range = lifespan, antigen_isos = antibodies, n_mcmc_samples = 0, renew_params = TRUE, add_noise = TRUE, noise_limits = dlims, format = "long" )
Simulate multiple data sets
sim_pop_data_multi( nclus = 10, sample_sizes = 100, lambdas = c(0.05, 0.1, 0.15, 0.2, 0.3), num_cores = max(1, parallel::detectCores() - 1), rng_seed = 1234, verbose = FALSE, sim_function = sim_pop_data, ... )sim_pop_data_multi( nclus = 10, sample_sizes = 100, lambdas = c(0.05, 0.1, 0.15, 0.2, 0.3), num_cores = max(1, parallel::detectCores() - 1), rng_seed = 1234, verbose = FALSE, sim_function = sim_pop_data, ... )
nclus |
number of clusters |
sample_sizes |
sample sizes to simulate |
lambdas |
incidence rate, in events/person*year |
num_cores |
number of cores to use for parallel computations |
rng_seed |
starting seed for random number generator,
passed to |
verbose |
whether to report verbose information |
sim_function |
which function to use: |
... |
Arguments passed on to
|
# Load curve parameters dmcmc <- typhoid_curves_nostrat_100 # Specify the antibody-isotype responses to include in analyses antibodies <- c("HlyE_IgA", "HlyE_IgG") # Set seed to reproduce results set.seed(54321) # Simulated incidence rate per person-year lambdas = c(.05, .1, .15, .2, .3) # Range covered in simulations lifespan <- c(0, 10); # Cross-sectional sample size nrep <- 100 # Biologic noise distribution dlims <- rbind( "HlyE_IgA" = c(min = 0, max = 0.5), "HlyE_IgG" = c(min = 0, max = 0.5) ) sim_data <- sim_pop_data_multi( curve_params = dmcmc, lambdas = lambdas, sample_sizes = nrep, age_range = lifespan, antigen_isos = antibodies, n_mcmc_samples = 0, renew_params = TRUE, add_noise = TRUE, noise_limits = dlims, format = "long", nclus = 10) sim_data# Load curve parameters dmcmc <- typhoid_curves_nostrat_100 # Specify the antibody-isotype responses to include in analyses antibodies <- c("HlyE_IgA", "HlyE_IgG") # Set seed to reproduce results set.seed(54321) # Simulated incidence rate per person-year lambdas = c(.05, .1, .15, .2, .3) # Range covered in simulations lifespan <- c(0, 10); # Cross-sectional sample size nrep <- 100 # Biologic noise distribution dlims <- rbind( "HlyE_IgA" = c(min = 0, max = 0.5), "HlyE_IgG" = c(min = 0, max = 0.5) ) sim_data <- sim_pop_data_multi( curve_params = dmcmc, lambdas = lambdas, sample_sizes = nrep, age_range = lifespan, antigen_isos = antibodies, n_mcmc_samples = 0, renew_params = TRUE, add_noise = TRUE, noise_limits = dlims, format = "long", nclus = 10) sim_data
A caching wrapper around sim_pop_data_multi(), which dominates the runtime
of most simulation studies. The first call simulates and saves; later calls
with the same arguments load the saved result instead of re-simulating.
sim_pop_data_multi_cached( ..., cache_path = "cache/", cache_id = "sim_pop_data_multi", cache_rerun = FALSE, cache_verbose = TRUE, cache_extra = NULL )sim_pop_data_multi_cached( ..., cache_path = "cache/", cache_id = "sim_pop_data_multi", cache_rerun = FALSE, cache_verbose = TRUE, cache_extra = NULL )
... |
Arguments passed on to
|
cache_path |
a |
cache_id |
a |
cache_rerun |
a |
cache_verbose |
a |
cache_extra |
an object folded into the cache key alongside the
arguments. |
The cache is keyed on the arguments, so changing any of them (a new
lambdas vector, a different nclus) recomputes automatically, and
restoring the old arguments reuses the old result. Argument order and
formatting do not matter.
The cache is not keyed on the implementation. If sim_pop_data_multi()
or the functions it calls change, an existing cache stays valid as far as
this wrapper is concerned. Pass cache_rerun = TRUE once to refresh it, or
fold a version into the key with, for example,
cache_extra = utils::packageVersion("serocalculator"). That is
deliberately not the default: a development version bumps often, which
would discard the cache on nearly every commit.
a tibble::tibble(), as returned by sim_pop_data_multi().
antibodies <- c("HlyE_IgA", "HlyE_IgG") # Examples must not write into the user's working directory, so send the # cache to a temporary one. `cache_path` gains its trailing slash # automatically. cache_dir <- file.path(tempdir(), "serocalculator-example-cache") sim_df <- sim_pop_data_multi_cached( curve_params = typhoid_curves_nostrat_100, lambdas = c(0.05, 0.1), nclus = 2, sample_sizes = 50, age_range = c(0, 10), antigen_isos = antibodies, num_cores = 1, add_noise = TRUE, noise_limits = rbind( HlyE_IgA = c(min = 0, max = 0.5), HlyE_IgG = c(min = 0, max = 0.5) ), format = "long", cache_path = cache_dir ) nrow(sim_df) # Calling again with the same arguments loads the saved result instead of # re-simulating. sim_df2 <- sim_pop_data_multi_cached( curve_params = typhoid_curves_nostrat_100, lambdas = c(0.05, 0.1), nclus = 2, sample_sizes = 50, age_range = c(0, 10), antigen_isos = antibodies, num_cores = 1, add_noise = TRUE, noise_limits = rbind( HlyE_IgA = c(min = 0, max = 0.5), HlyE_IgG = c(min = 0, max = 0.5) ), format = "long", cache_path = cache_dir ) identical(sim_df, sim_df2)antibodies <- c("HlyE_IgA", "HlyE_IgG") # Examples must not write into the user's working directory, so send the # cache to a temporary one. `cache_path` gains its trailing slash # automatically. cache_dir <- file.path(tempdir(), "serocalculator-example-cache") sim_df <- sim_pop_data_multi_cached( curve_params = typhoid_curves_nostrat_100, lambdas = c(0.05, 0.1), nclus = 2, sample_sizes = 50, age_range = c(0, 10), antigen_isos = antibodies, num_cores = 1, add_noise = TRUE, noise_limits = rbind( HlyE_IgA = c(min = 0, max = 0.5), HlyE_IgG = c(min = 0, max = 0.5) ), format = "long", cache_path = cache_dir ) nrow(sim_df) # Calling again with the same arguments loads the saved result instead of # re-simulating. sim_df2 <- sim_pop_data_multi_cached( curve_params = typhoid_curves_nostrat_100, lambdas = c(0.05, 0.1), nclus = 2, sample_sizes = 50, age_range = c(0, 10), antigen_isos = antibodies, num_cores = 1, add_noise = TRUE, noise_limits = rbind( HlyE_IgA = c(min = 0, max = 0.5), HlyE_IgG = c(min = 0, max = 0.5) ), format = "long", cache_path = cache_dir ) identical(sim_df, sim_df2)
Strata metadata from an objectGeneric method for extracting strata metadata from objects.
See strata.default()
strata(x)strata(x)
x |
an object |
the strata metadata of x
This function is a summary() method for seroincidence objects.
When the model was fit with clustered data (using the cluster_var
parameter in est_seroincidence()), this function automatically computes
cluster-robust standard errors to account for within-cluster correlation.
For a multi-biomarker fit with no cluster_var, the reported SE
assumes independence across biomarkers — see cluster_var's
documentation in est_seroincidence() for how to correct for
within-person correlation instead.
## S3 method for class 'seroincidence' summary( object, coverage = 0.95, verbose = TRUE, small_sample = c("CR1", "none"), floor_to_standard = FALSE, debug_cluster = FALSE, ... )## S3 method for class 'seroincidence' summary( object, coverage = 0.95, verbose = TRUE, small_sample = c("CR1", "none"), floor_to_standard = FALSE, debug_cluster = FALSE, ... )
object |
a |
coverage |
desired confidence interval coverage probability |
verbose |
whether to produce verbose messaging |
small_sample |
small-sample correction for cluster-robust variance.
Use |
floor_to_standard |
whether to floor cluster-robust variance at the model-based variance. |
debug_cluster |
whether to print the cluster-robust variance decomposition when clustering is used. |
... |
unused |
a tibble::tibble() containing the following:
est.start: the starting guess for incidence rate
ageCat: the age category we are analyzing
incidence.rate: the estimated incidence rate, per person year
SE: standard error of the incidence rate estimate
CI.lwr: lower limit of confidence interval for incidence rate
CI.upr: upper limit of confidence interval for incidence rate
se_type: type of standard error used ("standard" or "cluster-robust")
coverage: coverage probability
log.lik:
log-likelihood of the data used in the call to est_seroincidence(),
evaluated at the maximum-likelihood estimate of lambda
(i.e., at incidence.rate)
iterations: the number of iterations used
antigen_isos: a list of antigen isotypes used in the analysis
nlm.convergence.code:
information about convergence of the likelihood maximization procedure
performed by nlm()
(see "Value" section of stats::nlm(), component code);
codes 3-5 indicate issues:
1: relative gradient is close to zero, current iterate is probably solution.
2: successive iterates within tolerance, current iterate is probably solution.
3: Last global step failed to locate a point lower than x.
Either x is an approximate local minimum of the function,
the function is too non-linear for this algorithm,
or stepmin in est_seroincidence()
(a.k.a., steptol in stats::nlm()) is too large.
4: iteration limit exceeded; increase iterlim.
5: maximum step size stepmax exceeded five consecutive times.
Either the function is unbounded below,
becomes asymptotic to a finite value from above in some direction,
or stepmax is too small.
library(dplyr) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est1 <- est_seroincidence( pop_data = xs_data, sr_params = curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA") ) summary(est1)library(dplyr) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk est1 <- est_seroincidence( pop_data = xs_data, sr_params = curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA") ) summary(est1)
"seroincidence.by" ObjectsCalculate seroincidence from output of the seroincidence calculator
est_seroincidence_by().
## S3 method for class 'seroincidence.by' summary( object, confidence_level = 0.95, show_deviance = TRUE, show_convergence = TRUE, verbose = FALSE, small_sample = c("CR1", "none"), floor_to_standard = FALSE, debug_cluster = FALSE, ... )## S3 method for class 'seroincidence.by' summary( object, confidence_level = 0.95, show_deviance = TRUE, show_convergence = TRUE, verbose = FALSE, small_sample = c("CR1", "none"), floor_to_standard = FALSE, debug_cluster = FALSE, ... )
object |
A dataframe containing output of |
confidence_level |
desired confidence interval coverage probability |
show_deviance |
Logical flag ( |
show_convergence |
Logical flag ( |
verbose |
a logical scalar indicating whether to print verbose messages to the console |
small_sample |
small-sample correction for cluster-robust variance.
Use |
floor_to_standard |
whether to floor cluster-robust variance at the model-based variance. |
debug_cluster |
whether to print the cluster-robust variance decomposition when clustering is used. |
... |
Additional arguments affecting the summary produced. |
A summary.seroincidence.by object, which is a tibble::tibble,
with the following columns:
incidence.rate maximum likelihood estimate of lambda (seroincidence)
CI.lwr lower confidence bound for lambda
CI.upr upper confidence bound for lambda
Deviance (included if show_deviance = TRUE)
Negative log likelihood (NLL) at estimated (maximum likelihood) lambda)
nlm.convergence.code (included if show_convergence = TRUE)
Convergence information returned by stats::nlm()
The object also has the following metadata
(accessible through base::attr()):
antigen_isos
Character vector with names of input antigen isotypes
used in est_seroincidence_by()
Strata Character with names of strata used in est_seroincidence_by()
library(dplyr) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk # estimate seroincidence est2 <- est_seroincidence_by( strata = c("catchment"), pop_data = xs_data, sr_params = curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), # num_cores = 8 # Allow for parallel processing to decrease run time ) # calculate summary statistics for the seroincidence object summary(est2)library(dplyr) xs_data <- sees_pop_data_pk_100 curve <- typhoid_curves_nostrat_100 |> filter(antigen_iso %in% c("HlyE_IgA", "HlyE_IgG")) noise <- example_noise_params_pk # estimate seroincidence est2 <- est_seroincidence_by( strata = c("catchment"), pop_data = xs_data, sr_params = curve, noise_params = noise, antigen_isos = c("HlyE_IgG", "HlyE_IgA"), # num_cores = 8 # Allow for parallel processing to decrease run time ) # calculate summary statistics for the seroincidence object summary(est2)
A subset of data from the SEES study, for examples and testing.
typhoid_curves_nostrat_100typhoid_curves_nostrat_100
typhoid_curves_nostrat_100A curve_params object (from as_sr_params()) with 500 rows and 7
columns:
which antigen and isotype are being measured (data is in long format)
MCMC iteration
Antibody concentration at t = 0 (start of active infection)
Antibody concentration at t = t1 (end of active infection)
Duration of active infection
Antibody decay rate coefficient
Antibody decay rate exponent parameter