diff --git a/DESCRIPTION b/DESCRIPTION index 6b5dd1e1..2069a351 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: serocalculator Title: Estimating Infection Rates from Serological Data -Version: 1.2.0.9022 +Version: 1.2.0.9023 Authors@R: c( person("Peter", "Teunis", , "p.teunis@emory.edu", role = c("aut", "cph"), comment = "Author of the method and original code."), diff --git a/NEWS.md b/NEWS.md index f352a8a7..ecb644c6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,8 @@ ## New features +* Fixed a bug in computing the antibody response curve when $r=1$ (#323) + * Added example datasets with documentation for examples and testing (#314) * Improved error messaging for `autoplot.pop_data()` (#234). diff --git a/R/ab0.R b/R/ab0.R index c661753d..b515524a 100644 --- a/R/ab0.R +++ b/R/ab0.R @@ -1,19 +1,26 @@ # uses r > 1 scale for shape -ab0 <- function( - t, - curve_params) { +ab0 <- function(t, curve_params) { y0 <- curve_params[["y0"]] y1 <- curve_params[["y1"]] t1 <- curve_params[["t1"]] alpha <- curve_params[["alpha"]] - shape <- curve_params[["r"]] + r <- curve_params[["r"]] beta <- bt(y0, y1, t1) yt <- 0 yt_phase_1 <- y0 * exp(beta * t) - yt_phase_2 <- (y1^(1 - shape) - (1 - shape) * alpha * (t - t1))^(1 / (1 - shape)) + if (r == 1) { + yt_phase_2 <- y1 * exp(-alpha * (t - t1)) + # see wolfram alpha result: https://bit.ly/3ZB69Yn + # this is a version the product-limit characterization of the + # exponential function + } else { + yt_phase_2 <- + (y1^(1 - r) - (1 - r) * alpha * (t - t1))^(1 / (1 - r)) + } + yt <- dplyr::if_else(t <= t1, yt_phase_1, yt_phase_2) return(yt) } diff --git a/tests/testthat/_snaps/ab0.md b/tests/testthat/_snaps/ab0.md new file mode 100644 index 00000000..a991286f --- /dev/null +++ b/tests/testthat/_snaps/ab0.md @@ -0,0 +1,16 @@ +# `ab0()` produces consistent results + + 9298.67465260527 + +--- + + 9990.00499833375 + +--- + + 9298.67465260527 + +--- + + 909.090909090912 + diff --git a/tests/testthat/_snaps/plot_curve_params_one_ab/curve-r1.svg b/tests/testthat/_snaps/plot_curve_params_one_ab/curve-r1.svg new file mode 100644 index 00000000..1e722303 --- /dev/null +++ b/tests/testthat/_snaps/plot_curve_params_one_ab/curve-r1.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +2500 +5000 +7500 +10000 + + + + + + + + + + + + +0 +5 +10 +15 +20 +25 +Days since fever onset +Antibody concentration +Antibody Response Curve + + diff --git a/tests/testthat/test-ab0.R b/tests/testthat/test-ab0.R new file mode 100644 index 00000000..ddd8cab1 --- /dev/null +++ b/tests/testthat/test-ab0.R @@ -0,0 +1,43 @@ +test_that("`ab0()` produces consistent results", { + params1 <- + data.frame( + y0 = 10, + y1 = 10^4, + t1 = 9.5, + alpha = 0.01, + r = 1, + antigen_iso = "test" + ) |> + as_curve_params() + + calc1 <- + ab0(curve_params = params1, t = 9.4) + + expect_snapshot_value(calc1, style = "deparse") + + calc2 <- + ab0(curve_params = params1, t = 9.6) + + expect_snapshot_value(calc2, style = "deparse") + + params2 <- + data.frame( + y0 = 10, + y1 = 10^4, + t1 = 9.5, + alpha = 0.01, + r = 2, + antigen_iso = "test" + ) |> + as_curve_params() + + calc3 <- + ab0(curve_params = params2, t = 9.4) + + expect_snapshot_value(calc3, style = "deparse") + + calc4 <- + ab0(curve_params = params2, t = 9.6) + + expect_snapshot_value(calc4, style = "deparse") +}) diff --git a/tests/testthat/test-plot_curve_params_one_ab.R b/tests/testthat/test-plot_curve_params_one_ab.R new file mode 100644 index 00000000..f631191d --- /dev/null +++ b/tests/testthat/test-plot_curve_params_one_ab.R @@ -0,0 +1,23 @@ +test_that("`plot_curve_params_one_ab()` produces consistent results", { + params <- + data.frame( + y0 = 10, + y1 = 10 ^ 4, + t1 = 9.5, + alpha = 0.01, + r = 1, + antigen_iso = "test" + ) |> + as_curve_params() + + + fig1 <- + params |> + plot_curve_params_one_ab(n_points = 10 ^ 5, + xlim = c(0, 25), + log_y = FALSE) + + fig1 |> + vdiffr::expect_doppelganger(title = "curve_r1") + +})