Skip to content

Commit 00d8395

Browse files
committed
fix code
1 parent 5a3f57b commit 00d8395

24 files changed

+342
-144
lines changed

NAMESPACE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export(rct_beta_calibrate)
4040
export(rct_beta_power)
4141
export(rct_power_beta_binom_cpp_vec)
4242
export(run_bcts_app)
43+
export(sat_betabinom_calibrate)
44+
export(sat_betabinom_calibrate_exact)
4345
export(sat_betabinom_power)
4446
export(sat_betabinom_power_exact)
4547
export(sat_betabinom_type1)

R/RcppExports.R

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,11 @@ sat_betabinom_power <- function(B, p_t, n_t, M, threshold, prior = "flat", a_bas
153153
#'
154154
#' @param B Integer. Number of simulations.
155155
#' @param n_t Integer. Sample size of the treatment arm.
156+
#' @param p_null True response probability under H₀. Used to simulate Binomial outcomes.
156157
#' @param M Numeric. Decision threshold for θ (on probability scale, e.g., 0.6).
157158
#' @param threshold Posterior probability threshold γ (e.g., 0.95).
158-
#' @param prior Character string specifying the prior distribution.
159-
#' Options are:
160-
#' "flat" for a non-informative Beta(1,1) prior;
161-
#' "jeffreys" for the Jeffreys prior (Beta(0.5, 0.5));
162-
#' "beta" for a custom Beta(\code{a_base}, \code{b_base}) prior (user must provide \code{a_base} and \code{b_base}).
163-
#' @param a_base Alpha parameter for Beta prior (if prior = "beta").
164-
#' @param b_base Beta parameter for Beta prior (if prior = "beta").
159+
#' @param a_base Alpha parameter for Beta prior.
160+
#' @param b_base Beta parameter for Beta prior.
165161
#' @param show_progress Logical. Show progress in console?
166162
#'
167163
#' @return A list with \code{estimate} (type-I error), \code{mc_se}, \code{B}, and \code{rejections}.
@@ -174,8 +170,8 @@ sat_betabinom_power <- function(B, p_t, n_t, M, threshold, prior = "flat", a_bas
174170
#'
175171
#' @author Thomas Debray \email{[email protected]}
176172
#' @export
177-
sat_betabinom_type1 <- function(B, n_t, M, threshold, prior = "flat", a_base = 1, b_base = 1, show_progress = TRUE) {
178-
.Call(`_bcts_sat_betabinom_type1`, B, n_t, M, threshold, prior, a_base, b_base, show_progress)
173+
sat_betabinom_type1 <- function(B, n_t, p_null, M, threshold, a_base = 1, b_base = 1, show_progress = TRUE) {
174+
.Call(`_bcts_sat_betabinom_type1`, B, n_t, p_null, M, threshold, a_base, b_base, show_progress)
179175
}
180176

181177
#' @title Exact Type-I Error for Single-Arm Trial (Beta-Binomial)
@@ -192,37 +188,27 @@ sat_betabinom_type1 <- function(B, n_t, M, threshold, prior = "flat", a_base = 1
192188
#' @param M Numeric in \[0, 1\]. Decision threshold on the response rate, e.g., \code{M = 0.6}.
193189
#' @param threshold Numeric in \[0, 1\]. Posterior probability cutoff for declaring success,
194190
#' e.g., \code{threshold = 0.95}.
195-
#' @param prior Character string specifying the prior distribution.
196-
#' Options are:
197-
#' "flat" for a non-informative Beta(1,1) prior;
198-
#' "jeffreys" for the Jeffreys prior (Beta(0.5, 0.5));
199-
#' "beta" for a custom Beta(\code{a_base}, \code{b_base}) prior (user must provide \code{a_base} and \code{b_base})..
200-
#' @param a_base Numeric. Alpha parameter for the Beta prior (only used if \code{prior = "beta"}).
201-
#' @param b_base Numeric. Beta parameter for the Beta prior (only used if \code{prior = "beta"}).
191+
#' @param a_base Numeric. Alpha parameter for the Beta prior.
192+
#' @param b_base Numeric. Beta parameter for the Beta prior.
202193
#' @param p_null Optional. True response probability under the null hypothesis (e.g., \code{p_null = 0.6}).
203194
#' If not specified, defaults to \code{p_null = M} (boundary case).
204195
#'
205196
#' @return A named list with:
206197
#' \describe{
207198
#' \item{\code{estimate}}{Exact Type-I error (a number between 0 and 1).}
208199
#' \item{\code{mc_se}}{\code{NA_real_}, included for compatibility.}
209-
#' \item{\code{B}}{\code{NA_integer_}, included for compatibility.}
200+
#' \item{\code{B}}{\code{NA_real_}, included for compatibility.}
210201
#' \item{\code{rejections}}{\code{NA_integer_}, included for compatibility.}
211202
#' }
212203
#'
213204
#' @examples
214-
#' # Type-I error under flat prior at boundary
215-
#' sat_betabinom_type1_exact(n_t = 40, M = 0.65, threshold = 0.9, prior = "flat")
216-
#'
217-
#' # Type-I error under true p < M (frequentist view)
218-
#' sat_betabinom_type1_exact(n_t = 40, M = 0.65, threshold = 0.9,
219-
#' prior = "flat", p_null = 0.60)
205+
#' sat_betabinom_type1_exact(n_t = 40, M = 0.65, threshold = 0.9)
220206
#'
221207
#' @seealso \code{\link{sat_betabinom_type1}} for the simulation-based version.
222208
#'
223209
#' @author Thomas Debray \email{[email protected]}
224210
#' @export
225-
sat_betabinom_type1_exact <- function(n_t, M, threshold, prior = "flat", a_base = 1, b_base = 1, p_null = -1.0) {
226-
.Call(`_bcts_sat_betabinom_type1_exact`, n_t, M, threshold, prior, a_base, b_base, p_null)
211+
sat_betabinom_type1_exact <- function(n_t, M, threshold, a_base = 1, b_base = 1, p_null = -1.0) {
212+
.Call(`_bcts_sat_betabinom_type1_exact`, n_t, M, threshold, a_base, b_base, p_null)
227213
}
228214

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#' method = "cpp", show_progress = FALSE
3939
#' )
4040
#'
41+
#' @author Thomas Debray \email{[email protected]}
4142
#' @export
4243
rct_beta_power <- function(B = 10000,
4344
p_c, p_t, n_c, n_t,

R/rct_betabinom_sim.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#' )
3939
#' res$estimate
4040
#' res$ci
41+
#' @author Thomas Debray \email{[email protected]}
4142
#' @export
4243
bcts_power_betaBinom_conj <- function(B = 1000, p_c, p_t, n_c, n_t, M,
4344
threshold,

R/sat_betabinom_calibrate.R

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#' Calibrate posterior cutoff gamma and estimate power (Single-Arm, Beta–Binomial)
2+
#'
3+
#' Calibrates the posterior threshold `gamma` to control Type-I error at level `alpha`,
4+
#' and estimates Bayesian power using a conjugate Beta–Binomial model.
5+
#'
6+
#' @param alpha Target Type-I error rate (numeric in `(0,1)`).
7+
#' @param p_t True response probability in treatment group (numeric in `[0,1]`).
8+
#' @param n_t Sample size in treatment group (integer).
9+
#' @param M Decision threshold for theta (numeric in `[0,1]`).
10+
#' @param a_base,b_base Numeric. Hyperparameters of the Beta prior (used when `prior = "beta"`).
11+
#' @param tol Absolute tolerance for calibration convergence.
12+
#' @param seed RNG seed.
13+
#' @param show_progress Logical. Whether to display progress bars.
14+
#'
15+
#' @return A list with components:
16+
#' - `gamma`: Calibrated posterior probability threshold.
17+
#' - `type1`: Estimated Type-I error at `gamma`.
18+
#' - `power`: Estimated Bayesian power at `gamma`.
19+
#' - `settings`: Echo of input parameters.
20+
#'
21+
#' @examples
22+
#' \donttest{
23+
#' res <- sat_beta_calibrate(
24+
#' alpha = 0.10, p_t = 0.80, n_t = 40, M = 0.65,
25+
#' prior = "flat"
26+
#' )
27+
#' res$gamma
28+
#' res$power
29+
#' }
30+
#' @author Thomas Debray \email{[email protected]}
31+
#' @export
32+
sat_betabinom_calibrate <- function(alpha = 0.10,
33+
p_t = 0.80,
34+
n_t = 40,
35+
M = 0.65,
36+
prior = c("flat", "jeffreys", "beta"),
37+
a_base = 1, b_base = 1,
38+
tol = 0.002,
39+
seed = 123,
40+
show_progress = FALSE) {
41+
prior <- match.arg(prior)
42+
43+
cal <- sat_betabinom_find_gamma(
44+
alpha = alpha, p_c = M, M = M,
45+
n_t = n_t,
46+
prior = prior,
47+
prior_args = list(a_base = a_base, b_base = b_base),
48+
seed = seed,
49+
show_progress = show_progress,
50+
progress_fun = pf,
51+
calibrate_on = calibrate_on
52+
)
53+
54+
55+
power <- sat_betabinom_power(
56+
p_t = p_t, n_t = n_t, M = M,
57+
threshold = cal$gamma,
58+
prior = prior, a_base = a_base, b_base = b_base,
59+
show_progress = show_progress,
60+
method = "exact"
61+
)
62+
63+
type1 <- sat_betabinom_type1(
64+
n_t = n_t, M = M,
65+
threshold = cal$gamma,
66+
prior = prior, a_base = a_base, b_base = b_base,
67+
show_progress = show_progress,
68+
method = "exact"
69+
)
70+
71+
out <- list(
72+
gamma = cal$gamma,
73+
type1 = type1,
74+
power = power,
75+
settings = list(
76+
alpha = alpha, p_t = p_t, n_t = n_t, M = M,
77+
prior = prior, a_base = a_base, b_base = b_base,
78+
B_cal = B_cal, B_power = B_power,
79+
tol = tol, seed = seed
80+
)
81+
)
82+
class(out) <- "bcts_sat"
83+
return(out)
84+
}
85+
86+
#' Calibrate posterior threshold gamma to control Type-I error (exact, SAT)
87+
#'
88+
#' For single-arm trials with Beta–Binomial conjugate updates, computes the Type-I error
89+
#' exactly for all possible posterior thresholds, and selects the largest gamma such that
90+
#' Type-I error is below or equal to a target alpha.
91+
#'
92+
#' @param alpha Target Type-I error rate (e.g. 0.10)
93+
#' @param n_t Sample size in treatment arm
94+
#' @param M Decision margin (null threshold)
95+
#' @param a_base,b_base Prior Beta(a,b) parameters (default: 1,1)
96+
#'
97+
#' @return An object of class `"bcts_calibration"` with components: `gamma`, `type1`, `trace`, and `settings`.
98+
#' @author Thomas Debray \email{[email protected]}
99+
#' @export
100+
sat_betabinom_calibrate_exact <- function(alpha = 0.10,
101+
n_t,
102+
M,
103+
a_base = 1,
104+
b_base = 1,
105+
grid_n = 1000) {
106+
107+
# Step 1: Grid of gamma values (search over [0,1])
108+
gamma_vals <- seq(1, 0, length.out = grid_n) # from most to least conservative
109+
110+
# Step 2: Evaluate type-I error at each gamma
111+
type1_vals <- vapply(gamma_vals, function(g) {
112+
.Call(`_bcts_sat_betabinom_type1_exact`,
113+
n_t, M, g, a_base, b_base, -1.0)
114+
}, numeric(1))
115+
116+
# Step 3: Build trace table
117+
trace <- data.frame(
118+
gamma = gamma_vals,
119+
type1 = type1_vals
120+
)
121+
122+
# Step 4: Select gamma where type-I is just below alpha
123+
eligible <- trace$type1 <= alpha
124+
if (!any(eligible)) {
125+
stop("Calibration failed: Type-I error is above target alpha at all gamma values.")
126+
}
127+
128+
best_idx <- which.max(trace$gamma[eligible]) # most liberal gamma ≤ alpha
129+
best_gamma <- trace$gamma[eligible][best_idx]
130+
best_type1 <- trace$type1[eligible][best_idx]
131+
132+
out <- list(
133+
gamma = best_gamma,
134+
type1 = best_type1,
135+
trace = trace
136+
)
137+
class(out) <- "bcts_calibration"
138+
139+
return(out)
140+
}

R/sat_betabinom_power.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#' p_t = 0.75, n_t = 35, M = 0.60,
3030
#' threshold = 0.95, prior = "flat", method = "exact"
3131
#' )
32+
#' @author Thomas Debray \email{[email protected]}
3233
#'
3334
#' @export
3435
sat_betabinom_power <- function(B = 10000, p_t, n_t, M, threshold,

R/sat_betabinom_type1.R

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@
1212
#' @param M Numeric. Decision threshold (also used as null value if \code{p_null} not specified).
1313
#' @param threshold Numeric. Posterior probability threshold for declaring success, e.g., \code{0.95}.
1414
#' @param prior Prior type: one of:
15+
#' - \code{"beta"} (default) Use custom Beta(\code{a_base}, \code{b_base}) prior..
1516
#' - \code{"flat"} for a non-informative Beta(1,1) prior;
1617
#' - \code{"jeffreys"} for the Jeffreys prior Beta(0.5, 0.5);
17-
#' - \code{"beta"} for a custom Beta(\code{a_base}, \code{b_base}) prior.
1818
#' @param a_base Alpha of Beta prior (only used if \code{prior = "beta"}).
1919
#' @param b_base Beta of Beta prior (only used if \code{prior = "beta"}).
2020
#' @param p_null Optional numeric. True response rate under the null hypothesis (default is \code{M}).
2121
#' Only used when \code{method = "exact"}.
22-
#' @param n_draws Ignored. Kept for backward compatibility.
2322
#' @param show_progress Logical. Show progress bar during simulation (only relevant for \code{method = "simulate"}).
2423
#' @param method Character. Either \code{"exact"} (default) or \code{"simulate"}.
2524
#'
@@ -43,27 +42,40 @@
4342
#'
4443
#' @seealso \code{\link{sat_betabinom_power}}, \code{\link{sat_betabinom_type1_exact}}
4544
#'
45+
#' @author Thomas Debray \email{[email protected]}
4646
#' @export
4747
sat_betabinom_type1 <- function(B = 10000, n_t, M, threshold,
48-
prior = c("flat", "jeffreys", "beta"),
48+
prior = c("beta", "flat", "jeffreys"),
4949
a_base = 1, b_base = 1,
5050
p_null = NULL,
51-
n_draws = 2000, # ignored
5251
show_progress = TRUE,
5352
method = c("exact", "simulate")) {
5453
prior <- match.arg(prior)
5554
method <- match.arg(method)
5655

56+
# Convert prior to a_base and b_base
57+
if (prior == "flat") {
58+
a_base <- 1
59+
b_base <- 1
60+
} else if (prior == "jeffreys") {
61+
a_base <- 0.5
62+
b_base <- 0.5
63+
} else if (prior == "beta") {
64+
# leave a_base and b_base as provided
65+
} else {
66+
stop("Invalid prior. Must be one of 'flat', 'jeffreys', or 'beta'.")
67+
}
68+
69+
# Default p_null = M if not specified
70+
if (is.null(p_null)) p_null <- M
71+
5772
if (method == "simulate") {
5873
.Call(`_bcts_sat_betabinom_type1`,
59-
B, n_t, M, threshold,
60-
prior, a_base, b_base, show_progress)
74+
B, n_t, p_null, M, threshold,
75+
a_base, b_base, show_progress)
6176
} else {
62-
# Default p_null = M if not specified
63-
if (is.null(p_null)) p_null <- M
64-
6577
.Call(`_bcts_sat_betabinom_type1_exact`,
6678
n_t, M, threshold,
67-
prior, a_base, b_base, p_null)
79+
a_base, b_base, p_null)
6880
}
6981
}

inst/app/modules/singlearm/mod_singlearm_ui.R

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,18 @@ mod_singlearm_server <- function(id) {
127127
show_progress = FALSE
128128
)
129129

130-
# Frequentist power
131-
crit_val <- qbinom(gamma, size = nt, prob = M) + 1
132-
freq_power <- 1 - pbinom(crit_val - 1, size = nt, prob = pt)
133-
134-
135-
# Frequentist type-I error
136-
freq_type1 <- 1 - gamma
130+
# Optional frequentist comparison
131+
freq_power <- freq_type1 <- NA
132+
decision_mode <- input[["crit_sa-decision_mode_sa"]]
133+
134+
if (!is.null(decision_mode) && decision_mode == "alpha") {
135+
alpha <- input[["crit_sa-alpha_sa"]] / 100 # slider is in percent
136+
if (!is.null(alpha)) {
137+
crit_val <- qbinom(1 - alpha, size = nt, prob = M)
138+
freq_power <- 1 - pbinom(crit_val - 1, size = nt, prob = pt)
139+
freq_type1 <- 1 - pbinom(crit_val - 1, size = nt, prob = M)
140+
}
141+
}
137142

138143
list(
139144
power = power_res,
@@ -207,11 +212,11 @@ mod_singlearm_server <- function(id) {
207212
cat(sprintf("Estimated power: %.2f%%\n", 100 * power_res$estimate))
208213
cat(sprintf("Estimated Type-I error: %.2f%%\n", 100 * type1_res$estimate))
209214

210-
cat("\n")
211-
212-
cat("FREQUENTIST COMPARISON\n")
213-
cat(sprintf("Frequentist power: %.2f%%\n", 100 * freq_power))
214-
cat(sprintf("Frequentist Type-I error: %.2f%%\n", 100 * freq_type1))
215+
if (!is.na(res$freq_power) && !is.na(res$freq_type1)) {
216+
cat("\nFREQUENTIST COMPARISON\n")
217+
cat(sprintf("Frequentist power: %.2f%%\n", 100 * res$freq_power))
218+
cat(sprintf("Frequentist Type-I error: %.2f%%\n", 100 * res$freq_type1))
219+
}
215220
})
216221

217222
output$freq_binom_plot <- renderPlot({

man/bcts_power_betaBinom_conj.Rd

Lines changed: 3 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)