Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
e0491b2
renew.params case simulation
Kwan-Jenny Feb 5, 2025
cb9c575
renew_params case simulation
Kwan-Jenny Feb 5, 2025
72d03e1
Sample size 50's graph distribution of confidence intervals
Kwan-Jenny Feb 5, 2025
4587f49
in progress
d-morrison Feb 5, 2025
f006a32
synchronizing with other branch
d-morrison Feb 5, 2025
9de3698
Merge commit '4a2ffb35ff301a601d3954cdd03f25ef835521bf'
d-morrison Jun 27, 2025
a6438dc
decomp
d-morrison Jun 27, 2025
d97a897
more decomp
d-morrison Jun 27, 2025
4a1c4a8
cleanup
d-morrison Jun 27, 2025
239c3ea
decomp
d-morrison Jun 27, 2025
96cc7b7
cleanup
d-morrison Jun 27, 2025
2db9f54
more cleanup
d-morrison Jun 27, 2025
55ad6d1
generalize
d-morrison Jun 27, 2025
b86f14b
more cleanup
d-morrison Jun 27, 2025
ed4b734
trying to debug
d-morrison Jun 27, 2025
4fa37b6
fix
d-morrison Jun 27, 2025
5f5b176
more
d-morrison Jun 27, 2025
1d1f2b7
update snapshot
d-morrison Jun 27, 2025
14d7e75
update documentation
d-morrison Jun 27, 2025
220e672
finally got result
d-morrison Jun 27, 2025
510af79
snapshot
d-morrison Jun 27, 2025
d2da5bf
more cleanup
d-morrison Jun 27, 2025
00c2edb
more
d-morrison Jun 27, 2025
334f750
example
d-morrison Jun 27, 2025
9461594
more stuff
d-morrison Jun 27, 2025
17ffb89
add to simulation vignette
d-morrison Jun 27, 2025
78f754d
update documentation
d-morrison Jun 27, 2025
f8ff4d1
update wordlist
d-morrison Jun 27, 2025
360919a
news
d-morrison Jun 27, 2025
488944a
Increment version number to 1.3.0.9048
d-morrison Jun 27, 2025
359a2a0
update wordlist
d-morrison Jun 27, 2025
65fc1ed
fix
d-morrison Jun 27, 2025
6a899f3
dont export extra function
d-morrison Jun 27, 2025
1de6235
remove doc files
d-morrison Jun 27, 2025
34807a6
add Kwan as contributor
d-morrison Jun 27, 2025
7230165
move files to data-raw for now
d-morrison Jun 27, 2025
6ce5b5a
fix
d-morrison Jun 27, 2025
4e16bc1
just use two cores
d-morrison Jun 27, 2025
ca63dea
more fixes
d-morrison Jun 27, 2025
502f892
remove duplicates
d-morrison Jun 27, 2025
15db204
cleanup
d-morrison Jun 27, 2025
6446a81
fix
d-morrison Jun 27, 2025
0a68cf2
update vignette
d-morrison Jun 27, 2025
073eac3
update news
d-morrison Jun 27, 2025
41ae3a4
link to pr
d-morrison Jun 27, 2025
fd1096a
fixed?
d-morrison Jun 27, 2025
3922b22
more
d-morrison Jun 27, 2025
9066933
donttest
d-morrison Jun 27, 2025
2655ea2
update snapshot
d-morrison Jun 27, 2025
d91ca1d
cleanup
d-morrison Jun 27, 2025
d3a4351
lint
d-morrison Jun 27, 2025
18496c8
skip test on linux for now
d-morrison Jun 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
Type: Package
Package: serocalculator
Title: Estimating Infection Rates from Serological Data
Version: 1.3.0.9047
Version: 1.3.0.9048
Authors@R: c(
person("Peter", "Teunis", , "p.teunis@emory.edu", role = c("aut", "cph"),
comment = "Author of the method and original code."),
person("Kristina", "Lai", , "kwlai@ucdavis.edu", role = c("aut", "cre")),
person("Chris", "Orwa", role = "aut"),
person("Kwan Ho", "Lee", , "ksjlee@ucdavis.edu", role = "ctb"),
person("Kristen", "Aiemjoy", , "kaiemjoy@ucdavis.edu", role = "aut"),
person("Douglas Ezra", "Morrison", , "demorrison@ucdavis.edu", role = "aut")
)
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ S3method(autoplot,curve_params)
S3method(autoplot,pop_data)
S3method(autoplot,seroincidence)
S3method(autoplot,seroincidence.by)
S3method(autoplot,sim_results)
S3method(autoplot,summary.seroincidence.by)
S3method(print,seroincidence)
S3method(print,seroincidence.by)
Expand All @@ -14,6 +15,7 @@ S3method(strata,default)
S3method(summary,pop_data)
S3method(summary,seroincidence)
S3method(summary,seroincidence.by)
export(analyze_sims)
export(as_curve_params)
export(as_noise_params)
export(as_pop_data)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## New features

* Extended `sim_pop_data_multi()` to loop over multiple sample sizes (#444)
* Added new functions `analyze_sims()` and `autoplot.sim_results()` (#444)
* Rename `estimate_scr()` to `est_seroincidence_by()` (#439)
* Rename `estimate_scr()` to `est_seroincidence()` (#432)
* Rename argument `curve_params` to `sr_params` (#424)
Expand Down
69 changes: 69 additions & 0 deletions R/analyze_sims.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#' Analyze simulation results
#'
#' @param data a [tibble::tbl_df] with columns:
#' * `lambda.sim`,
#' * `incidence.rate`,
#' * `SE`,
#' * `CI.lwr`,
#' * `CI.upr`
#' for example, as produced by [summary.seroincidence.by()] with
#' `lambda.sim` as a stratifying variable
#'
#' @returns a `sim_results` object (extends [tibble::tbl_df])
#' @export
#'
#' @example inst/examples/exm-analyze_sims.R
#'
analyze_sims <- function(
data) {

to_return <-
data |>
split(
f = ~ sample_size + lambda.sim
) |>
lapply(FUN = analyze_sims_one_stratum) |>
bind_rows()

class(to_return) <- union("sim_results", class(to_return))

return(to_return)
}

analyze_sims_one_stratum <- function(
data,
true_lambda = data$lambda.sim,
sample_size = data$sample_size) {

# Filter out rows where CI.lwr or CI.upr is Inf or NaN
data <- data |>
filter(is.finite(.data$CI.lwr) & is.finite(.data$CI.upr))

# Compute Bias
bias <- mean(data$incidence.rate - true_lambda, na.rm = TRUE)

# Standard Error (Mean of reported standard errors)
standard_error <- mean(data$SE, na.rm = TRUE)

# RMSE (Root Mean Square Error)
rmse <- mean((data$incidence.rate - true_lambda)^2, na.rm = TRUE) |> sqrt()

# Confidence Interval Width (Mean of Upper - Lower bounds, without Inf values)
ci_width <- mean(data$CI.upr - data$CI.lwr, na.rm = TRUE)

coverage_prop <-

Check notice on line 54 in R/analyze_sims.R

View check run for this annotation

codefactor.io / CodeFactor

R/analyze_sims.R#L54

Use implicit return behavior; explicit return() is not needed. (return_linter)
mean(data$CI.lwr <= true_lambda & data$CI.upr >= true_lambda, na.rm = TRUE)

to_return <- tibble(
lambda.sim = mean(true_lambda),
sample_size = mean(sample_size),
Bias = bias,
Mean_Est_SE = standard_error,
Empirical_SE = stats::sd(data$incidence.rate, na.rm = TRUE),
RMSE = rmse,
Mean_CI_Width = ci_width,
CI_Coverage = coverage_prop
)
# Return computed statistics as a list
return(to_return)
}
27 changes: 27 additions & 0 deletions R/autoplot.sim_results.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#' Plot simulation results
#' `autoplot()` method for `sim_results` objects
#'
#' @param object a `sim_results` object (from [analyze_sims()])
#' @param statistic which column of `object` should be the y-axis?
#' @param ... unused
#' @returns a [ggplot2::ggplot]
#' @export
#'
#' @example inst/examples/exm-autoplot.sim_results.R
autoplot.sim_results <- function(
object,
statistic = "Empirical_SE",
...) {
object |>
dplyr::mutate(lambda.sim = factor(.data$lambda.sim)) |>
ggplot2::ggplot() +
ggplot2::aes(
x = .data$sample_size,
group = .data$lambda.sim,
col = .data$lambda.sim,
y = .data[[statistic]]
) +
ggplot2::geom_point() +
ggplot2::geom_line() +
ggplot2::theme(legend.position = "bottom")
}
3 changes: 2 additions & 1 deletion R/sim_pop_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ sim_pop_data <- function(

predpar <-
curve_params |>
filter(.data$antigen_iso %in% antigen_isos) |>
dplyr::filter(.data$antigen_iso %in% antigen_isos) |>
droplevels() |>
prep_curve_params_for_array() |>
df_to_array(dim_var_names = c("antigen_iso", "parameter"))
Expand Down Expand Up @@ -196,6 +196,7 @@ sim_pop_data <- function(
#' consistent API.
#' @keywords internal
#' @export

sim.cs <- function( # nolint: object_name_linter
n.smpl, # nolint: object_name_linter
age.rng, # nolint: object_name_linter
Expand Down
81 changes: 38 additions & 43 deletions R/sim_pop_data_multi.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,18 @@
#' @param nclus number of clusters
#' @param rng_seed starting seed for random number generator,
#' passed to [rngtools::RNGseq()]
#' @param lambdas #incidence rate, in events/person*year
#' @param sample_sizes sample sizes to simulate
#' @param lambdas incidence rate, in events/person*year
#' @param num_cores number of cores to use for parallel computations
#' @param verbose whether to report verbose information
#' @param ... arguments passed to [sim.cs()]
#' @inheritDotParams sim_pop_data
#' @return a [tibble::tibble()]
#' @export
#' @examples
#' # 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_pop_data_multi(
#' curve_params = dmcmc,
#' lambdas = lambdas,
#' n_samples = nrep,
#' age_range = lifespan,
#' antigen_isos = antibodies,
#' n_mcmc_samples = 0,
#' renew_params = TRUE,
#' add_noise = TRUE,
#' noise_limits = dlims,
#' format = "long",
#' nclus = 10)
#'
#' @example inst/examples/exm-sim_pop_data_multi.R
sim_pop_data_multi <- function(
nclus = 10,
sample_sizes = 100,
lambdas = c(.05, .1, .15, .2, .3),
num_cores = max(1, parallel::detectCores() - 1),
rng_seed = 1234,
Expand Down Expand Up @@ -81,31 +46,61 @@
}

doParallel::registerDoParallel(cores = num_cores)

n_sample_sizes <- length(sample_sizes)

Check warning on line 49 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L49

Added line #L49 was not covered by tests
n_lambda <- length(lambdas)

# trying to reproduce results using parallel
rng <- rngtools::RNGseq(n_lambda * nclus, rng_seed)
rng <- rngtools::RNGseq(n_sample_sizes * n_lambda * nclus, rng_seed)

Check warning on line 53 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L53

Added line #L53 was not covered by tests

dimnames1 <-
list(
"iteration" = 1:nclus,
"lambda" = lambdas,
"sample size" = sample_sizes
)

Check warning on line 60 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L55-L60

Added lines #L55 - L60 were not covered by tests

dims1 <-
sapply(FUN = length, dimnames1)

Check warning on line 63 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L62-L63

Added lines #L62 - L63 were not covered by tests

rng <- rng |>
array(
dimnames = dimnames1,
dim = dims1
)

Check warning on line 69 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L65-L69

Added lines #L65 - L69 were not covered by tests
i <- NA
j <- 1

Check warning on line 71 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L71

Added line #L71 was not covered by tests
r <- NA

sim_df <-
foreach::foreach(
.combine = bind_rows,
j = seq_along(sample_sizes)

Check warning on line 77 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L75-L77

Added lines #L75 - L77 were not covered by tests

) %:%

Check warning on line 79 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L79

Added line #L79 was not covered by tests
foreach::foreach(
.combine = bind_rows,
i = seq_along(lambdas)

) %:%
foreach::foreach(
.combine = bind_rows,
n = 1:nclus,
r = rng[(i - 1) * nclus + 1:nclus]
r = rng[1:nclus, i, j]

Check warning on line 88 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L88

Added line #L88 was not covered by tests
) %dopar% {
l <- lambdas[i]
ns <- sample_sizes[j]

Check warning on line 91 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L91

Added line #L91 was not covered by tests
rngtools::setRNG(r)
sim_pop_data(
lambda = l,
n_samples = ns,

Check warning on line 95 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L95

Added line #L95 was not covered by tests
...
) |>
mutate(lambda.sim = l, cluster = n)
mutate(
lambda.sim = l,
sample_size = ns,
cluster = n
) |>
structure(r = r)

Check warning on line 103 in R/sim_pop_data_multi.R

View check run for this annotation

Codecov / codecov/patch

R/sim_pop_data_multi.R#L98-L103

Added lines #L98 - L103 were not covered by tests
}
doParallel::stopImplicitCluster()
sim_df <- sim_df |> set_biomarker_var(biomarker = "antigen_iso")
Expand Down
3 changes: 2 additions & 1 deletion data-raw/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
test_sim_020425_2.pdf
*.pdf
*.rmarkdown
22 changes: 22 additions & 0 deletions data-raw/coverage-CI.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Compute Coverage and its Confidence Interval
compute_coverage_ci <- function(coverage_count, total_count) {
test_result <- stats::binom.test(
coverage_count,
total_count,
conf.level = 0.95
)
# 95% CI
coverage_proportion <- coverage_count / total_count
ci_lower <- test_result$conf.int[1]
ci_upper <- test_result$conf.int[2]

return(

Check notice on line 13 in data-raw/coverage-CI.R

View check run for this annotation

codefactor.io / CodeFactor

data-raw/coverage-CI.R#L13

Use implicit return behavior; explicit return() is not needed. (return_linter)
list(
coverage = coverage_proportion,
ci_lower = ci_lower,
ci_upper = ci_upper
)
)
}

# coverage_result <- compute_coverage_ci(coverage_count, nrow(data)) # nolint: object_usage_linter
42 changes: 42 additions & 0 deletions data-raw/generate_sim_table.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#' Generate table of simulation results
#'
#' @param results_list output from [simulate_seroincidence()]
#' @param sample_size sample size of simulated data sets
#' @noRd
#' @returns a [tibble::tbl_df]
generate_sim_table <- function(
results_list,
sample_size = results_list |> attr("sample_size")) {
# Initialize an empty list to store the results
summary_results <- list()

# Loop through each of the 100 results and extract the required columns
for (i in 1:300) {
# Extract the summary for each result
result_summary <- summary(results_list[[i]]$est1)

# Select the required columns
extracted_columns <- result_summary %>%

Check warning on line 19 in data-raw/generate_sim_table.R

View workflow job for this annotation

GitHub Actions / lint-changed-files

file=data-raw/generate_sim_table.R,line=19,col=41,[pipe_consistency_linter] Use the |> pipe operator instead of the %>% pipe operator.
select(incidence.rate, SE, CI.lwr, CI.upr)

Check warning on line 20 in data-raw/generate_sim_table.R

View workflow job for this annotation

GitHub Actions / lint-changed-files

file=data-raw/generate_sim_table.R,line=20,col=42,[object_usage_linter] no visible binding for global variable 'CI.upr'

Check warning on line 20 in data-raw/generate_sim_table.R

View workflow job for this annotation

GitHub Actions / lint-changed-files

file=data-raw/generate_sim_table.R,line=20,col=34,[object_usage_linter] no visible binding for global variable 'CI.lwr'

Check warning on line 20 in data-raw/generate_sim_table.R

View workflow job for this annotation

GitHub Actions / lint-changed-files

file=data-raw/generate_sim_table.R,line=20,col=30,[object_usage_linter] no visible binding for global variable 'SE'

Check warning on line 20 in data-raw/generate_sim_table.R

View workflow job for this annotation

GitHub Actions / lint-changed-files

file=data-raw/generate_sim_table.R,line=20,col=14,[object_usage_linter] no visible binding for global variable 'incidence.rate'

# Add a column for the index (optional, for tracking)
extracted_columns <- extracted_columns %>%

Check warning on line 23 in data-raw/generate_sim_table.R

View workflow job for this annotation

GitHub Actions / lint-changed-files

file=data-raw/generate_sim_table.R,line=23,col=44,[pipe_consistency_linter] Use the |> pipe operator instead of the %>% pipe operator.
mutate(index = i)

# Append to the list
summary_results[[i]] <- extracted_columns
}

# Combine all results into a single data frame
final_table <- bind_rows(summary_results) %>%

Check warning on line 31 in data-raw/generate_sim_table.R

View workflow job for this annotation

GitHub Actions / lint-changed-files

file=data-raw/generate_sim_table.R,line=31,col=45,[pipe_consistency_linter] Use the |> pipe operator instead of the %>% pipe operator.
mutate(sample_size = sample_size) # Add sample size column for clarity

final_table <-
final_table |>
structure(
sample_size = sample_size,
true_lambda = results_list |> attr("lambda_true")
)

return(final_table)

Check notice on line 41 in data-raw/generate_sim_table.R

View check run for this annotation

codefactor.io / CodeFactor

data-raw/generate_sim_table.R#L41

Use implicit return behavior; explicit return() is not needed. (return_linter)
}
Loading
Loading