From fb23e44a8ccf083d69543fb8db771fab0dda6633 Mon Sep 17 00:00:00 2001 From: gowerc Date: Fri, 28 Jun 2024 17:10:05 +0100 Subject: [PATCH 1/3] initial commit --- R/LongitudinalGSF.R | 29 +++++++-------- R/SimLongitudinalGSF.R | 47 +++++++++++++----------- inst/stan/lm-gsf/model.stan | 18 ++++++--- inst/stan/lm-gsf/quantities.stan | 2 +- man/LongitudinalGSF-class.Rd | 11 +++--- man/SimLongitudinalGSF-class.Rd | 22 +++++------ tests/testthat/_snaps/JointModel.md | 6 +-- tests/testthat/_snaps/LongitudinalGSF.md | 12 +++--- tests/testthat/test-Grid.R | 20 +++++----- tests/testthat/test-GridPrediction.R | 12 +++--- tests/testthat/test-LongitudinalGSF.R | 14 +++---- tests/testthat/test-SimJointData.R | 4 +- tests/testthat/test-SimLongitudinalGSF.R | 6 +-- tests/testthat/test-initialValues.R | 2 +- vignettes/extending-jmpost.Rmd | 19 ++++++---- vignettes/statistical-specification.Rmd | 6 ++- 16 files changed, 123 insertions(+), 107 deletions(-) diff --git a/R/LongitudinalGSF.R b/R/LongitudinalGSF.R index ced7fa0af..d8a7d47e9 100755 --- a/R/LongitudinalGSF.R +++ b/R/LongitudinalGSF.R @@ -31,16 +31,16 @@ NULL #' @param mu_bsld (`Prior`)\cr for the mean baseline value `mu_bsld`. #' @param mu_ks (`Prior`)\cr for the mean shrinkage rate `mu_ks`. #' @param mu_kg (`Prior`)\cr for the mean growth rate `mu_kg`. +#' @param mu_phi (`Prior`)\cr for the mean proportion of cells affected by the treatment `mu_phi`. #' #' @param omega_bsld (`Prior`)\cr for the baseline value standard deviation `omega_bsld`. #' @param omega_ks (`Prior`)\cr for the shrinkage rate standard deviation `omega_ks`. #' @param omega_kg (`Prior`)\cr for the growth rate standard deviation `omega_kg`. +#' @param omega_phi (`Prior`)\cr for the proportion of cells affected by the +#' treatment standard deviation `omega_phi`. #' #' @param sigma (`Prior`)\cr for the variance of the longitudinal values `sigma`. #' -#' @param a_phi (`Prior`)\cr for the alpha parameter for the fraction of cells that respond to treatment. -#' @param b_phi (`Prior`)\cr for the beta parameter for the fraction of cells that respond to treatment. -#' #' @param centred (`logical`)\cr whether to use the centred parameterization. #' #' @export @@ -49,13 +49,12 @@ LongitudinalGSF <- function( mu_bsld = prior_normal(log(60), 1), mu_ks = prior_normal(log(0.5), 1), mu_kg = prior_normal(log(0.3), 1), + mu_phi = prior_normal(qlogis(0.5), 1), omega_bsld = prior_lognormal(log(0.2), 1), omega_ks = prior_lognormal(log(0.2), 1), omega_kg = prior_lognormal(log(0.2), 1), - - a_phi = prior_lognormal(log(5), 1), - b_phi = prior_lognormal(log(5), 1), + omega_phi = prior_lognormal(log(0.2), 1), sigma = prior_lognormal(log(0.1), 1), @@ -71,18 +70,12 @@ LongitudinalGSF <- function( Parameter(name = "lm_gsf_mu_bsld", prior = mu_bsld, size = "n_studies"), Parameter(name = "lm_gsf_mu_ks", prior = mu_ks, size = "n_arms"), Parameter(name = "lm_gsf_mu_kg", prior = mu_kg, size = "n_arms"), + Parameter(name = "lm_gsf_mu_phi", prior = mu_phi, size = "n_arms"), Parameter(name = "lm_gsf_omega_bsld", prior = omega_bsld, size = 1), Parameter(name = "lm_gsf_omega_ks", prior = omega_ks, size = 1), Parameter(name = "lm_gsf_omega_kg", prior = omega_kg, size = 1), - - Parameter(name = "lm_gsf_a_phi", prior = a_phi, size = "n_arms"), - Parameter(name = "lm_gsf_b_phi", prior = b_phi, size = "n_arms"), - Parameter( - name = "lm_gsf_psi_phi", - prior = prior_init_only(prior_beta(a_phi@init, b_phi@init)), - size = "n_subjects" - ), + Parameter(name = "lm_gsf_omega_phi", prior = omega_phi, size = 1), Parameter(name = "lm_gsf_sigma", prior = sigma, size = 1) ) @@ -104,13 +97,19 @@ LongitudinalGSF <- function( name = "lm_gsf_psi_kg", prior = prior_init_only(prior_lognormal(mu_kg@init, omega_kg@init)), size = "n_subjects" + ), + Parameter( + name = "lm_gsf_psi_phi_logit", + prior = prior_init_only(prior_normal(mu_phi@init, omega_phi@init)), + size = "n_subjects" ) ) } else { list( Parameter(name = "lm_gsf_eta_tilde_bsld", prior = prior_std_normal(), size = "n_subjects"), Parameter(name = "lm_gsf_eta_tilde_ks", prior = prior_std_normal(), size = "n_subjects"), - Parameter(name = "lm_gsf_eta_tilde_kg", prior = prior_std_normal(), size = "n_subjects") + Parameter(name = "lm_gsf_eta_tilde_kg", prior = prior_std_normal(), size = "n_subjects"), + Parameter(name = "lm_gsf_eta_tilde_phi", prior = prior_std_normal(), size = "n_subjects") ) } parameters <- append(parameters, parameters_extra) diff --git a/R/SimLongitudinalGSF.R b/R/SimLongitudinalGSF.R index c5ad6e122..13224cac5 100644 --- a/R/SimLongitudinalGSF.R +++ b/R/SimLongitudinalGSF.R @@ -8,14 +8,14 @@ NULL #' #' @param times (`numeric`)\cr the times to generate observations at. #' @param sigma (`number`)\cr the variance of the longitudinal values. -#' @param mu_s (`numeric`)\cr the mean shrinkage rates for the two treatment arms. -#' @param mu_g (`numeric`)\cr the mean growth rates for the two treatment arms. -#' @param mu_b (`numeric`)\cr the mean baseline values for the two treatment arms. +#' @param mu_s (`numeric`)\cr the mean shrinkage rates. +#' @param mu_g (`numeric`)\cr the mean growth rates. +#' @param mu_b (`numeric`)\cr the mean baseline values. +#' @param mu_phi (`numeric`)\cr the mean proportion of cells affected by the treatment #' @param omega_b (`number`)\cr the baseline value standard deviation. #' @param omega_s (`number`)\cr the shrinkage rate standard deviation. #' @param omega_g (`number`)\cr the growth rate standard deviation. -#' @param a_phi (`number`)\cr the alpha parameter for the fraction of cells that respond to treatment. -#' @param b_phi (`number`)\cr the beta parameter for the fraction of cells that respond to treatment. +#' @param omega_phi (`number`)\cr the proportion of cells affected by the treatment standard deviation. #' @param link_dsld (`number`)\cr the link coefficient for the derivative contribution. #' @param link_ttg (`number`)\cr the link coefficient for the time-to-growth contribution. #' @param link_identity (`number`)\cr the link coefficient for the SLD Identity contribution. @@ -25,11 +25,11 @@ NULL #' @slot mu_s (`numeric`)\cr See arguments. #' @slot mu_g (`numeric`)\cr See arguments. #' @slot mu_b (`numeric`)\cr See arguments. +#' @slot mu_phi (`numeric`)\cr See arguments. #' @slot omega_b (`numeric`)\cr See arguments. #' @slot omega_s (`numeric`)\cr See arguments. #' @slot omega_g (`numeric`)\cr See arguments. -#' @slot a_phi (`numeric`)\cr See arguments. -#' @slot b_phi (`numeric`)\cr See arguments. +#' @slot omega_phi (`numeric`)\cr See arguments. #' @slot link_dsld (`numeric`)\cr See arguments. #' @slot link_ttg (`numeric`)\cr See arguments. #' @slot link_identity (`numeric`)\cr See arguments. @@ -45,11 +45,11 @@ NULL mu_s = "numeric", mu_g = "numeric", mu_b = "numeric", - a_phi = "numeric", - b_phi = "numeric", + mu_phi = "numeric", omega_b = "numeric", omega_s = "numeric", omega_g = "numeric", + omega_phi = "numeric", link_dsld = "numeric", link_ttg = "numeric", link_identity = "numeric", @@ -65,11 +65,11 @@ SimLongitudinalGSF <- function( mu_s = log(c(0.6, 0.4)), mu_g = log(c(0.25, 0.35)), mu_b = log(60), - a_phi = c(4, 6), - b_phi = c(4, 6), + mu_phi = qlogis(c(0.4, 0.6)), omega_b = 0.2, omega_s = 0.2, omega_g = 0.2, + omega_phi = 0.2, link_dsld = 0, link_ttg = 0, link_identity = 0, @@ -81,11 +81,11 @@ SimLongitudinalGSF <- function( mu_s = mu_s, mu_g = mu_g, mu_b = mu_b, - a_phi = a_phi, - b_phi = b_phi, + mu_phi = mu_phi, omega_b = omega_b, omega_s = omega_s, omega_g = omega_g, + omega_phi = omega_phi, link_dsld = link_dsld, link_ttg = link_ttg, link_identity = link_identity, @@ -100,17 +100,15 @@ setValidity( par_lengths <- c( length(object@mu_s), length(object@mu_g), - length(object@a_phi), - length(object@b_phi) + length(object@mu_phi) ) if (length(unique(par_lengths)) != 1) { - return("The parameters `mu_s`, `mu_g`, `a_phi`, and `b_phi` must have the same length.") + return("The parameters `mu_s`, `mu_g` and `mu_phi` must have the same length.") } len_1_pars <- c( - "sigma", "omega_b", "omega_s", "omega_g", - "link_dsld", "link_ttg", "link_identity", - "link_growth" + "sigma", "omega_b", "omega_s", "omega_g", "omega_phi", + "link_dsld", "link_ttg", "link_identity", "link_growth" ) for (par in len_1_pars) { if (length(slot(object, par)) != 1) { @@ -152,7 +150,9 @@ sampleSubjects.SimLongitudinalGSF <- function(object, subjects_df) { is.factor(subjects_df$study), is.factor(subjects_df$arm), length(levels(subjects_df$study)) == length(object@mu_b), - length(levels(subjects_df$arm)) == length(object@mu_s) + length(levels(subjects_df$arm)) == length(object@mu_s), + length(levels(subjects_df$arm)) == length(object@mu_g), + length(levels(subjects_df$arm)) == length(object@mu_phi) ) res <- subjects_df |> @@ -162,7 +162,12 @@ sampleSubjects.SimLongitudinalGSF <- function(object, subjects_df) { dplyr::mutate(psi_b = stats::rlnorm(dplyr::n(), object@mu_b[.data$study_idx], object@omega_b)) |> dplyr::mutate(psi_s = stats::rlnorm(dplyr::n(), object@mu_s[.data$arm_idx], object@omega_s)) |> dplyr::mutate(psi_g = stats::rlnorm(dplyr::n(), object@mu_g[.data$arm_idx], object@omega_g)) |> - dplyr::mutate(psi_phi = stats::rbeta(dplyr::n(), object@a_phi[.data$arm_idx], object@b_phi[.data$arm_idx])) + dplyr::mutate(psi_phi_logit = stats::rnorm( + dplyr::n(), + object@mu_phi[.data$arm_idx], + object@omega_phi + )) |> + dplyr::mutate(psi_phi = stats::plogis(psi_phi_logit)) res[, c("subject", "arm", "study", "psi_b", "psi_s", "psi_g", "psi_phi")] } diff --git a/inst/stan/lm-gsf/model.stan b/inst/stan/lm-gsf/model.stan index 560023d6b..1a2af45cf 100755 --- a/inst/stan/lm-gsf/model.stan +++ b/inst/stan/lm-gsf/model.stan @@ -10,26 +10,25 @@ parameters{ vector[n_studies] lm_gsf_mu_bsld; vector[n_arms] lm_gsf_mu_ks; vector[n_arms] lm_gsf_mu_kg; + vector[n_arms] lm_gsf_mu_phi; real lm_gsf_omega_bsld; real lm_gsf_omega_ks; real lm_gsf_omega_kg; + real lm_gsf_omega_phi; {% if centred -%} vector[n_subjects] lm_gsf_psi_bsld; vector[n_subjects] lm_gsf_psi_ks; vector[n_subjects] lm_gsf_psi_kg; + vector[n_subjects] lm_gsf_psi_phi_logit; {% else -%} vector[n_subjects] lm_gsf_eta_tilde_bsld; vector[n_subjects] lm_gsf_eta_tilde_ks; vector[n_subjects] lm_gsf_eta_tilde_kg; + vector[n_subjects] lm_gsf_eta_tilde_phi; {%- endif -%} - // Phi Parameters - vector[n_subjects] lm_gsf_psi_phi; - vector[n_arms] lm_gsf_a_phi; - vector[n_arms] lm_gsf_b_phi; - // Standard deviation of the error term real lm_gsf_sigma; @@ -54,7 +53,14 @@ transformed parameters{ vector[n_subjects] lm_gsf_psi_kg = exp( lm_gsf_mu_kg[subject_arm_index] + (lm_gsf_eta_tilde_kg * lm_gsf_omega_kg) ); + vector[n_subjects] lm_gsf_psi_phi_logit = ( + lm_gsf_mu_phi[subject_arm_index] + (lm_gsf_eta_tilde_phi * lm_gsf_omega_phi) + ); {%- endif -%} + vector< + lower={{ machine_double_eps }}, + upper={{ 1 - machine_double_eps }} + >[n_subjects] lm_gsf_psi_phi = inv_logit(lm_gsf_psi_phi_logit); vector[n_tumour_all] Ypred; @@ -90,7 +96,7 @@ model { lm_gsf_psi_bsld ~ lognormal(lm_gsf_mu_bsld[subject_study_index], lm_gsf_omega_bsld); lm_gsf_psi_ks ~ lognormal(lm_gsf_mu_ks[subject_arm_index], lm_gsf_omega_ks); lm_gsf_psi_kg ~ lognormal(lm_gsf_mu_kg[subject_arm_index], lm_gsf_omega_kg); + lm_gsf_psi_phi_logit ~ normal(lm_gsf_mu_phi[subject_arm_index], lm_gsf_omega_phi); {%- endif -%} - lm_gsf_psi_phi ~ beta(lm_gsf_a_phi[subject_arm_index], lm_gsf_b_phi[subject_arm_index]); } diff --git a/inst/stan/lm-gsf/quantities.stan b/inst/stan/lm-gsf/quantities.stan index 285d89511..43b4feb0c 100644 --- a/inst/stan/lm-gsf/quantities.stan +++ b/inst/stan/lm-gsf/quantities.stan @@ -25,5 +25,5 @@ generated quantities { long_gq_pop_parameters[, 1] = exp(lm_gsf_mu_bsld[gq_long_pop_study_index]); long_gq_pop_parameters[, 2] = exp(lm_gsf_mu_ks[gq_long_pop_arm_index]); long_gq_pop_parameters[, 3] = exp(lm_gsf_mu_kg[gq_long_pop_arm_index]); - long_gq_pop_parameters[, 4] = lm_gsf_a_phi[gq_long_pop_arm_index] ./ (lm_gsf_a_phi[gq_long_pop_arm_index] + lm_gsf_b_phi[gq_long_pop_arm_index]); + long_gq_pop_parameters[, 4] = inv_logit(lm_gsf_mu_phi[gq_long_pop_arm_index]); } diff --git a/man/LongitudinalGSF-class.Rd b/man/LongitudinalGSF-class.Rd index 9128f9e50..0dbc93141 100644 --- a/man/LongitudinalGSF-class.Rd +++ b/man/LongitudinalGSF-class.Rd @@ -11,11 +11,11 @@ LongitudinalGSF( mu_bsld = prior_normal(log(60), 1), mu_ks = prior_normal(log(0.5), 1), mu_kg = prior_normal(log(0.3), 1), + mu_phi = prior_normal(qlogis(0.5), 1), omega_bsld = prior_lognormal(log(0.2), 1), omega_ks = prior_lognormal(log(0.2), 1), omega_kg = prior_lognormal(log(0.2), 1), - a_phi = prior_lognormal(log(5), 1), - b_phi = prior_lognormal(log(5), 1), + omega_phi = prior_lognormal(log(0.2), 1), sigma = prior_lognormal(log(0.1), 1), centred = FALSE ) @@ -27,15 +27,16 @@ LongitudinalGSF( \item{mu_kg}{(\code{Prior})\cr for the mean growth rate \code{mu_kg}.} +\item{mu_phi}{(\code{Prior})\cr for the mean proportion of cells affected by the treatment \code{mu_phi}.} + \item{omega_bsld}{(\code{Prior})\cr for the baseline value standard deviation \code{omega_bsld}.} \item{omega_ks}{(\code{Prior})\cr for the shrinkage rate standard deviation \code{omega_ks}.} \item{omega_kg}{(\code{Prior})\cr for the growth rate standard deviation \code{omega_kg}.} -\item{a_phi}{(\code{Prior})\cr for the alpha parameter for the fraction of cells that respond to treatment.} - -\item{b_phi}{(\code{Prior})\cr for the beta parameter for the fraction of cells that respond to treatment.} +\item{omega_phi}{(\code{Prior})\cr for the proportion of cells affected by the +treatment standard deviation \code{omega_phi}.} \item{sigma}{(\code{Prior})\cr for the variance of the longitudinal values \code{sigma}.} diff --git a/man/SimLongitudinalGSF-class.Rd b/man/SimLongitudinalGSF-class.Rd index 703bb97a1..65d3efb61 100644 --- a/man/SimLongitudinalGSF-class.Rd +++ b/man/SimLongitudinalGSF-class.Rd @@ -13,11 +13,11 @@ SimLongitudinalGSF( mu_s = log(c(0.6, 0.4)), mu_g = log(c(0.25, 0.35)), mu_b = log(60), - a_phi = c(4, 6), - b_phi = c(4, 6), + mu_phi = qlogis(c(0.4, 0.6)), omega_b = 0.2, omega_s = 0.2, omega_g = 0.2, + omega_phi = 0.2, link_dsld = 0, link_ttg = 0, link_identity = 0, @@ -29,15 +29,13 @@ SimLongitudinalGSF( \item{sigma}{(\code{number})\cr the variance of the longitudinal values.} -\item{mu_s}{(\code{numeric})\cr the mean shrinkage rates for the two treatment arms.} +\item{mu_s}{(\code{numeric})\cr the mean shrinkage rates.} -\item{mu_g}{(\code{numeric})\cr the mean growth rates for the two treatment arms.} +\item{mu_g}{(\code{numeric})\cr the mean growth rates.} -\item{mu_b}{(\code{numeric})\cr the mean baseline values for the two treatment arms.} +\item{mu_b}{(\code{numeric})\cr the mean baseline values.} -\item{a_phi}{(\code{number})\cr the alpha parameter for the fraction of cells that respond to treatment.} - -\item{b_phi}{(\code{number})\cr the beta parameter for the fraction of cells that respond to treatment.} +\item{mu_phi}{(\code{numeric})\cr the mean proportion of cells affected by the treatment} \item{omega_b}{(\code{number})\cr the baseline value standard deviation.} @@ -45,6 +43,8 @@ SimLongitudinalGSF( \item{omega_g}{(\code{number})\cr the growth rate standard deviation.} +\item{omega_phi}{(\code{number})\cr the proportion of cells affected by the treatment standard deviation.} + \item{link_dsld}{(\code{number})\cr the link coefficient for the derivative contribution.} \item{link_ttg}{(\code{number})\cr the link coefficient for the time-to-growth contribution.} @@ -67,15 +67,15 @@ Simulate Longitudinal Data from a GSF Model \item{\code{mu_b}}{(\code{numeric})\cr See arguments.} +\item{\code{mu_phi}}{(\code{numeric})\cr See arguments.} + \item{\code{omega_b}}{(\code{numeric})\cr See arguments.} \item{\code{omega_s}}{(\code{numeric})\cr See arguments.} \item{\code{omega_g}}{(\code{numeric})\cr See arguments.} -\item{\code{a_phi}}{(\code{numeric})\cr See arguments.} - -\item{\code{b_phi}}{(\code{numeric})\cr See arguments.} +\item{\code{omega_phi}}{(\code{numeric})\cr See arguments.} \item{\code{link_dsld}}{(\code{numeric})\cr See arguments.} diff --git a/tests/testthat/_snaps/JointModel.md b/tests/testthat/_snaps/JointModel.md index 79135e328..6323643e0 100644 --- a/tests/testthat/_snaps/JointModel.md +++ b/tests/testthat/_snaps/JointModel.md @@ -93,16 +93,16 @@ lm_gsf_mu_bsld ~ normal(mu = 4.09434, sigma = 1) lm_gsf_mu_ks ~ normal(mu = -0.69315, sigma = 1) lm_gsf_mu_kg ~ normal(mu = -1.20397, sigma = 1) + lm_gsf_mu_phi ~ normal(mu = 0, sigma = 1) lm_gsf_omega_bsld ~ lognormal(mu = -1.60944, sigma = 1) lm_gsf_omega_ks ~ lognormal(mu = -1.60944, sigma = 1) lm_gsf_omega_kg ~ lognormal(mu = -1.60944, sigma = 1) - lm_gsf_a_phi ~ lognormal(mu = 1.60944, sigma = 1) - lm_gsf_b_phi ~ lognormal(mu = 1.60944, sigma = 1) - lm_gsf_psi_phi ~ + lm_gsf_omega_phi ~ lognormal(mu = -1.60944, sigma = 1) lm_gsf_sigma ~ lognormal(mu = -2.30259, sigma = 1) lm_gsf_eta_tilde_bsld ~ std_normal() lm_gsf_eta_tilde_ks ~ std_normal() lm_gsf_eta_tilde_kg ~ std_normal() + lm_gsf_eta_tilde_phi ~ std_normal() Link: No Link diff --git a/tests/testthat/_snaps/LongitudinalGSF.md b/tests/testthat/_snaps/LongitudinalGSF.md index a6afe95d2..a02065f9e 100644 --- a/tests/testthat/_snaps/LongitudinalGSF.md +++ b/tests/testthat/_snaps/LongitudinalGSF.md @@ -9,16 +9,16 @@ lm_gsf_mu_bsld ~ normal(mu = 4.09434, sigma = 1) lm_gsf_mu_ks ~ normal(mu = -0.69315, sigma = 1) lm_gsf_mu_kg ~ normal(mu = -1.20397, sigma = 1) + lm_gsf_mu_phi ~ normal(mu = 0, sigma = 1) lm_gsf_omega_bsld ~ lognormal(mu = -1.60944, sigma = 1) lm_gsf_omega_ks ~ lognormal(mu = -1.60944, sigma = 1) lm_gsf_omega_kg ~ lognormal(mu = -1.60944, sigma = 1) - lm_gsf_a_phi ~ lognormal(mu = 1.60944, sigma = 1) - lm_gsf_b_phi ~ lognormal(mu = 1.60944, sigma = 1) - lm_gsf_psi_phi ~ + lm_gsf_omega_phi ~ lognormal(mu = -1.60944, sigma = 1) lm_gsf_sigma ~ lognormal(mu = -2.30259, sigma = 1) lm_gsf_eta_tilde_bsld ~ std_normal() lm_gsf_eta_tilde_ks ~ std_normal() lm_gsf_eta_tilde_kg ~ std_normal() + lm_gsf_eta_tilde_phi ~ std_normal() --- @@ -32,15 +32,15 @@ lm_gsf_mu_bsld ~ normal(mu = 4.09434, sigma = 1) lm_gsf_mu_ks ~ normal(mu = -0.69315, sigma = 1) lm_gsf_mu_kg ~ gamma(alpha = 2, beta = 1) + lm_gsf_mu_phi ~ normal(mu = 0, sigma = 1) lm_gsf_omega_bsld ~ lognormal(mu = -1.60944, sigma = 1) lm_gsf_omega_ks ~ lognormal(mu = -1.60944, sigma = 1) lm_gsf_omega_kg ~ lognormal(mu = -1.60944, sigma = 1) - lm_gsf_a_phi ~ lognormal(mu = 1.60944, sigma = 1) - lm_gsf_b_phi ~ lognormal(mu = 1.60944, sigma = 1) - lm_gsf_psi_phi ~ + lm_gsf_omega_phi ~ lognormal(mu = -1.60944, sigma = 1) lm_gsf_sigma ~ normal(mu = 0, sigma = 1) lm_gsf_eta_tilde_bsld ~ std_normal() lm_gsf_eta_tilde_ks ~ std_normal() lm_gsf_eta_tilde_kg ~ std_normal() + lm_gsf_eta_tilde_phi ~ std_normal() diff --git a/tests/testthat/test-Grid.R b/tests/testthat/test-Grid.R index 5602311d3..3ca2f1a34 100644 --- a/tests/testthat/test-Grid.R +++ b/tests/testthat/test-Grid.R @@ -29,11 +29,11 @@ set_fixtures_gsf <- function() { mu_s = log(c(0.6, 0.4)), mu_g = log(c(0.25, 0.35)), mu_b = log(c(60, 50)), - a_phi = c(15, 15), - b_phi = c(15, 15), + mu_phi = qlogis(c(0.4, 0.6)), omega_b = 0.2, omega_s = 0.2, - omega_g = 0.2 + omega_g = 0.2, + omega_phi = 0.2 ), .silent = TRUE ) @@ -53,11 +53,11 @@ set_fixtures_gsf <- function() { mu_bsld = prior_normal(log(60), 0.5), mu_ks = prior_normal(log(0.6), 0.5), mu_kg = prior_normal(log(0.3), 0.5), + mu_phi = prior_normal(plogis(0.5), 0.5), omega_bsld = prior_lognormal(log(0.2), 0.5), omega_ks = prior_lognormal(log(0.2), 0.5), omega_kg = prior_lognormal(log(0.2), 0.5), - a_phi = prior_lognormal(log(15), 0.5), - b_phi = prior_lognormal(log(15), 0.5), + omega_phi = prior_lognormal(log(0.2), 0.5), sigma = prior_lognormal(log(0.01), 0.5), centred = TRUE ), @@ -637,7 +637,7 @@ test_that("GridPopulation() works as expected for GSF models", { } samples_df <- as.CmdStanMCMC(fixtures_gsf$mp)$draws( - c("lm_gsf_mu_ks", "lm_gsf_mu_kg", "lm_gsf_mu_bsld", "lm_gsf_a_phi", "lm_gsf_b_phi"), + c("lm_gsf_mu_ks", "lm_gsf_mu_kg", "lm_gsf_mu_bsld", "lm_gsf_mu_phi"), format = "draws_df" ) |> dplyr::as_tibble(.name_repair = make.names) |> @@ -649,16 +649,14 @@ test_that("GridPopulation() works as expected for GSF models", { time = selected_times ) |> dplyr::mutate( - lm_gsf_phi_1 = lm_gsf_a_phi.1. / (lm_gsf_a_phi.1. + lm_gsf_b_phi.1.), - lm_gsf_phi_2 = lm_gsf_a_phi.2. / (lm_gsf_a_phi.2. + lm_gsf_b_phi.2.), esld_g1 = gsf_sld( - time, exp(lm_gsf_mu_bsld.1.), exp(lm_gsf_mu_ks.1.), exp(lm_gsf_mu_kg.1.), lm_gsf_phi_1 + time, exp(lm_gsf_mu_bsld.1.), exp(lm_gsf_mu_ks.1.), exp(lm_gsf_mu_kg.1.), plogis(lm_gsf_mu_phi.1.) ), esld_g2 = gsf_sld( - time, exp(lm_gsf_mu_bsld.1.), exp(lm_gsf_mu_ks.2.), exp(lm_gsf_mu_kg.2.), lm_gsf_phi_2 + time, exp(lm_gsf_mu_bsld.1.), exp(lm_gsf_mu_ks.2.), exp(lm_gsf_mu_kg.2.), plogis(lm_gsf_mu_phi.2.) ), esld_g3 = gsf_sld( - time, exp(lm_gsf_mu_bsld.2.), exp(lm_gsf_mu_ks.2.), exp(lm_gsf_mu_kg.2.), lm_gsf_phi_2 + time, exp(lm_gsf_mu_bsld.2.), exp(lm_gsf_mu_ks.2.), exp(lm_gsf_mu_kg.2.), plogis(lm_gsf_mu_phi.2.) ), ) |> dplyr::select(time, esld_g1, esld_g2, esld_g3, sample_id) |> diff --git a/tests/testthat/test-GridPrediction.R b/tests/testthat/test-GridPrediction.R index 0a839e098..3820c8031 100644 --- a/tests/testthat/test-GridPrediction.R +++ b/tests/testthat/test-GridPrediction.R @@ -24,11 +24,11 @@ set_fixtures_gsf_link <- function() { mu_s = log(c(0.6, 0.4)), mu_g = log(c(0.25, 0.35)), mu_b = log(c(60, 50)), - a_phi = c(15, 15), - b_phi = c(15, 15), + mu_phi = qlogis(c(0.4, 0.6)), omega_b = 0.2, omega_s = 0.2, omega_g = 0.2, + omega_phi = 0.2, link_dsld = 0.04, link_identity = 0.04 ), @@ -50,11 +50,11 @@ set_fixtures_gsf_link <- function() { mu_bsld = prior_normal(log(60), 0.5), mu_ks = prior_normal(log(0.6), 0.5), mu_kg = prior_normal(log(0.3), 0.5), + mu_phi = prior_normal(plogis(0.5), 0.5), omega_bsld = prior_lognormal(log(0.2), 0.5), omega_ks = prior_lognormal(log(0.2), 0.5), omega_kg = prior_lognormal(log(0.2), 0.5), - a_phi = prior_lognormal(log(15), 0.5), - b_phi = prior_lognormal(log(15), 0.5), + omega_phi = prior_lognormal(log(0.2), 0.5), sigma = prior_lognormal(log(0.01), 0.5), centred = TRUE ), @@ -133,11 +133,11 @@ set_fixtures_weibull_only <- function() { mu_s = log(c(0.6, 0.4)), mu_g = log(c(0.25, 0.35)), mu_b = log(c(60, 50)), - a_phi = c(15, 15), - b_phi = c(15, 15), + mu_phi = qlogis(c(0.4, 0.6)), omega_b = 0.2, omega_s = 0.2, omega_g = 0.2, + omega_phi = 0.2, link_dsld = 0, link_identity = 0 ), diff --git a/tests/testthat/test-LongitudinalGSF.R b/tests/testthat/test-LongitudinalGSF.R index 0e2f05537..490016f84 100644 --- a/tests/testthat/test-LongitudinalGSF.R +++ b/tests/testthat/test-LongitudinalGSF.R @@ -88,11 +88,11 @@ test_that("Can recover known distributional parameters from a full GSF joint mod mu_s = log(c(0.6, 0.4)), mu_g = log(c(0.25, 0.35)), mu_b = log(60), - a_phi = c(20, 15), - b_phi = c(15, 20), + mu_phi = qlogis(c(0.4, 0.6)), omega_b = 0.2, omega_s = 0.2, omega_g = 0.2, + omega_phi = 0.2, link_dsld = 0.1, link_ttg = 0.2, link_identity = 0 @@ -122,11 +122,11 @@ test_that("Can recover known distributional parameters from a full GSF joint mod mu_bsld = prior_normal(log(60), 1), mu_ks = prior_normal(log(0.6), 1), mu_kg = prior_normal(log(0.3), 1), + mu_phi = prior_normal(qlogis(0.5), 0.5), omega_bsld = prior_lognormal(log(0.2), 1), omega_ks = prior_lognormal(log(0.2), 1), omega_kg = prior_lognormal(log(0.2), 1), - a_phi = prior_lognormal(log(18), 1), - b_phi = prior_lognormal(log(18), 1), + omega_phi = prior_lognormal(log(0.2), 1), sigma = prior_lognormal(log(0.01), 1), centred = TRUE ), @@ -147,7 +147,7 @@ test_that("Can recover known distributional parameters from a full GSF joint mod iter_warmup = 400, iter_sampling = 800, chains = 2, - refresh = 0, + refresh = 200, parallel_chains = 2 ) }) @@ -189,10 +189,10 @@ test_that("Can recover known distributional parameters from a full GSF joint mod dat <- summary_post( as.CmdStanMCMC(mp), - c("link_dsld", "link_ttg", "lm_gsf_a_phi", "lm_gsf_b_phi", "sm_exp_lambda") + c("link_dsld", "link_ttg", "sm_exp_lambda", "lm_gsf_mu_phi") ) - true_values <- c(0.1, 0.2, 20, 15, 15, 20, 1 / (1 / (400 / 365))) + true_values <- c(0.1, 0.2, 1 / (1 / (400 / 365)), qlogis(c(0.4, 0.6))) expect_true(all(dat$q01 <= true_values)) expect_true(all(dat$q99 >= true_values)) expect_true(all(dat$ess_bulk > 100)) diff --git a/tests/testthat/test-SimJointData.R b/tests/testthat/test-SimJointData.R index aba511282..06c59e9cd 100644 --- a/tests/testthat/test-SimJointData.R +++ b/tests/testthat/test-SimJointData.R @@ -21,11 +21,11 @@ test_that("SimJointData works as expected", { mu_s = log(c(0.2, 0.25)), mu_g = log(c(0.15, 0.2)), mu_b = log(60), + mu_phi = qlogis(c(0.4, 0.6)), omega_b = 0.1, omega_s = 0.1, omega_g = 0.1, - a_phi = c(4, 6), - b_phi = c(4, 6), + omega_phi = 0.1, link_dsld = 0, link_ttg = 0 ), diff --git a/tests/testthat/test-SimLongitudinalGSF.R b/tests/testthat/test-SimLongitudinalGSF.R index 30c2d8d8e..78d415417 100644 --- a/tests/testthat/test-SimLongitudinalGSF.R +++ b/tests/testthat/test-SimLongitudinalGSF.R @@ -6,11 +6,11 @@ test_that("SimLongitudinalGSF works as expected", { mu_b = log(c(60, 90)), mu_s = log(c(0.6, 0.4)), mu_g = log(c(0.25, 0.35)), + mu_phi = qlogis(c(0.4, 0.6)), omega_b = 0.000000001, omega_s = 0.000000001, omega_g = 0.000000001, - a_phi = c(99999999, 11111111), - b_phi = c(11111111, 99999999), + omega_phi = 0.000000001, link_dsld = 0, link_ttg = 0, link_identity = 0 @@ -29,7 +29,7 @@ test_that("SimLongitudinalGSF works as expected", { expect_equal(res_subs$psi_b, c(60, 60, 90), tolerance = 0.00001) expect_equal(res_subs$psi_s, c(0.6, 0.4, 0.6), tolerance = 0.00001) expect_equal(res_subs$psi_g, c(0.25, 0.35, 0.25), tolerance = 0.0001) - expect_equal(res_subs$psi_phi, c(0.9, 0.1, 0.9), tolerance = 0.01) + expect_equal(res_subs$psi_phi, c(0.4, 0.6, 0.4), tolerance = 0.01) expect_equal(nrow(res_subs), nrow(subs)) expect_equal( names(res_subs), diff --git a/tests/testthat/test-initialValues.R b/tests/testthat/test-initialValues.R index 0204eaf2d..8e35539c2 100644 --- a/tests/testthat/test-initialValues.R +++ b/tests/testthat/test-initialValues.R @@ -90,7 +90,7 @@ test_that("intial values for fixed distributions gives valid values", { ivs <- initialValues(gsfmodel, n_chains = 100) for (values in ivs) { - expect_true(values$lm_gsf_psi_phi > 0 & values$lm_gsf_psi_phi < 1) + expect_true(plogis(values$lm_gsf_psi_phi_logit) > 0 & plogis(values$lm_gsf_psi_phi_logit) < 1) expect_true(values$lm_gsf_psi_bsld > 0) expect_true(values$lm_gsf_psi_ks > 0) expect_true(values$lm_gsf_psi_kg > 0) diff --git a/vignettes/extending-jmpost.Rmd b/vignettes/extending-jmpost.Rmd index 92a3aa79d..1f2274c30 100644 --- a/vignettes/extending-jmpost.Rmd +++ b/vignettes/extending-jmpost.Rmd @@ -577,11 +577,11 @@ the `SimLongitudinalGSF` class is implemented: mu_s = "numeric", mu_g = "numeric", mu_b = "numeric", - a_phi = "numeric", - b_phi = "numeric", + mu_phi = "numeric", omega_b = "numeric", omega_s = "numeric", omega_g = "numeric", + omega_phi = "numeric", link_dsld = "numeric", link_ttg = "numeric", link_identity = "numeric" @@ -595,11 +595,11 @@ SimLongitudinalGSF <- function( mu_s = log(c(0.6, 0.4)), mu_g = log(c(0.25, 0.35)), mu_b = log(60), - a_phi = c(4, 6), - b_phi = c(4, 6), + mu_phi = qlogis(c(0.4, 0.6)), omega_b = 0.2, omega_s = 0.2, omega_g = 0.2, + omega_phi = 0.2, link_dsld = 0, link_ttg = 0, link_identity = 0 @@ -610,11 +610,11 @@ SimLongitudinalGSF <- function( mu_s = mu_s, mu_g = mu_g, mu_b = mu_b, - a_phi = a_phi, - b_phi = b_phi, + mu_phi = mu_phi, omega_b = omega_b, omega_s = omega_s, omega_g = omega_g, + omega_phi = omega_phi, link_dsld = link_dsld, link_ttg = link_ttg, link_identity = link_identity @@ -628,7 +628,12 @@ sampleSubjects.SimLongitudinalGSF <- function(object, subjects_df) { dplyr::mutate(psi_b = stats::rlnorm(dplyr::n(), object@mu_b[.data$study_idx], object@omega_b)) |> dplyr::mutate(psi_s = stats::rlnorm(dplyr::n(), object@mu_s[.data$arm_idx], object@omega_s)) |> dplyr::mutate(psi_g = stats::rlnorm(dplyr::n(), object@mu_g[.data$arm_idx], object@omega_g)) |> - dplyr::mutate(psi_phi = stats::rbeta(dplyr::n(), object@a_phi[.data$arm_idx], object@b_phi[.data$arm_idx])) + dplyr::mutate(psi_phi_logit = stats::rnorm( + dplyr::n(), + object@mu_phi[.data$arm_idx], + object@omega_phi + )) |> + dplyr::mutate(psi_phi = stats::plogis(psi_phi_logit)) res[, c("subject", "arm", "study", "psi_b", "psi_s", "psi_g", "psi_phi")] } diff --git a/vignettes/statistical-specification.Rmd b/vignettes/statistical-specification.Rmd index e1dd5cdfd..63bc8194f 100644 --- a/vignettes/statistical-specification.Rmd +++ b/vignettes/statistical-specification.Rmd @@ -258,7 +258,7 @@ b_i e^{g_i t_{ij}} & \text{if } t_{ij}\lt 0 b_i &\sim \text{LogNormal}(\mu_{bl(i)}, \omega_b) \\ s_i &\sim \text{LogNormal}(\mu_{sk(i)}, \omega_s) \\ g_i &\sim \text{LogNormal}(\mu_{gk(i)}, \omega_g) \\ -\phi &\sim \text{Beta}(a_{\phi k(i)}, b_{\phi k(i)}) +\phi_i &\sim \text{LogitNormal}(\mu_{\phi k(i)}, \omega_\phi) \end{align*} $$ @@ -285,10 +285,12 @@ $$ b_i &= exp(\mu_{bl(i)} + \omega_b * \eta_{b i}) \\ s_i &= exp(\mu_{sk(i)} + \omega_s * \eta_{s i}) \\ g_i &= exp(\mu_{gk(i)} + \omega_g * \eta_{g i}) \\ +\phi_i &= \text{logistic}(\mu_{gk(i)} + \omega_\phi * \eta_{\phi i}) \\ \\ \eta_{b i} &\sim N(0, 1)\\ \eta_{s i} &\sim N(0, 1) \\ \eta_{g i} &\sim N(0, 1) \\ +\eta_{\phi i} &\sim N(0, 1) \\ \end{align*} $$ @@ -349,7 +351,7 @@ Accessible via `linkGrowth()` ### Population Quantities -Note that when generating population quantities for the $b$, $s$ and $g$ parameters the median +Note that when generating population quantities for the $b$, $s$, $g$ and $\phi$ parameters the median of the distribution is used. This is because this has the same interpretation as using a non-centred parameterisation and setting the "random effects" term to be 0. From f9c13c8c04af9572d89064ba0bf9ba7a73f8ff65 Mon Sep 17 00:00:00 2001 From: gowerc Date: Fri, 28 Jun 2024 17:17:48 +0100 Subject: [PATCH 2/3] Fix false-positive spelling --- inst/WORDLIST | 1 + 1 file changed, 1 insertion(+) diff --git a/inst/WORDLIST b/inst/WORDLIST index 448789d8f..ab3f1f57c 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -141,3 +141,4 @@ groupwise du int pk +LogitNormal From eceb927fbc2ff5da6b0ed0effcbedec2003662a3 Mon Sep 17 00:00:00 2001 From: gowerc Date: Mon, 1 Jul 2024 16:24:49 +0100 Subject: [PATCH 3/3] updated docs2 --- R/LongitudinalGSF.R | 4 ++-- R/SimLongitudinalGSF.R | 3 ++- man/LongitudinalGSF-class.Rd | 4 ++-- man/SimLongitudinalGSF-class.Rd | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/R/LongitudinalGSF.R b/R/LongitudinalGSF.R index d8a7d47e9..38d96cba1 100755 --- a/R/LongitudinalGSF.R +++ b/R/LongitudinalGSF.R @@ -36,8 +36,8 @@ NULL #' @param omega_bsld (`Prior`)\cr for the baseline value standard deviation `omega_bsld`. #' @param omega_ks (`Prior`)\cr for the shrinkage rate standard deviation `omega_ks`. #' @param omega_kg (`Prior`)\cr for the growth rate standard deviation `omega_kg`. -#' @param omega_phi (`Prior`)\cr for the proportion of cells affected by the -#' treatment standard deviation `omega_phi`. +#' @param omega_phi (`Prior`)\cr for the standard deviation of the proportion of cells +#' affected by the treatment `omega_phi`. #' #' @param sigma (`Prior`)\cr for the variance of the longitudinal values `sigma`. #' diff --git a/R/SimLongitudinalGSF.R b/R/SimLongitudinalGSF.R index 13224cac5..d40e8d16c 100644 --- a/R/SimLongitudinalGSF.R +++ b/R/SimLongitudinalGSF.R @@ -15,7 +15,8 @@ NULL #' @param omega_b (`number`)\cr the baseline value standard deviation. #' @param omega_s (`number`)\cr the shrinkage rate standard deviation. #' @param omega_g (`number`)\cr the growth rate standard deviation. -#' @param omega_phi (`number`)\cr the proportion of cells affected by the treatment standard deviation. +#' @param omega_phi (`number`)\cr for the standard deviation of the proportion of cells +#' affected by the treatment `omega_phi`. #' @param link_dsld (`number`)\cr the link coefficient for the derivative contribution. #' @param link_ttg (`number`)\cr the link coefficient for the time-to-growth contribution. #' @param link_identity (`number`)\cr the link coefficient for the SLD Identity contribution. diff --git a/man/LongitudinalGSF-class.Rd b/man/LongitudinalGSF-class.Rd index 0dbc93141..236b3b945 100644 --- a/man/LongitudinalGSF-class.Rd +++ b/man/LongitudinalGSF-class.Rd @@ -35,8 +35,8 @@ LongitudinalGSF( \item{omega_kg}{(\code{Prior})\cr for the growth rate standard deviation \code{omega_kg}.} -\item{omega_phi}{(\code{Prior})\cr for the proportion of cells affected by the -treatment standard deviation \code{omega_phi}.} +\item{omega_phi}{(\code{Prior})\cr for the standard deviation of the proportion of cells +affected by the treatment \code{omega_phi}.} \item{sigma}{(\code{Prior})\cr for the variance of the longitudinal values \code{sigma}.} diff --git a/man/SimLongitudinalGSF-class.Rd b/man/SimLongitudinalGSF-class.Rd index 65d3efb61..38d18d632 100644 --- a/man/SimLongitudinalGSF-class.Rd +++ b/man/SimLongitudinalGSF-class.Rd @@ -43,7 +43,8 @@ SimLongitudinalGSF( \item{omega_g}{(\code{number})\cr the growth rate standard deviation.} -\item{omega_phi}{(\code{number})\cr the proportion of cells affected by the treatment standard deviation.} +\item{omega_phi}{(\code{number})\cr for the standard deviation of the proportion of cells +affected by the treatment \code{omega_phi}.} \item{link_dsld}{(\code{number})\cr the link coefficient for the derivative contribution.}