Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring matchTolerance #706

Merged
merged 7 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
1 change: 0 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ Imports:
checkmate (>= 2.2.0),
futile.logger,
GenSA,
grid,
magrittr,
gridExtra,
lifecycle,
Expand Down
4 changes: 3 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -270,12 +270,14 @@ export(TDsamplesDesign)
export(TITELogisticLogNormal)
export(ThreePlusThreeDesign)
export(approximate)
export(assert_equal)
export(assert_length)
export(assert_probabilities)
export(assert_probability)
export(assert_probability_range)
export(assert_range)
export(biomarker)
export(check_equal)
export(check_length)
export(check_probabilities)
export(check_probability)
Expand Down Expand Up @@ -336,7 +338,7 @@ export(h_validate_combine_results)
export(is_logging_enabled)
export(log_trace)
export(logit)
export(matchTolerance)
export(match_within_tolerance)
export(maxDose)
export(maxSize)
export(mcmc)
Expand Down
9 changes: 5 additions & 4 deletions R/Data-class.R
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ Data <- function(x = numeric(),
assert_numeric(doseGrid, any.missing = FALSE, unique = TRUE)
assert_flag(placebo)

doseGrid <- as.numeric(sort(doseGrid))
doseGrid <- sort(doseGrid)
assert_subset(x, doseGrid)

if (length(ID) == 0 && length(x) > 0) {
message("Used default patient IDs!")
Expand All @@ -148,10 +149,10 @@ Data <- function(x = numeric(),
y = as.integer(y),
ID = as.integer(ID),
cohort = as.integer(cohort),
doseGrid = doseGrid,
doseGrid = as.numeric(doseGrid),
nObs = length(x),
nGrid = length(doseGrid),
xLevel = matchTolerance(x = x, table = doseGrid),
xLevel = match_within_tolerance(x, doseGrid),
placebo = placebo
)
}
Expand Down Expand Up @@ -488,7 +489,7 @@ DataOrdinal <- function(x = numeric(),
doseGrid = doseGrid,
nObs = length(x),
nGrid = length(doseGrid),
xLevel = matchTolerance(x = x, table = doseGrid),
xLevel = match_within_tolerance(x = x, table = doseGrid),
placebo = placebo,
yCategories = yCategories
)
Expand Down
4 changes: 2 additions & 2 deletions R/Data-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ setMethod(
n <- length(y)

# Which grid level is the dose?
gridLevel <- matchTolerance(x, object@doseGrid)
gridLevel <- match_within_tolerance(x, object@doseGrid)
object@xLevel <- c(object@xLevel, rep(gridLevel, n))

# Add dose.
Expand Down Expand Up @@ -399,7 +399,7 @@ setMethod(
n <- length(y)

# Which grid level is the dose?
gridLevel <- matchTolerance(x, object@doseGrid)
gridLevel <- match_within_tolerance(x, object@doseGrid)
object@xLevel <- c(object@xLevel, rep(gridLevel, n))

# Add dose.
Expand Down
2 changes: 1 addition & 1 deletion R/Model-class.R
Original file line number Diff line number Diff line change
Expand Up @@ -2591,7 +2591,7 @@ EffFlexi <- function(eff,
)

x <- c(eff_dose, getEff(data, no_dlt = TRUE)$x_no_dlt)
x_level <- matchTolerance(x, data@doseGrid)
x_level <- match_within_tolerance(x, data@doseGrid)
X <- model.matrix(~ -1L + factor(x_level, levels = seq_len(data@nGrid)))
X <- matrix(as.integer(X), ncol = ncol(X)) # To remove some obsolete attributes.

Expand Down
2 changes: 1 addition & 1 deletion R/Model-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,7 @@ setMethod(
assert_length(dose, len = n_samples)

dose_grid <- model@data@doseGrid
dose_level <- matchTolerance(dose, dose_grid)
dose_level <- match_within_tolerance(dose, dose_grid)
dose[which(!is.na(dose_level))] <- dose_grid[stats::na.omit(dose_level)]

# linear interpolation, NA for doses that are outside of the dose_grid range.
Expand Down
2 changes: 1 addition & 1 deletion R/Rules-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -1500,7 +1500,7 @@ setMethod(
if (is.null(incrmnt)) {
callNextMethod(increments, data, ...)
} else {
max_dose_lev_part1 <- matchTolerance(max(data@x), data@part1Ladder)
max_dose_lev_part1 <- match_within_tolerance(max(data@x), data@part1Ladder)
new_max_dose_level <- max_dose_lev_part1 + incrmnt
assert_true(new_max_dose_level >= 0L)
assert_true(new_max_dose_level <= length(data@part1Ladder))
Expand Down
10 changes: 5 additions & 5 deletions R/Simulations-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ setMethod("summary",
doseMostSelected <-
as.numeric(names(which.max(table(doseSelected))))
xMostSelected <-
matchTolerance(doseMostSelected,
match_within_tolerance(doseMostSelected,
table = doseGrid
)

Expand Down Expand Up @@ -588,7 +588,7 @@ setMethod("summary",

## dose level most often selected as MTD
xMostSelected <-
matchTolerance(start@doseMostSelected,
match_within_tolerance(start@doseMostSelected,
table = doseGrid
)

Expand Down Expand Up @@ -683,7 +683,7 @@ setMethod("summary",

## dose level most often selected as MTD
xMostSelected <-
matchTolerance(start@doseMostSelected,
match_within_tolerance(start@doseMostSelected,
table = doseGrid
)

Expand Down Expand Up @@ -1584,7 +1584,7 @@ setMethod("summary",
# doseRec <- doseMostSelected

xMostSelected <-
matchTolerance(doseMostSelected,
match_within_tolerance(doseMostSelected,
table = doseGrid
)

Expand Down Expand Up @@ -2467,7 +2467,7 @@ setMethod("summary",

## ## dose level most often selected as MTD (TDtargetEnd of Trial)
xMostSelected <-
matchTolerance(start@doseMostSelected,
match_within_tolerance(start@doseMostSelected,
table = doseGrid
)

Expand Down
103 changes: 102 additions & 1 deletion R/checkmate.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,107 @@
#' @name assertions
NULL

# check equality ----

#' Check if All Arguments Are Equal
#'
#' @description `r lifecycle::badge("experimental")`
#' Elements of `...` must be numeric vectors or scalars.
#'
#' This function performs an element-by-element comparison of the first object
#' provided in `...` with every other object in `...` and returns `TRUE` if all
#' comparisons are equal within a given tolerance and `FALSE` otherwise.
#'
#' @param ... (`numeric`)\cr vectors to be compared
#' @param tol (`numeric`)\cr the maximum difference to be tolerated when
#' judging equality
Puzzled-Face marked this conversation as resolved.
Show resolved Hide resolved
#'
#' @note If there are any missing or infinite values in `...`, this function
#' returns `FALSE`, regardless of the values of other elements in `...`.
#'
#' @note If elements in `...` are not all of the same length, `FALSE` is returned.
#'
#' @return TRUE if all element-by-element differences are less than `tolerance`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#' @return TRUE if all element-by-element differences are less than `tolerance`
#' @return `TRUE` if all element-by-element differences are less than `tolerance`

#' in magnitude, `FALSE` otherwise.
#' @seealso [`assertions`] for more details.
#'
#' @export
#' @examples
#' check_equal(1:2, 1:2) # TRUE
#' check_equal(1:2, 2:3) # "Not all equal"
#' check_equal(Inf, Inf) # "Not all equal"
#' check_equal(0.01, 0.02) # "Not all equal"
#' check_equal(0.01, 0.02, tol = 0.05) # TRUE
#' check_equal(1, c(1, 1)) # "Not all equal"
Puzzled-Face marked this conversation as resolved.
Show resolved Hide resolved
check_equal <- function(..., tol = sqrt(.Machine$double.eps)) {
dot_args <- list(...)

sapply(dot_args, assert_numeric)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better use vapply everywhere here (because it is safer)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better use vapply everywhere here (because it is safer)

vapply is new to me. Not sure I agree here.

The potential problem is vapply's FUN.VALUE argument. From the online doc: "all values of FUN [should be] compatible with the FUN.VALUE, in that they must have the same length and type".

The problem is that we don't know:

  1. How many entries are in ...
  2. The length of each entry in ...

and, in addition,

  1. assert_numeric returns an object of the same type as its first argument (or throws an error)

I think we could work all that out, but it would add considerably to the complexity of the function.


tmp <- sapply(dot_args, length)
if (min(tmp) != max(tmp)) {
return("Not all of same length")
}
if (any(sapply(dot_args, is.na))) {
return("Some entries NA")
}
if (any(sapply(dot_args, is.infinite))) {
return("Not all entries finite")
}
if (!all(sapply(dot_args, test_numeric))) {
return("Not all numeric")
}

rv <- test_true(
Puzzled-Face marked this conversation as resolved.
Show resolved Hide resolved
all(
sapply(
2:length(dot_args),
function(z) abs(dot_args[[1]] - dot_args[[z]]) < tol
)
)
)
if (rv) {
return(TRUE)
} else {
return("Not all equal")
Puzzled-Face marked this conversation as resolved.
Show resolved Hide resolved
}
}

# assert equality
Puzzled-Face marked this conversation as resolved.
Show resolved Hide resolved

#' Assert That All Arguments Are Equal
Puzzled-Face marked this conversation as resolved.
Show resolved Hide resolved
#'
#' @description `r lifecycle::badge("experimental")`
#' Elements of `...` must be numeric vectors or scalars.
#'
#' This function performs an element-by-element comparison of the first object
#' provided in `...` with every other object in `...` and throws an error if they
#' are not.
#'
#' @param ... (`numeric`)\cr vectors to be compared
#' @param tol (`numeric`)\cr the maximum difference to be tolerated when
#' judging equality
#'
#' @note If there are any missing or infinite values in `...`, this function
#' throws an error, regardless of the values of other elements in `...`.
#'
#' @note If elements in `...` are not all of the same length, an error is thrown.
#'
#' @return `list(...)`, invisibly.
#' @seealso [`assertions`] for more details.
#' @inheritParams checkmate::assert_numeric
#'
#' @export
#' @examples
#' assert_equal(1:2, 1:2) # no error
#' assert_equal(0.01, 0.02, tol = 0.05) # no error
# nolint start
assert_equal <- function(..., tol = sqrt(.Machine$double.eps), .var.name = vname(x), add = NULL) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better use makeAssertionFunction or add comment why that would not work

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better use makeAssertionFunction or add comment why that would not work

assert_equal <- makeAssertionFunction(check_equal) fails with error "Error in checkmate::makeAssertion(..., res, .var.name, add): unused argument (add)". I think this is because of the use of ... in check_equal.

res <- check_equal(..., tol = tol)
makeAssertion(list(...), res, .var.name, add)
}
# nolint end

# assert_probabilities ----

#' Check if an argument is a probability vector
Expand All @@ -31,7 +132,7 @@ NULL
#' probability, that is a number within (0, 1) interval, that can optionally be
#' closed at any side.
#'
#' @note If there are any missing or non-finite values in `x`, this functions
#' @note If there are any missing or non-finite values in `x`, this function
#' returns `FALSE`, regardless of the values of other elements in `x`.
#'
#' @param x (`numeric`)\cr vector or matrix with numerical values to check.
Expand Down
2 changes: 1 addition & 1 deletion R/helpers.R
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ positive_number <- setClass(
##'
##' @export
##' @keywords programming
matchTolerance <- function(x, table) {
match_within_tolerance <- function(x, table) {
if (length(table) == 0) {
return(integer())
}
Expand Down
2 changes: 1 addition & 1 deletion R/mcmc.R
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ setMethod("mcmc",
w1 <- c(thismodel@eff, eff_obsrv$w_no_dlt)
x1 <- c(thismodel@eff_dose, eff_obsrv$x_no_dlt)
}
x1Level <- matchTolerance(x1, data@doseGrid)
x1Level <- match_within_tolerance(x1, data@doseGrid)
## betaW is constant, the average of the efficacy values
betaW <- rep(mean(w1), data@nGrid)
## sigma2betaW use fixed value or prior mean
Expand Down
4 changes: 3 additions & 1 deletion _pkgdown.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ reference:
- SimulationsSummary-class
- approximate
- assertions
- assert_equal
- check_equal
- crmPackExample
- crmPackHelp
- examine
Expand All @@ -415,7 +417,7 @@ reference:
- get,Samples,character-method
- getMinInfBeta
- logit
- matchTolerance
- match_within_tolerance
- maxSize
- minSize
- or-Stopping-Stopping
Expand Down
4 changes: 2 additions & 2 deletions design/ordinal-crm.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ DataOrdinal <- function(
doseGrid = doseGrid,
nObs = length(x),
nGrid = length(doseGrid),
xLevel = matchTolerance(x = x, table = doseGrid),
xLevel = match_within_tolerance(x = x, table = doseGrid),
placebo = placebo,
yCategories = yCategories
)
Expand Down Expand Up @@ -441,7 +441,7 @@ setMethod(
n <- length(y)

# Which grid level is the dose?
gridLevel <- matchTolerance(x, object@doseGrid)
gridLevel <- match_within_tolerance(x, object@doseGrid)
object@xLevel <- c(object@xLevel, rep(gridLevel, n))

# Add dose.
Expand Down
4 changes: 2 additions & 2 deletions design/ordinal_crm.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ DataOrdinal <- function(
doseGrid = doseGrid,
nObs = length(x),
nGrid = length(doseGrid),
xLevel = matchTolerance(x = x, table = doseGrid),
xLevel = match_within_tolerance(x = x, table = doseGrid),
placebo = placebo,
yCategories = yCategories
)
Expand Down Expand Up @@ -443,7 +443,7 @@ setMethod(
n <- length(y)

# Which grid level is the dose?
gridLevel <- matchTolerance(x, object@doseGrid)
gridLevel <- match_within_tolerance(x, object@doseGrid)
object@xLevel <- c(object@xLevel, rep(gridLevel, n))

# Add dose.
Expand Down
50 changes: 50 additions & 0 deletions man/assert_equal.Rd

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

Loading