|
38 | 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 | 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 | 40 | #' @param maxiter Integer. Maximum number of iterations allowed for finding the sample size. Defaults to 1000. Used only when `optimization_method` is `"fast"`. |
| 41 | +#' @param verbose Logical. If `TRUE`, the function displays progress and informational messages during execution. Defaults to `FALSE`. |
41 | 42 | #' @return An object simss that contains the following elements : |
42 | 43 | #' \describe{ |
43 | 44 | #' \item{"response"}{ array with the sample sizes for each arm and aproximated achieved power with confidence intervals} |
@@ -117,46 +118,37 @@ sampleSize <- function(mu_list, varcov_list = NA, sigma_list = NA, cor_mat = NA, |
117 | 118 | step.power=6, |
118 | 119 | step.up=TRUE, |
119 | 120 | pos.side=FALSE, |
120 | | - maxiter = 1000 |
| 121 | + maxiter = 1000, verbose = FALSE |
121 | 122 | ){ |
122 | 123 |
|
123 | 124 | # Assign default values for Eper and Eco |
124 | | - if (missing(Eper)) Eper <- c(0, 0) |
125 | | - if (missing(Eco)) Eco <- c(0, 0) |
| 125 | + if (missing(Eper)) { |
| 126 | + Eper <- c(0, 0) |
| 127 | + info_msg("Eper not provided. Defaulting to c(0, 0).", verbose) |
| 128 | + } |
| 129 | + if (missing(Eco)) { |
| 130 | + Eco <- c(0, 0) |
| 131 | + info_msg("Eco not provided. Defaulting to c(0, 0).", verbose) |
| 132 | + } |
126 | 133 |
|
127 | 134 | # is mu provided? |
128 | 135 | if (all(is.na(mu_list))) { |
129 | 136 | stop("mu_list must be provided") |
130 | 137 | } |
131 | 138 |
|
132 | | - # Parameters endpoints ----- |
133 | | - n <- length(mu_list) # number of arms |
134 | | - |
135 | | - # Derive the arm names |
136 | | - if (any(is.na(arm_names))) { |
137 | | - if (!is.null(names(mu_list))) { |
138 | | - arm_names <- names(mu_list) |
139 | | - } |
140 | | - } |
141 | | - |
142 | | - if (any(is.na(ynames_list))) { |
143 | | - |
144 | | - # Try to derive the ynames from mu_list |
145 | | - ynames_list <- lapply(mu_list, function(x) names(x)) |
146 | | - |
147 | | - if (length(names(ynames_list)) == 0 | any(sapply(ynames_list, is.null))) { |
148 | | - #warning("no all endpoints names provided for each arm, so arbitrary names are assigned") |
149 | | - ynames_list <- lapply(mu_list, function(x) paste0("y", 1:length(x))) |
150 | | - } |
151 | | - } |
| 139 | + # Derive the Number of Arms |
| 140 | + n <- length(mu_list) |
152 | 141 |
|
| 142 | + # Derive the Arm Names |
| 143 | + arm_names <- derive_arm_names(arm_names = arm_names, mu_list = mu_list, |
| 144 | + verbose = verbose) |
153 | 145 |
|
154 | | - # Treatment allocation rate |
155 | | - if (any(is.na(TAR))) { |
156 | | - TAR <- rep(1,n) |
157 | | - } |
| 146 | + # Derive the Endpoint Names |
| 147 | + ynames_list <- derive_endpoint_names(ynames_list = ynames_list, |
| 148 | + mu_list = mu_list, verbose = verbose) |
158 | 149 |
|
159 | | - TAR_list <- as.list(TAR) |
| 150 | + # Derive the Treatment Allocation Rate |
| 151 | + TAR_list <- derive_allocation_rate(TAR = TAR, n_arms = n, verbose = verbose) |
160 | 152 |
|
161 | 153 |
|
162 | 154 | for (i in 1:n) { |
@@ -281,11 +273,6 @@ sampleSize <- function(mu_list, varcov_list = NA, sigma_list = NA, cor_mat = NA, |
281 | 273 | } |
282 | 274 | names(weight_seq) <- uynames |
283 | 275 |
|
284 | | - # Give to list the arm names |
285 | | - if (any(is.na(arm_names))) { |
286 | | - arm_names <- paste0("A",rep(1:n)) |
287 | | - } |
288 | | - |
289 | 276 | #if (len_mu[[1]] == 1){ |
290 | 277 | # mu_list <- lapply(mu_list,FUN = function(x){array(unlist(x))}) |
291 | 278 | # varcov_list <- lapply(varcov_list,FUN = function(x){matrix(unlist(x))})} |
@@ -470,13 +457,16 @@ sampleSize <- function(mu_list, varcov_list = NA, sigma_list = NA, cor_mat = NA, |
470 | 457 | } |
471 | 458 |
|
472 | 459 |
|
473 | | - # Save endopoints related information on a parameter list |
| 460 | + # Save endpoints related information on a parameter list |
474 | 461 |
|
475 | 462 | param <- list(mu = mu_list, varcov = varcov_list, sigmaB = sigmaB, |
476 | 463 | TAR_list = TAR_list, type_y = type_y, weight_seq = weight_seq, |
477 | 464 | arm_names = arm_names, ynames_list = ynames_list, |
478 | 465 | list_comparator = list_comparator, |
479 | | - list_y_comparator = list_y_comparator,sigmaB = sigmaB, |
| 466 | + list_y_comparator = list_y_comparator, |
| 467 | + list_lequi.tol = list_lequi.tol, |
| 468 | + list_uequi.tol = list_uequi.tol, |
| 469 | + sigmaB = sigmaB, |
480 | 470 | Eper = Eper, Eco = Eco) |
481 | 471 |
|
482 | 472 | # Parameters related to design ---- |
@@ -579,4 +569,100 @@ sampleSize <- function(mu_list, varcov_list = NA, sigma_list = NA, cor_mat = NA, |
579 | 569 |
|
580 | 570 | } |
581 | 571 |
|
| 572 | +#' Derive or Assign Arm Names |
| 573 | +#' |
| 574 | +#' This function checks if `arm_names` is provided. If `arm_names` is missing, it attempts to derive names |
| 575 | +#' from `mu_list`. If `mu_list` does not contain names, it assigns default names ("A1", "A2", etc.) to each arm. |
| 576 | +#' Informational messages are displayed if `verbose` is set to `TRUE`. |
| 577 | +#' |
| 578 | +#' @author Thomas Debray \email{[email protected]} |
| 579 | +#' |
| 580 | +#' @param arm_names Optional vector of arm names. |
| 581 | +#' @param mu_list Named list of means per treatment arm, from which arm names may be derived. |
| 582 | +#' @param verbose Logical, if `TRUE`, displays messages about the derivation process. |
| 583 | +#' |
| 584 | +#' @return A vector of arm names. |
| 585 | +derive_arm_names <- function(arm_names, mu_list, verbose = FALSE) { |
| 586 | + |
| 587 | + # Check if arm_names is missing and attempt to derive from mu_list |
| 588 | + if (any(is.na(arm_names))) { |
| 589 | + if (!is.null(names(mu_list))) { |
| 590 | + arm_names <- names(mu_list) |
| 591 | + info_msg(paste("Arm names derived from mu_list: ", paste(arm_names, collapse = ", ")), verbose) |
| 592 | + } else { |
| 593 | + arm_names <- paste0("A",seq(mu_list)) |
| 594 | + info_msg(paste("Arm names not provided and could not be derived from mu_list. Assigning default names: ", paste(arm_names, collapse = ", ")), verbose) |
| 595 | + } |
| 596 | + } else { |
| 597 | + info_msg(paste("Using user-provided arm names: ", paste(arm_names, collapse = ", ")), verbose) |
| 598 | + } |
| 599 | + |
| 600 | + return(arm_names) |
| 601 | +} |
| 602 | + |
| 603 | +#' Derive Endpoint Names |
| 604 | +#' |
| 605 | +#' @author Thomas Debray \email{[email protected]} |
| 606 | +#' |
| 607 | +#' This function derives endpoint names (`ynames_list`) from `mu_list` if `ynames_list` |
| 608 | +#' is missing. If `ynames_list` is already provided, it confirms the names to the user when |
| 609 | +#' `verbose` is set to `TRUE`. |
| 610 | +#' |
| 611 | +#' @param ynames_list Optional list of vectors with endpoint names for each arm. |
| 612 | +#' @param mu_list Named list of means per treatment arm, where names can be used as endpoint names. |
| 613 | +#' @param verbose Logical, if `TRUE`, displays messages about the derivation process. |
| 614 | +#' |
| 615 | +#' @return A list of endpoint names for each arm. |
| 616 | +derive_endpoint_names <- function(ynames_list, mu_list, verbose = FALSE) { |
| 617 | + |
| 618 | + # Check if ynames_list is missing and attempt to derive from mu_list |
| 619 | + if (any(is.na(ynames_list))) { |
| 620 | + |
| 621 | + # Try to derive the ynames from mu_list |
| 622 | + ynames_list <- lapply(mu_list, function(x) names(x)) |
| 623 | + info_msg("Attempting to derive endpoint names (ynames_list) from mu_list.", verbose) |
| 624 | + |
| 625 | + # Check if ynames were successfully derived |
| 626 | + if (length(names(ynames_list)) == 0 || any(sapply(ynames_list, is.null))) { |
| 627 | + info_msg("Not all endpoint names were provided. Assigning arbitrary names (y1, y2, etc.) to endpoints for each arm.", verbose) |
| 628 | + ynames_list <- lapply(mu_list, function(x) paste0("y", 1:length(x))) |
| 629 | + } else { |
| 630 | + info_msg("Endpoint names derived from mu_list.", verbose) |
| 631 | + } |
| 632 | + } else { |
| 633 | + info_msg("Using user-provided endpoint names (ynames_list).", verbose) |
| 634 | + } |
| 635 | + |
| 636 | + return(ynames_list) |
| 637 | +} |
| 638 | + |
| 639 | +#' Derive Treatment Allocation Rate (TAR) |
| 640 | +#' |
| 641 | +#' This function checks if `TAR` (treatment allocation rate) is provided. If `TAR` is missing, it assigns a default |
| 642 | +#' equal allocation rate across all arms. It then converts `TAR` to a list format for further use. |
| 643 | +#' Informational messages are displayed if `verbose` is set to `TRUE`. |
| 644 | +#' |
| 645 | +#' @author Thomas Debray \email{[email protected]} |
| 646 | +#' |
| 647 | +#' @param TAR Optional numeric vector specifying the allocation rate for each treatment arm. If missing, a default equal allocation rate is assigned. |
| 648 | +#' @param n_arms Integer specifying the number of treatment arms. |
| 649 | +#' @param verbose Logical, if `TRUE`, displays messages about the status of `TAR` derivation or assignment. |
| 650 | +#' |
| 651 | +#' @return A list representing the treatment allocation rate for each arm. |
| 652 | +derive_allocation_rate <- function(TAR, n_arms, verbose = FALSE) { |
| 653 | + |
| 654 | + # Check if TAR is missing and assign default if necessary |
| 655 | + if (any(is.na(TAR))) { |
| 656 | + TAR <- rep(1, n_arms) # Default equal allocation across all arms |
| 657 | + info_msg(paste("TAR not provided. Assigning equal allocation rate across all arms: ", paste(TAR, collapse = ":")), verbose) |
| 658 | + } else { |
| 659 | + info_msg(paste("Using user-provided TAR: ", paste(TAR, collapse = ":")), verbose) |
| 660 | + } |
| 661 | + |
| 662 | + # Convert TAR to list format |
| 663 | + TAR_list <- as.list(TAR) |
| 664 | + |
| 665 | + return(TAR_list) |
| 666 | +} |
| 667 | + |
582 | 668 |
|
0 commit comments