diff --git a/NAMESPACE b/NAMESPACE
index d7dad8b..d5b46ca 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -3,7 +3,7 @@
export(add_exposure_data)
export(biokinetics)
export(biokinetics_priors)
-export(convert_log_scale_inverse)
+export(convert_log2_scale_inverse)
importFrom(R6,R6Class)
importFrom(data.table,":=")
importFrom(data.table,.BY)
diff --git a/R/biokinetics.R b/R/biokinetics.R
index 16fdaa8..82295db 100644
--- a/R/biokinetics.R
+++ b/R/biokinetics.R
@@ -212,6 +212,7 @@ biokinetics <- R6::R6Class(
#' @param priors Object of type \link[epikinetics]{biokinetics_priors}. Default biokinetics_priors().
#' @param covariate_formula Formula specifying linear regression model. Note all variables in the formula
#' will be treated as categorical variables. Default ~0.
+ #' @param preds_sd Standard deviation of predictor coefficients. Default 0.25.
#' @param scale One of "log" or "natural". Default "natural". Is provided data on a log or a natural scale? If on a natural scale it
#' will be converted to a log scale for model fitting.
initialize = function(priors = biokinetics_priors(),
@@ -246,7 +247,7 @@ biokinetics <- R6::R6Class(
validate_formula_vars(private$all_formula_vars, private$data)
logger::log_info("Preparing data for stan")
if (scale == "natural") {
- private$data <- convert_log_scale(private$data, "value")
+ private$data <- convert_log2_scale(private$data, "value")
}
private$data[, `:=`(obs_id = seq_len(.N),
t_since_last_exp = as.integer(day - last_exp_day, units = "days"))]
@@ -269,6 +270,8 @@ biokinetics <- R6::R6Class(
get_stan_data = function() {
private$stan_input_data
},
+ #' @description View the mapping of human readable covariate names to the model variable p.
+ #' @return A data.table mapping the model variable p to human readable covariates.
get_covariate_lookup_table = function() {
private$covariate_lookup_table
},
@@ -390,10 +393,10 @@ biokinetics <- R6::R6Class(
}
if (summarise) {
- dt_out <- convert_log_scale_inverse(
+ dt_out <- convert_log2_scale_inverse(
dt_out, vars_to_transform = c("me", "lo", "hi"))
} else {
- dt_out <- convert_log_scale_inverse(
+ dt_out <- convert_log2_scale_inverse(
dt_out, vars_to_transform = "mu")
}
dt_out
@@ -430,7 +433,7 @@ biokinetics <- R6::R6Class(
dt_peak_switch <- private$recover_covariate_names(dt_peak_switch)
if (private$scale == "natural") {
- dt_peak_switch <- convert_log_scale_inverse(
+ dt_peak_switch <- convert_log2_scale_inverse(
dt_peak_switch, vars_to_transform = c("mu_0", "mu_p", "mu_s"))
}
@@ -491,11 +494,11 @@ biokinetics <- R6::R6Class(
# Running the C++ code to simulate trajectories for each parameter sample
# for each individual
logger::log_info("Simulating individual trajectories")
- dt_params_ind_traj <- data.table::setDT(biokinetics_simulate_trajectories(dt_params_ind))
+ dt_params_ind_traj <- biokinetics_simulate_trajectories(dt_params_ind)
if (private$scale == "natural") {
- dt_params_ind_traj <- convert_log_scale_inverse_cpp(
- dt_params_ind_traj, vars_to_transform = "mu")
+ dt_params_ind_traj <- data.table::setDT(convert_log2_scale_inverse_cpp(
+ dt_params_ind_traj, vars_to_transform = "mu"))
}
# convert numeric pid to original pid
diff --git a/R/cpp11.R b/R/cpp11.R
index 2317c1c..5141cfe 100644
--- a/R/cpp11.R
+++ b/R/cpp11.R
@@ -1,7 +1,7 @@
# Generated by cpp11: do not edit by hand
-convert_log_scale_inverse_cpp <- function(dt, vars_to_transform) {
- .Call(`_epikinetics_convert_log_scale_inverse_cpp`, dt, vars_to_transform)
+convert_log2_scale_inverse_cpp <- function(dt, vars_to_transform) {
+ .Call(`_epikinetics_convert_log2_scale_inverse_cpp`, dt, vars_to_transform)
}
simulate_trajectories_cpp <- function(person_params) {
diff --git a/R/utils.R b/R/utils.R
index 576cfc2..1ee1a2e 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -1,4 +1,4 @@
-convert_log_scale <- function(
+convert_log2_scale <- function(
dt_in, vars_to_transform = "titre",
simplify_limits = TRUE) {
@@ -14,14 +14,14 @@ convert_log_scale <- function(
#' @title Invert base 2 log scale conversion
#'
-#' @description User provided data is converted to a base 2 log scale before model fitting. This
-#' function reverses that transformation. This function does not modify the provided data.table in-place,
-#' but returns a transformed copy.
+#' @description Natural scale data is converted to a base 2 log scale before model fitting. This
+#' function reverses that transformation and may be useful if working directly with fitted parameters.
+#' This function does not modify the provided data.table in-place, but returns a transformed copy.
#' @return A data.table, identical to the input data but with specified columns transformed.
#' @param dt_in data.table containing data to be transformed from base 2 log to natural scale.
#' @param vars_to_transform Names of columns to apply the transformation to.
#' @export
-convert_log_scale_inverse <- function(dt_in, vars_to_transform) {
+convert_log2_scale_inverse <- function(dt_in, vars_to_transform) {
dt_out <- data.table::copy(dt_in)
for (var in vars_to_transform) {
# Reverse the log2 transformation and multiplication by 5.
diff --git a/man/biokinetics.Rd b/man/biokinetics.Rd
index 1de7305..5481497 100644
--- a/man/biokinetics.Rd
+++ b/man/biokinetics.Rd
@@ -50,6 +50,8 @@ for required columns: \code{vignette("data", package = "epikinetics")}.}
\item{\code{covariate_formula}}{Formula specifying linear regression model. Note all variables in the formula
will be treated as categorical variables. Default ~0.}
+\item{\code{preds_sd}}{Standard deviation of predictor coefficients. Default 0.25.}
+
\item{\code{scale}}{One of "log" or "natural". Default "natural". Is provided data on a log or a natural scale? If on a natural scale it
will be converted to a log scale for model fitting.}
}
@@ -76,10 +78,14 @@ A list of arguments that will be passed to the stan model.
\if{html}{\out{}}
\if{latex}{\out{\hypertarget{method-biokinetics-get_covariate_lookup_table}{}}}
\subsection{Method \code{get_covariate_lookup_table()}}{
+View the mapping of human readable covariate names to the model variable p.
\subsection{Usage}{
\if{html}{\out{
}}\preformatted{biokinetics$get_covariate_lookup_table()}\if{html}{\out{
}}
}
+\subsection{Returns}{
+A data.table mapping the model variable p to human readable covariates.
+}
}
\if{html}{\out{
}}
\if{html}{\out{}}
diff --git a/man/convert_log_scale_inverse.Rd b/man/convert_log2_scale_inverse.Rd
similarity index 57%
rename from man/convert_log_scale_inverse.Rd
rename to man/convert_log2_scale_inverse.Rd
index d84c93a..f5409a2 100644
--- a/man/convert_log_scale_inverse.Rd
+++ b/man/convert_log2_scale_inverse.Rd
@@ -1,10 +1,10 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/utils.R
-\name{convert_log_scale_inverse}
-\alias{convert_log_scale_inverse}
+\name{convert_log2_scale_inverse}
+\alias{convert_log2_scale_inverse}
\title{Invert base 2 log scale conversion}
\usage{
-convert_log_scale_inverse(dt_in, vars_to_transform)
+convert_log2_scale_inverse(dt_in, vars_to_transform)
}
\arguments{
\item{dt_in}{data.table containing data to be transformed from base 2 log to natural scale.}
@@ -15,7 +15,7 @@ convert_log_scale_inverse(dt_in, vars_to_transform)
A data.table, identical to the input data but with specified columns transformed.
}
\description{
-User provided data is converted to a base 2 log scale before model fitting. This
-function reverses that transformation. This function does not modify the provided data.table in-place,
-but returns a transformed copy.
+Natural scale data is converted to a base 2 log scale before model fitting. This
+function reverses that transformation and may be useful if working directly with fitted parameters.
+This function does not modify the provided data.table in-place, but returns a transformed copy.
}
diff --git a/src/convert_log_scale_inverse.cpp b/src/convert_log_scale_inverse.cpp
index 2abe7ba..77524e6 100644
--- a/src/convert_log_scale_inverse.cpp
+++ b/src/convert_log_scale_inverse.cpp
@@ -3,7 +3,7 @@
using namespace cpp11;
[[cpp11::register]]
-cpp11::data_frame convert_log_scale_inverse_cpp(cpp11::writable::list dt,
+cpp11::data_frame convert_log2_scale_inverse_cpp(cpp11::writable::list dt,
cpp11::strings vars_to_transform) {
for (int i = 0; i < vars_to_transform.size(); i++) {
diff --git a/src/cpp11.cpp b/src/cpp11.cpp
index caad6d2..18c707b 100644
--- a/src/cpp11.cpp
+++ b/src/cpp11.cpp
@@ -6,10 +6,10 @@
#include
// convert_log_scale_inverse.cpp
-cpp11::data_frame convert_log_scale_inverse_cpp(cpp11::writable::list dt, cpp11::strings vars_to_transform);
-extern "C" SEXP _epikinetics_convert_log_scale_inverse_cpp(SEXP dt, SEXP vars_to_transform) {
+cpp11::data_frame convert_log2_scale_inverse_cpp(cpp11::writable::list dt, cpp11::strings vars_to_transform);
+extern "C" SEXP _epikinetics_convert_log2_scale_inverse_cpp(SEXP dt, SEXP vars_to_transform) {
BEGIN_CPP11
- return cpp11::as_sexp(convert_log_scale_inverse_cpp(cpp11::as_cpp>(dt), cpp11::as_cpp>(vars_to_transform)));
+ return cpp11::as_sexp(convert_log2_scale_inverse_cpp(cpp11::as_cpp>(dt), cpp11::as_cpp>(vars_to_transform)));
END_CPP11
}
// simulate_trajectories.cpp
@@ -22,8 +22,8 @@ extern "C" SEXP _epikinetics_simulate_trajectories_cpp(SEXP person_params) {
extern "C" {
static const R_CallMethodDef CallEntries[] = {
- {"_epikinetics_convert_log_scale_inverse_cpp", (DL_FUNC) &_epikinetics_convert_log_scale_inverse_cpp, 2},
- {"_epikinetics_simulate_trajectories_cpp", (DL_FUNC) &_epikinetics_simulate_trajectories_cpp, 1},
+ {"_epikinetics_convert_log2_scale_inverse_cpp", (DL_FUNC) &_epikinetics_convert_log2_scale_inverse_cpp, 2},
+ {"_epikinetics_simulate_trajectories_cpp", (DL_FUNC) &_epikinetics_simulate_trajectories_cpp, 1},
{NULL, NULL, 0}
};
}
diff --git a/tests/testthat/test-convert-log-scale.R b/tests/testthat/test-convert-log-scale.R
index b6c378b..26715fb 100644
--- a/tests/testthat/test-convert-log-scale.R
+++ b/tests/testthat/test-convert-log-scale.R
@@ -1,14 +1,14 @@
test_that("Can convert to and from log scale in R", {
inputs <- data.table::fread(test_path("testdata", "testdata.csv"))
- log_inputs <- convert_log_scale(inputs, "me", simplify_limits = FALSE)
- unlog_inputs <- convert_log_scale_inverse(log_inputs, "me")
+ log_inputs <- convert_log2_scale(inputs, "me", simplify_limits = FALSE)
+ unlog_inputs <- convert_log2_scale_inverse(log_inputs, "me")
expect_equal(inputs, unlog_inputs)
})
test_that("Can convert from log scale in R", {
inputs <- data.table::fread(test_path("testdata", "testdata.csv"))
- res <- convert_log_scale_inverse(
+ res <- convert_log2_scale_inverse(
inputs, vars_to_transform = c("me", "lo"))
expect_equal(res$me, 5 * 2^inputs$me)
@@ -19,7 +19,7 @@ test_that("Can convert from log scale in R", {
test_that("Can convert from log scale in Cpp", {
inputs <- data.table::fread(test_path("testdata", "testdata.csv"))
- rescpp <- convert_log_scale_inverse_cpp(
+ rescpp <- convert_log2_scale_inverse_cpp(
inputs, vars_to_transform = c("me", "lo"))
expect_equal(rescpp$me, 5 * 2^(inputs$me))
diff --git a/tests/testthat/test-data.R b/tests/testthat/test-data.R
index 233f1cb..a9aa1a1 100644
--- a/tests/testthat/test-data.R
+++ b/tests/testthat/test-data.R
@@ -52,7 +52,7 @@ test_that("Natural scale data is converted to log scale for stan", {
dat <- data.table::fread(system.file("delta_full.rds", package = "epikinetics"))
mod <- biokinetics$new(data = dat)
stan_data <- mod$get_stan_data()
- expect_equivalent(stan_data$value, convert_log_scale(dat, "value")$value)
+ expect_equivalent(stan_data$value, convert_log2_scale(dat, "value")$value)
})
test_that("Log scale data is passed directly to stan", {
diff --git a/tests/testthat/test-simulate-individual-trajectories.R b/tests/testthat/test-simulate-individual-trajectories.R
index dec0046..507b877 100644
--- a/tests/testthat/test-simulate-individual-trajectories.R
+++ b/tests/testthat/test-simulate-individual-trajectories.R
@@ -81,3 +81,19 @@ test_that("Exposure dates are brought forward by time_shift days", {
expect_equal(trajectories$mu, trajectories_shifted$mu)
expect_true(all(as.numeric(difftime(trajectories$exposure_date, trajectories_shifted$exposure_date, units = "days")) == 75))
})
+
+test_that("Natural scale data is returned on natural scale", {
+ mod <- biokinetics$new(file_path = system.file("delta_full.rds", package = "epikinetics"),
+ covariate_formula = ~0 + infection_history, scale = "natural")
+ mod$fit()
+ trajectories <- mod$simulate_individual_trajectories(summarise = TRUE, n_draws = 10)
+ expect_false(all(trajectories$me < 10))
+})
+
+test_that("Log scale data is returned on log scale", {
+ mod <- biokinetics$new(file_path = system.file("delta_full.rds", package = "epikinetics"),
+ covariate_formula = ~0 + infection_history, scale = "log")
+ mod$fit()
+ trajectories <- mod$simulate_individual_trajectories(summarise = TRUE, n_draws = 10)
+ expect_true(all(trajectories$me < 10))
+})
diff --git a/tests/testthat/test-simulate-population-trajectories.R b/tests/testthat/test-simulate-population-trajectories.R
index 246d392..73b7092 100644
--- a/tests/testthat/test-simulate-population-trajectories.R
+++ b/tests/testthat/test-simulate-population-trajectories.R
@@ -45,3 +45,19 @@ test_that("Only times up to t_max are returned", {
trajectories <- mod$simulate_population_trajectories(summarise = TRUE, t_max = 10)
expect_true(all(trajectories$t <= 10))
})
+
+test_that("Natural scale data is returned on natural scale", {
+ mod <- biokinetics$new(file_path = system.file("delta_full.rds", package = "epikinetics"),
+ covariate_formula = ~0 + infection_history, scale = "natural")
+ mod$fit()
+ trajectories <- mod$simulate_population_trajectories(summarise = TRUE, t_max = 10)
+ expect_false(all(trajectories$me < 10))
+})
+
+test_that("Log scale data is returned on log scale", {
+ mod <- biokinetics$new(file_path = system.file("delta_full.rds", package = "epikinetics"),
+ covariate_formula = ~0 + infection_history, scale = "log")
+ mod$fit()
+ trajectories <- mod$simulate_population_trajectories(summarise = TRUE, t_max = 10)
+ expect_true(all(trajectories$me < 10))
+})