Skip to content

Commit 0199f6c

Browse files
committed
Add validator functions
1 parent b85a473 commit 0199f6c

File tree

9 files changed

+159
-80
lines changed

9 files changed

+159
-80
lines changed

R/SampleSize.R

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#' @param Eper Optional. Vector of length 2 specifying the period effect in a `dtype = "2x2"` design, applied to c(Period 0, Period 1). Defaults to `c(0, 0)` if not provided. Ignored for `dtype = "parallel"`.
1010
#' @param Eco Optional. Vector of length 2 specifying the carry-over effect for each arm in a `dtype = "2x2"` design, applied to c(Reference, Treatment). Defaults to `c(0, 0)` if not provided. Ignored for `dtype = "parallel"`.
1111
#' @param rho Correlation parameter applied uniformly across all endpoint pairs, used with sigma_list to calculate varcov if cor_mat or varcov_list are not provided.
12-
#' @param TAR vector of allocation rates with allocation rates of the arm, default is equivalent rate.
12+
#' @param TAR Numeric vector. Treatment allocation rate for each arm, where the length of `TAR` specifies the number of arms. The default is an equal allocation ratio across all arms.
1313
#' @param arm_names Optional vector with the treatment names. If not supplied, it will be derived from mu_list.
1414
#' @param ynames_list Optional list of vectors with Endpoint names on each arm. When not all endpoint names are provided for each arm, arbitrary names (assigned by vector order) are used.
1515
#' @param type_y vector with the type of endpoints: primary endpoint(1), otherwise (2).
@@ -22,23 +22,22 @@
2222
#' @param list_lequi.tol list of lower equivalence bounds (e.g., -0.5) expressed in raw scale units (e.g., scalepoints) of endpoint in comparator
2323
#' @param list_uequi.tol list of upper equivalence bounds (e.g., -0.5) expressed in raw scale units (e.g., scalepoints) of endpoint in comparator
2424
#' @param vareq Logical indicating whether variances are assumed equal across arms (default = FALSE).
25-
#' @param dtype design type ("parallel","2x2")
25+
#' @param dtype Character. Design type for the trial: `"parallel"` (default) for parallel group design or `"2x2"` for crossover design (applicable only for trials with 2 arms).
2626
#' @param lognorm Is data log-normally distributed? (TRUE, FALSE)
2727
#' @param k Vector with the number of endpoints that must be successful (integer) for global bioequivalence for each comparator. If no k vector is provided, it will be set to the total number of endpoints on each comparator.
28-
#' @param adjust alpha adjustment ( "k", "bon","sid","no","seq")
29-
#' @param ctype comparison dtype ("DOM"(Difference of means), "ROM"(Ratio of means))
28+
#' @param adjust Character. Method for alpha adjustment: `"k"` (K-fold), `"bon"` (Bonferroni), `"sid"` (Sidak), `"no"` (no adjustment, default), or `"seq"` (sequential adjustment).
29+
#' @param ctype Character. Specifies the type of hypothesis test for comparison: `"DOM"` for Difference of Means or `"ROM"` for Ratio of Means.
3030
#' @param dropout vector with proportion of total population with dropout per arm
31-
#' @param step.power initial step size is 2^step.power
32-
#' @param step.up if TRUE steps up from 'lower', if FALSE steps down from 'upper'
33-
#' @param pos.side if TRUE finds integer, i, closest to the root such that f(i) >0
34-
#' @param maxiter maximum number of iterations
3531
#' @param nsim number of simulated studies (default=5000)
36-
#' @param lower initial value of N to be searched (default=2)
37-
#' @param upper max value of N to be searched (default=500)
3832
#' @param seed main seed
39-
#' @param ncores Number of processing cores for parallel computation; defaults to the total detected cores minus one.
33+
#' @param ncores Integer. Number of processing cores to use for parallel computation. Defaults to one less than the total number of detected cores.
4034
#' @param optimization_method Character. Method for determining the required sample size: "fast" (using modified root-finding algorithms) or "step-by-step". Defaults to "fast".
41-
#'
35+
#' @param lower Integer. Initial value of `N` for the search range. Defaults to 2.
36+
#' @param upper Integer. Maximum value of `N` for the search range. Defaults to 500.
37+
#' @param step.power Numeric. The initial step size for the sample size search, defined as `2^step.power`. Relevant when `optimization_method` is `"fast"`.
38+
#' @param step.up Logical. If `TRUE` (default), the sample size search increments upward from the `lower` limit; if `FALSE`, it decrements downward from the `upper` limit. Used only when `optimization_method` is `"fast"`.
39+
#' @param pos.side Logical. If `TRUE`, finds the smallest integer, `i`, closest to the root such that `f(i) > 0`. Used only when `optimization_method` is `"fast"`.
40+
#' @param maxiter Integer. Maximum number of iterations allowed for finding the sample size. Defaults to 1000. Used only when `optimization_method` is `"fast"`.
4241
#' @return An object simss that contains the following elements :
4342
#' \describe{
4443
#' \item{"response"}{ array with the sample sizes for each arm and aproximated achieved power with confidence intervals}
@@ -67,10 +66,9 @@
6766
#' EUREF = c(AUCinf = 12332, AUClast = 9398, Cmax = 17.9),
6867
#' USREF = c(AUCinf = 10064, AUClast = 8332, Cmax = 18.8))
6968
#'
70-
#'# Equivalent boundaries
71-
#'lequi.tol <- c(AUCinf = 0.8, AUClast = 0.8, Cmax = 0.8)
72-
#'uequi.tol <- c(AUCinf = 1.25, AUClast = 1.25, Cmax = 1.25)
73-
#'
69+
#' # Equivalent boundaries
70+
#' lequi.tol <- c(AUCinf = 0.8, AUClast = 0.8, Cmax = 0.8)
71+
#' uequi.tol <- c(AUCinf = 1.25, AUClast = 1.25, Cmax = 1.25)
7472
#'
7573
#' # arms to be compared
7674
#' list_comparator <- list(EMA = c("SB2", "EUREF"),
@@ -89,8 +87,8 @@
8987
#' lognorm = TRUE, ncores = 1, nsim = 50, seed = 1234)
9088
#'
9189
#' @export
92-
sampleSize <- function(mu_list, varcov_list=NA, sigma_list=NA, cor_mat=NA,
93-
sigmaB =NA, Eper, Eco, rho=0,
90+
sampleSize <- function(mu_list, varcov_list = NA, sigma_list = NA, cor_mat = NA,
91+
sigmaB =NA, Eper, Eco, rho = 0,
9492
TAR=NA,
9593
arm_names=NA,
9694
ynames_list=NA,
@@ -111,15 +109,15 @@ sampleSize <- function(mu_list, varcov_list=NA, sigma_list=NA, cor_mat=NA,
111109
adjust="no",
112110
dropout = NA,
113111
nsim=5000,
114-
lower=2,
115-
upper=500,
116112
seed=1234,
117113
ncores=NA,
114+
optimization_method = "fast",
115+
lower=2,
116+
upper=500,
118117
step.power=6,
119118
step.up=TRUE,
120119
pos.side=FALSE,
121-
maxiter = 1000,
122-
optimization_method = "fast"
120+
maxiter = 1000
123121
){
124122

125123
# Assign default values for Eper and Eco
@@ -141,13 +139,6 @@ sampleSize <- function(mu_list, varcov_list=NA, sigma_list=NA, cor_mat=NA,
141139
}
142140
}
143141

144-
# Derive the names of the endpoints in each arm
145-
#
146-
# Example output for a trial with 2 treatments and 3 outcomes:
147-
# $SB2
148-
# [1] "AUCinf" "AUClast" "Cmax"
149-
# $EUREF
150-
# [1] "AUCinf" "AUClast" "Cmax"
151142
if (any(is.na(ynames_list))) {
152143

153144
# Try to derive the ynames from mu_list
@@ -173,6 +164,9 @@ sampleSize <- function(mu_list, varcov_list=NA, sigma_list=NA, cor_mat=NA,
173164
mu_list[[i]] <- mu
174165
}
175166

167+
# Check the sample size limits
168+
validate_sample_size_limits(lower = lower, upper = upper)
169+
176170

177171
# Varcov specfication
178172
if (any(is.na(varcov_list))) {
@@ -268,20 +262,8 @@ sampleSize <- function(mu_list, varcov_list=NA, sigma_list=NA, cor_mat=NA,
268262
len_mu <- lapply(mu_list,length)
269263
len_cvar <- lapply(varcov_list,ncol)
270264

271-
272-
273265
# test positive defined varcov
274-
positive <- function(x) {
275-
resp <- base::tryCatch({matrixcalc::is.positive.semi.definite(round(x,3))},
276-
error = function(e) {FALSE})
277-
}
278-
279-
280-
lis_pdef <- unlist(lapply(varcov_list, positive))
281-
282-
if (!all(lis_pdef)) {
283-
stop("All 'varcov' matrices must be symmetric and positive definite.")
284-
}
266+
validate_positive_definite(varcov_list)
285267

286268
# Define weights according to type of endpoint,i.e. primary, secondary
287269

@@ -596,3 +578,5 @@ sampleSize <- function(mu_list, varcov_list=NA, sigma_list=NA, cor_mat=NA,
596578
return(out)
597579

598580
}
581+
582+

R/validation.R

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#' @title Check Sample Size Limits
2+
#'
3+
#' @author
4+
#' Thomas Debray \email{[email protected]}
5+
#'
6+
#' @description Validates that the upper and lower limits are numeric and that the upper limit is greater than the lower limit.
7+
#'
8+
#' @param lower Numeric. The initial lower limit for the search range.
9+
#' @param upper Numeric. The initial upper limit for the search range.
10+
#'
11+
#' @return NULL. If the checks pass, the function returns nothing. If the checks fail, it stops execution with an error message.
12+
validate_sample_size_limits <- function(lower, upper) {
13+
14+
# Check if both lower and upper are numeric
15+
if (!is.numeric(upper) || !is.numeric(lower)) {
16+
stop("The upper and lower limits for the sample size must be numeric.")
17+
}
18+
19+
# Check if both lower and upper are integers
20+
if (lower != as.integer(lower) || upper != as.integer(upper)) {
21+
stop("The upper and lower limits for the sample size must be integers.")
22+
}
23+
24+
# Check lower is greater than 0
25+
if (lower <= 0) {
26+
stop("The lower limit for the sample size must be greater than 0.")
27+
}
28+
29+
# Check if upper is greater than or equal to lower
30+
if (upper < lower) {
31+
stop("The upper limit for the sample size must be greater than or equal to the lower limit.")
32+
}
33+
}
34+
35+
36+
#' @title Validate Positive Semi-Definite Matrices
37+
#'
38+
#' @author
39+
#' Thomas Debray \email{[email protected]}
40+
#'
41+
#' @description Validates that all matrices in a list are symmetric and positive semi-definite.
42+
#'
43+
#' @param varcov_list List of matrices. Each matrix is checked to ensure it is symmetric and positive semi-definite.
44+
#'
45+
#' @return NULL. If all matrices pass, the function returns nothing. If any matrix fails, it stops with an error message.
46+
validate_positive_definite <- function(varcov_list) {
47+
# Function to check if a matrix is positive semi-definite
48+
is_positive <- function(x) {
49+
resp <- tryCatch({
50+
matrixcalc::is.positive.semi.definite(round(x, 3))
51+
}, error = function(e) {
52+
FALSE
53+
})
54+
return(resp)
55+
}
56+
57+
# Apply the check to each matrix in the list
58+
positive_definite_list <- unlist(lapply(varcov_list, is_positive))
59+
60+
# Stop if any matrix is not positive semi-definite
61+
if (!all(positive_definite_list)) {
62+
stop("All matrices in 'varcov_list' must be symmetric and positive semi-definite.")
63+
}
64+
}

README.Rmd

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,9 @@ You can also install the development version of SimTOST from [GitHub](https://gi
3838
devtools::install_github("smartdata-analysis-and-statistics/SimTOST")
3939
```
4040

41-
## Example
41+
## Vignettes
4242

43-
The main features of this package is `sampleSize` function which can be used to calculate sample size for individual and multiple endpoints.
43+
The main features of this package is `sampleSize` function which can be used to calculate sample size for individual and multiple endpoints. Various worked examples are available as [vignettes](https://smartdata-analysis-and-statistics.github.io/SimTOST)
4444

45-
The example of using the functionality of this package can be found in these vignettes:
46-
47-
1. [Sample size calculation of individual endpoint]()
48-
2. [Sample size calculation of multiple endpoints]()
4945

5046

man/print.simss.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/sampleSize.Rd

Lines changed: 17 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/simParallelEndpoints.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/validate_positive_definite.Rd

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/validate_sample_size_limits.Rd

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)