Skip to content

Commit

Permalink
673: Add LogisticLogNormalGrouped class (#674)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
danielinteractive and github-actions[bot] authored Sep 14, 2023
1 parent 8bb205e commit 1762da7
Show file tree
Hide file tree
Showing 15 changed files with 538 additions and 24 deletions.
1 change: 0 additions & 1 deletion .lintr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ linters: linters_with_defaults(
cyclocomp_linter = NULL,
object_usage_linter = NULL,
object_length_linter = NULL,
indentation_linter = NULL,
object_name_linter = object_name_linter(c("CamelCase", "camelCase", "snake_case"))
)
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export(.DefaultIncrementsRelativeParts)
export(.DefaultLogisticKadane)
export(.DefaultLogisticKadaneBetaGamma)
export(.DefaultLogisticLogNormal)
export(.DefaultLogisticLogNormalGrouped)
export(.DefaultLogisticLogNormalMixture)
export(.DefaultLogisticLogNormalSub)
export(.DefaultLogisticNormal)
Expand Down Expand Up @@ -112,6 +113,7 @@ export(.LogisticIndepBeta)
export(.LogisticKadane)
export(.LogisticKadaneBetaGamma)
export(.LogisticLogNormal)
export(.LogisticLogNormalGrouped)
export(.LogisticLogNormalMixture)
export(.LogisticLogNormalSub)
export(.LogisticNormal)
Expand Down Expand Up @@ -210,6 +212,7 @@ export(LogisticIndepBeta)
export(LogisticKadane)
export(LogisticKadaneBetaGamma)
export(LogisticLogNormal)
export(LogisticLogNormalGrouped)
export(LogisticLogNormalMixture)
export(LogisticLogNormalSub)
export(LogisticNormal)
Expand Down Expand Up @@ -400,6 +403,7 @@ exportClasses(LogisticIndepBeta)
exportClasses(LogisticKadane)
exportClasses(LogisticKadaneBetaGamma)
exportClasses(LogisticLogNormal)
exportClasses(LogisticLogNormalGrouped)
exportClasses(LogisticLogNormalMixture)
exportClasses(LogisticLogNormalSub)
exportClasses(LogisticNormal)
Expand Down
91 changes: 91 additions & 0 deletions R/Model-class.R
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,97 @@ ProbitLogNormalRel <- function(mean, cov, ref_dose = 1) {
ProbitLogNormalRel(mean = c(-0.85, 1), cov = matrix(c(1, -0.5, -0.5, 1), nrow = 2))
}

# LogisticLogNormalGrouped ----

## class ----

#' `LogisticLogNormalGrouped`
#'
#' @description `r lifecycle::badge("experimental")`
#'
#' [`LogisticLogNormalGrouped`] is the class for a logistic regression model
#' for both the mono and the combo arms of the simultaneous dose escalation
#' design.
#'
#' @details The continuous covariate is the natural logarithm of the dose \eqn{x} divided by
#' the reference dose \eqn{x*} as in [`LogisticLogNormal`]. In addition,
#' \eqn{I_c} is a binary indicator covariate which is 1 for the combo arm and 0 for the mono arm.
#' The model is then defined as:
#' \deqn{logit[p(x)] = (alpha0 + I_c * delta0) + (alpha1 + I_c * delta1) * log(x / x*),}
#' where \eqn{p(x)} is the probability of observing a DLT for a given dose \eqn{x},
#' and `delta0` and `delta1` are the differences in the combo arm compared to the mono intercept
#' and slope parameters `alpha0` and `alpha1`.
#' The prior is defined as \deqn{(alpha0, log(delta0), log(alpha1), log(delta1)) ~ Normal(mean, cov).}
#'
#' @seealso [`ModelLogNormal`], [`LogisticLogNormal`].
#'
#' @aliases LogisticLogNormalGrouped
#' @export
#'
.LogisticLogNormalGrouped <- setClass(
Class = "LogisticLogNormalGrouped",
contains = "ModelLogNormal"
)

## constructor ----

#' @rdname LogisticLogNormalGrouped-class
#'
#' @inheritParams ModelLogNormal
#'
#' @export
#' @example examples/Model-class-LogisticLogNormalGrouped.R
#'
LogisticLogNormalGrouped <- function(mean, cov, ref_dose = 1) {
params <- ModelParamsNormal(mean, cov)
.LogisticLogNormalGrouped(
params = params,
ref_dose = positive_number(ref_dose),
priormodel = function() {
theta ~ dmnorm(mean, prec)
alpha0 <- theta[1]
delta0 <- exp(theta[2])
alpha1 <- exp(theta[3])
delta1 <- exp(theta[4])
},
datamodel = function() {
for (i in 1:nObs) {
logit(p[i]) <- (alpha0 + is_combo[i] * delta0) +
(alpha1 + is_combo[i] * delta1) * log(x[i] / ref_dose)
y[i] ~ dbern(p[i])
}
},
modelspecs = function(group, from_prior) {
ms <- list(
mean = params@mean,
prec = params@prec
)
if (!from_prior) {
ms$ref_dose <- ref_dose
ms$is_combo <- as.integer(group == "combo")
}
ms
},
init = function() {
list(theta = c(0, 1, 1, 1))
},
datanames = c("nObs", "y", "x"),
sample = c("alpha0", "delta0", "alpha1", "delta1")
)
}

## default constructor ----

#' @rdname LogisticLogNormalGrouped-class
#' @note Typically, end users will not use the `.DefaultLogisticLogNormalGrouped()` function.
#' @export
.DefaultLogisticLogNormalGrouped <- function() {
LogisticLogNormalGrouped(
mean = rep(0, 4),
cov = diag(rep(1, 4)),
)
}

# LogisticKadane ----

## class ----
Expand Down
78 changes: 74 additions & 4 deletions R/Model-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ setMethod(
data = model_params,
options = McmcOptions(samples = NROW(model_params[[1]]))
)
function(x) {
dose(x = x, model = model, samples = samples)
function(x, ...) {
dose(x = x, model = model, samples = samples, ...)
}
}
)
Expand Down Expand Up @@ -127,8 +127,8 @@ setMethod(
data = model_params,
options = McmcOptions(samples = NROW(model_params[[1]]))
)
function(dose) {
prob(dose = dose, model = model, samples = samples)
function(dose, ...) {
prob(dose = dose, model = model, samples = samples, ...)
}
}
)
Expand Down Expand Up @@ -403,6 +403,41 @@ setMethod(
}
)

## LogisticLogNormalGrouped ----

#' @describeIn dose method for [`LogisticLogNormalGrouped`] which needs `group`
#' argument in addition.
#' @param group (`character` or `factor`)\cr for [`LogisticLogNormalGrouped`],
#' indicating whether to calculate the dose for the `mono` or for
#' the `combo` arm.
#' @aliases dose-LogisticLogNormalGrouped
#' @export
#'
setMethod(
f = "dose",
signature = signature(
x = "numeric",
model = "LogisticLogNormalGrouped",
samples = "Samples"
),
definition = function(x, model, samples, group) {
assert_probabilities(x)
assert_subset(c("alpha0", "delta0", "alpha1", "delta1"), names(samples))
assert_length(x, len = size(samples))
assert_multi_class(group, c("character", "factor"))
assert_subset(as.character(group), choices = c("mono", "combo"))
assert_length(group, len = size(samples))

alpha0 <- samples@data$alpha0
delta0 <- samples@data$delta0
alpha1 <- samples@data$alpha1
delta1 <- samples@data$delta1
ref_dose <- as.numeric(model@ref_dose)
is_combo <- as.integer(group == "combo")
exp((logit(x) - (alpha0 + is_combo * delta0)) / (alpha1 + is_combo * delta1)) * ref_dose
}
)

## LogisticKadane ----

#' @describeIn dose compute the dose level reaching a specific target
Expand Down Expand Up @@ -923,6 +958,41 @@ setMethod(
}
)

## LogisticLogNormalGrouped ----

#' @describeIn prob method for [`LogisticLogNormalGrouped`] which needs `group`
#' argument in addition.
#' @param group (`character` or `factor`)\cr for [`LogisticLogNormalGrouped`],
#' indicating whether to calculate the probability for the `mono` or for
#' the `combo` arm.
#' @aliases prob-LogisticLogNormalGrouped
#' @export
#'
setMethod(
f = "prob",
signature = signature(
dose = "numeric",
model = "LogisticLogNormalGrouped",
samples = "Samples"
),
definition = function(dose, model, samples, group) {
assert_numeric(dose, lower = 0L, any.missing = FALSE, min.len = 1L)
assert_subset(c("alpha0", "delta0", "alpha1", "delta1"), names(samples))
assert_length(dose, len = size(samples))
assert_multi_class(group, c("character", "factor"))
assert_subset(as.character(group), choices = c("mono", "combo"))
assert_length(group, len = size(samples))

alpha0 <- samples@data$alpha0
delta0 <- samples@data$delta0
alpha1 <- samples@data$alpha1
delta1 <- samples@data$delta1
ref_dose <- as.numeric(model@ref_dose)
is_combo <- as.integer(group == "combo")
plogis((alpha0 + is_combo * delta0) + (alpha1 + is_combo * delta1) * log(dose / ref_dose))
}
)

## LogisticKadane ----

#' @describeIn prob
Expand Down
5 changes: 4 additions & 1 deletion R/crmPack-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ globalVariables(c(
"logit<-",
"rho0",
"alpha0",
"delta0",
"alpha1",
"delta1",
"inverse",
"priorCov",
"theta",
Expand Down Expand Up @@ -135,7 +137,8 @@ globalVariables(c(
"ref_dose",
"comp",
"X",
"skel_probs"
"skel_probs",
"is_combo"
))

# nolint end
1 change: 1 addition & 0 deletions _pkgdown.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ reference:
- LogisticLogNormalSub
- ProbitLogNormal
- ProbitLogNormalRel
- LogisticLogNormalGrouped
- LogisticKadane
- LogisticKadaneBetaGamma
- LogisticNormalMixture
Expand Down
6 changes: 6 additions & 0 deletions examples/Model-class-LogisticLogNormalGrouped.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
my_model <- LogisticLogNormalGrouped(
mean = c(-0.85, 0, 1, 0),
cov = diag(1, 4),
ref_dose = 50
)
my_model
55 changes: 55 additions & 0 deletions man/LogisticLogNormalGrouped-class.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions man/dose.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 1762da7

Please sign in to comment.