
Create an Optimal Conditional Error Design
Source:R/f_design_optimal_user.R
getDesignOptimalConditionalError.RdThis function returns a design object which contains all
important parameters for the specification of the optimal conditional
error function.
The returned object is of class TrialDesignOptimalConditionalError
and can be passed to other package functions.
Usage
getDesignOptimalConditionalError(
alpha,
efficacyBounds,
futilityBounds,
conditionalPower = NA_real_,
thetaH1 = NA_real_,
minThetaH1 = NA_real_,
maxThetaH1 = Inf,
useInterimEstimate = TRUE,
firstStageInformation,
likelihoodRatioDistribution,
minInformationPerStage = 0,
maxInformationPerStage = Inf,
minConditionalError = 0,
maxConditionalError = 1,
conditionalPowerFunction = NULL,
minLevelConstant = 0,
maxLevelConstant = 10,
enforceMonotonicity = TRUE,
efficacyBoundsScale = "pValue",
futilityBoundsScale = "pValue",
nonCentralityParameterH1 = NULL,
minNonCentralityParameterH1 = NULL,
maxNonCentralityParameterH1 = Inf,
...
)Arguments
- alpha
The overall type I error rate \(\alpha\) of the design. Must be a numeric value between 0 and 1.
- efficacyBounds
Stage 1 efficacy boundary \(\alpha_1\) (p-value scale). Must be a numeric value between 0 and 1. Should be smaller than
futilityBounds.- futilityBounds
Binding stage 1 futility boundary \(\alpha_0\) (p-value scale). Must be a numeric value between 0 and 1. Should be greater than
efficacyBounds. SpecifyfutilityBounds=1to disable early stopping for futility.- conditionalPower
The target conditional power \(CP\) of the design. Must be a numeric scalar strictly between 0 and 1. Takes precedence over
conditionalPowerFunction.- thetaH1
Fixed effect assumption at which the conditional power should be achieved, expressed on the mean difference scale. Is only used if
useInterimEstimate=FALSE. Must be a numeric value greater than 0.- minThetaH1
The minimum for an interim estimate of the treatment effect, specified on the mean difference scale. If the interim estimate (on the mean difference scale) yields a value smaller than
minThetaH1,minThetaH1is used for it. Is only used ifuseInterimEstimate=TRUE. Must be a numeric value.- maxThetaH1
The maximum for an interim estimate of the treatment effect, specified on the mean difference scale. If the interim estimate (on the mean difference scale) yields a value larger than
maxThetaH1,maxThetaH1is used for it. Is only used ifuseInterimEstimate=TRUE. Must be a numeric value. Default value isInf, i.e., no upper restriction.- useInterimEstimate
Logical. Defines whether or not an interim estimate should be used for conditional power. If
TRUE, a lower cut-off for the interim estimate must be specified byminThetaH1orminNonCentralityParameterH1. An upper cut-off may also be specified bymaxThetaH1ormaxNonCentralityParameterH1. IfFALSE, the fixed effect size must be specified bythetaH1ornonCentralityParameterH1.- firstStageInformation
Information of the first stage of the trial. Must be a positive numeric value.
- likelihoodRatioDistribution
The distribution to be used for the effect size of the likelihood ratio in the optimal conditional error function. Options are
"fixed", "normal", "exp", "unif", "maxlr"for fixed effect size, normally distributed, exponentially distributed, uniformly distributed prior of the effect size and maximum likelihood ratio, respectively. Each case requires different additional specifications:likelihoodRatioDistribution="fixed"uses one (or more) fixed effect sizes for the likelihood ratio and requires the parameterthetaLRwhich provides the mean difference under which to calculate the likelihood ratio. IfthetaLRcontains multiple values, they may be weighted using an additional argumentweightsLR. OmittingweightsLRautomatically leads to equal weighting.likelihoodRatioDistribution="normal"uses a normal prior for the effect size and requires parametersthetaLRandstDevLRfor the mean and standard deviation of the normal distribution (both on mean difference scale).likelihoodRatioDistribution="exp"uses an exponential prior for the effect size and requires the parameterkappaLRwhich specifies the rate on the non-centrality scale divided bysqrt(firstStageInformation). The mean effect on the mean difference scale is1 / (kappaLR * firstStageInformation).likelihoodRatioDistribution="unif"uses a uniform prior for the effect size and requires the specification ofmaxThetaLR, which is the maximum of the support for the uniform likelihood ratio distribution (on the mean difference scale).likelihoodRatioDistribution="maxlr"estimates the non-centrality parameter to be used for the likelihood ratio from the data. No additional parameters must be specified.
- minInformationPerStage
The minimum additional information allowed in stage two. A single numeric value; does not apply to firstStageInformation. Default value is
0, i.e., no restriction.- maxInformationPerStage
The maximum additional information allowed in stage two. A single numeric value; does not apply to firstStageInformation. Default value is
Inf, i.e., no restriction.- minConditionalError
Lower boundary for the optimal conditional error function. Default 0 (no restriction).
- maxConditionalError
Upper boundary for the optimal conditional error function. Default value is 1, however, the optimal conditional error function is inherently bounded by the conditional power.
- conditionalPowerFunction
A function accepting a single first-stage p-value and returning a numeric scalar strictly between 0 and 1. The function is evaluated separately for each p-value. This function should not be increasing in the first-stage p-value, otherwise monotonicity issues may occur. With a conditional power function, the resulting conditional error function is not necessarily optimal for expected second-stage information.
- minLevelConstant
The minimum of the interval on which the value for the level constant should be searched. Default value is 0.
- maxLevelConstant
The maximum of the interval on which the value for the level constant should be searched. Default value is 10.
- enforceMonotonicity
Logical. Determines whether or not the optimal conditional error function should automatically be modified to be non-increasing. Default is
TRUE.- efficacyBoundsScale, futilityBoundsScale
Scale of the interim boundaries. Currently only
"pValue"is supported. These are p-value cutoffs, not the test-statistic boundaries used by conventional group sequential designs.- nonCentralityParameterH1
Fixed conditional-power effect on the non-centrality scale; alternative to
thetaH1whenuseInterimEstimate = FALSE.- minNonCentralityParameterH1, maxNonCentralityParameterH1
Lower and upper limits for the interim effect on the non-centrality scale; alternatives to
minThetaH1andmaxThetaH1whenuseInterimEstimate = TRUE. Non-centrality equals the mean difference timessqrt(firstStageInformation). Mean-difference arguments take precedence when both scales are supplied. The default upper limit isInf.- ...
Distribution parameters
thetaLR,weightsLR,stDevLR,kappaLR, andmaxThetaLR, as described under Likelihood ratio distribution.
Value
An object of class TrialDesignOptimalConditionalError,
which can be passed to getConditionalError(), getStageInformation(),
and getDesignCharacteristics().
This adaptive design is not interchangeable with a conventional TrialDesign.
Details
The design object contains the information required to determine the specific setting of the optimal conditional error function and can be passed to other package functions. From the given user specifications, the constant to achieve level condition for control of the overall type I error rate as well as the constants to ensure a non-increasing optimal CEF (if required) are automatically calculated.
Hypotheses and trial decisions
The one-sided hypotheses are \(H_0: \Delta \leq 0\) versus
\(H_1: \Delta > 0\). With a first-stage p-value \(p_1\), stop for
efficacy if \(p_1 \leq \alpha_1\) and \(\alpha_1 > 0\); stop for
futility if \(p_1 > \alpha_0\). Futility is binding: continuing beyond
this boundary is not part of the calibrated design. In the continuation
region, reject at stage two if its p-value is no larger than
getConditionalError(). The second-stage p-value must be based on
the new, independent second-stage data, not the cumulative data.
Setting efficacyBounds = 0 disables early efficacy and
futilityBounds = 1 disables early futility.
Here, \(\alpha_1\) denotes efficacyBounds and \(\alpha_0\) denotes
futilityBounds; both are single interim cutoffs on the p-value scale.
The calibration satisfies
$$\alpha = \alpha_1 + \int_{\alpha_1}^{\alpha_0} \alpha_2(p_1) \, dp_1.$$
Target conditional power refers to a specified planning effect after
continuation; it is not the overall power returned by getDesignCharacteristics().
Likelihood ratio distribution
To calculate the optimal conditional error function, an assumption about
the true parameter under which the second-stage information is to be
minimised is required.
Various options are available and can be specified via the argument
likelihoodRatioDistribution:
likelihoodRatioDistribution="fixed": calculates the likelihood ratio for a fixed \(\Delta\). The non-centrality parameter of the likelihood ratio \(\vartheta\) is then computed asthetaLR*sqrt(firstStageInformation)and the likelihood ratio is calculated as: $$l(p_1) = e^{\Phi^{-1}(1-p_1)\vartheta - \vartheta^2/2}.$$thetaLRmay also contain multiple elements, in which case a weighted likelihood ratio is calculated for the given values. Unless positive weights that sum to 1 are provided by the argumentweightsLR, equal weights are assumed.likelihoodRatioDistribution="normal": calculates the likelihood ratio for a normally distributed prior of \(\vartheta\) with meanthetaLR*sqrt(firstStageInformation)(\(\mu\)) and standard deviationstDevLR*sqrt(firstStageInformation)(\(\sigma\)). The parametersthetaLRandstDevLRmust be specified on the mean difference scale. $$l(p_1) = (1+\sigma^2)^{-\frac{1}{2}}\cdot e^{-(\mu/\sigma)^2/2 + (\sigma\Phi^{-1}(1-p_1) + \mu/\sigma)^2 / (2\cdot (1+\sigma^2))}$$likelihoodRatioDistribution="exp": calculates the likelihood ratio for an exponentially distributed prior of \(\vartheta\) with ratekappaLR*sqrt(firstStageInformation)(\(\eta\)). The likelihood ratio is then calculated as: $$l(p_1) = \eta \cdot \sqrt{2\pi} \cdot e^{(\Phi^{-1}(1-p_1)-\eta)^2/2} \cdot \Phi(\Phi^{-1}(1-p_1)-\eta)$$likelihoodRatioDistribution="unif": calculates the likelihood ratio for a uniformly distributed prior of \(\vartheta\) on the support \([0, \Delta\cdot\sqrt{I_1}]\), where \(\Delta\) is specified asmaxThetaLRand \(I_1\) is thefirstStageInformation. $$l(p_1) = \frac{\sqrt{2\pi}}{\Delta\cdot\sqrt{I_1}} \cdot e^{\Phi^{-1}(1-p_1)^2/2} \cdot (\Phi(\Delta\cdot\sqrt{I_1} - \Phi^{-1}(1-p_1))-p_1)$$likelihoodRatioDistribution="maxlr": the non-centrality parameter \(\vartheta\) is estimated from the data and no additional parameters must be specified. The likelihood ratio is estimated from the data as: $$l(p_1) = e^{max(0, \Phi^{-1}(1-p_1))^2/2}$$ The maximum likelihood ratio is always restricted to effect sizes \(\vartheta \geq 0\) (corresponding to \(p_1 \leq 0.5\)).
Effect for conditional power
For the treatment effect at which the target conditional power should be
achieved, either a fixed effect or an interim estimate can be used.
The planning effect thetaH1 need not equal thetaLR: the former sets the
conditional power target, whereas the latter specifies the effect or mixture
under which expected second-stage information is minimised.
The usage of a fixed effect is indicated by setting useInterimEstimate=FALSE,
in which case the fixed effect is provided by thetaH1 on the mean difference scale.
For an interim estimate, specified by useInterimEstimate=TRUE,
a lower cut-off for the interim estimate must be provided, by minThetaH1
on the mean difference scale.
In addition, an upper limit of the estimate may be analogously provided by
maxThetaH1. These effects may alternatively be specified on the
non-centrality parameter scale as
nonCentralityParameterH1, minNonCentralityParameterH1, and
maxNonCentralityParameterH1.
Sample size and information
The first-stage information of the trial design must be specified to allow for
calculations between the mean difference and non-centrality parameter scale.
It is provided to the design object via firstStageInformation.
Listed below are some examples for the calculation between information (\(I_1\)) and sample size:
One-sample z-test with \(n\) total patients: \(I_1 = \frac{n}{\sigma^2}\), where \(\sigma^2\) is the variance of an individual observation
Balanced two-sample z-test with \(n_1\) patients per group: \(I_1 = \frac{1}{2}\cdot\frac{n_1}{\sigma^2}\), where \(\sigma^2\) is the common variance
General two-sample z-test with \(n_1\), \(n_2\) patients per group: \(I_1 = 1/(\frac{\sigma_1^2}{n_1}+\frac{\sigma_2^2}{n_2})\), where \(\sigma_1^2\), \(\sigma_2^2\) are the group-wise variances
Monotonicity
By default, the function Q (likelihood ratio divided by the squared effect)
is transformed to be non-increasing in the first-stage p-value. For constant
conditional power this yields a non-increasing conditional error function.
A conditional power callback combined with interim effect estimates and
information constraints can still produce a non-monotone conditional error
function; enforceMonotonicity does not guarantee monotonicity in that setting.
The necessary intervals and constants for the transformation are calculated by
an internal monotonisation routine.
Although not recommended for the operating characteristics of the design,
the transformation may be omitted by setting enforceMonotonicity=FALSE.
Constraints
In some applications, it may be feasible to restrict the optimal conditional
error function by a lower and/or upper limit.
These constraints can be directly implemented on the function by using the
arguments minConditionalError and maxConditionalError.
By default, minConditionalError=0 and maxConditionalError=1,
i.e., no constraints are applied.
The constraints may also be specified on the second-stage information via
minInformationPerStage and maxInformationPerStage.
If both minConditionalError and maxInformationPerStage
respectively maxConditionalError and minInformationPerStage
are provided, both constraints will be applied.
Set these constraints when creating the design, so that calibration accounts
for them. For fixed \(\Delta_1\) and conditional power \(CP\),
an upper information bound corresponds to the lower conditional error bound
\(\Phi(\Phi^{-1}(CP) - \Delta_1 \sqrt{I_{2,\max}})\); a lower information
bound analogously corresponds to an upper conditional error bound.
Information bounds apply only when the trial continues: information is zero
after early stopping. They refer to additional stage-two information, not
cumulative information.
minInformationPerStage and maxInformationPerStage are scalar limits for
stage two only; they do not constrain firstStageInformation.
In the continuation region, conditional error cannot exceed the conditional power;
an upper bound above it has no additional effect. Before calibration, the integrated
lower and upper bounds are checked for compatibility with the overall alpha level.
Level constant
The level constant is determined by an internal root-finding routine.
It is identified using the uniroot() function and by default, the
interval between 0 and 10 is searched for the level constant.
In specific settings, the level constant may lie outside of this interval.
In such cases, the search interval can be changed by altering the
parameters minLevelConstant and maxLevelConstant.
If inappropriate constraints to the optimal conditional error function are
provided via minConditionalError and maxConditionalError
or minInformationPerStage and maxInformationPerStage, it may
be impossible to find a level constant which exhausts the full alpha level.
Numerical integration uses an adapted routine for piecewise constant functions
where applicable. Set options(rpact.design.optimal.enforce.basic.integration = TRUE)
to use standard adaptive integration for comparison.
Generic functions
The print() and plot() functions are available for objects
of class TrialDesignOptimalConditionalError.
For details, see ?print.TrialDesignOptimalConditionalError and
?plot.TrialDesignOptimalConditionalError.
References
Brannath, W. & Bauer, P. (2004). Optimal conditional error functions for the control of conditional power. Biometrics, 60(3), 715-723. doi:10.1111/j.0006-341X.2004.00221.x
Brannath, W., zur Verth, J., Dreher, M. & Scharpenberg, M. (2024; revised 2026). Optimal monotone conditional error functions. doi:10.48550/arXiv.2402.00814
The related R package optconerrf: Optimal Monotone Conditional Error Functions provides a standalone implementation of this methodology. The rpact implementation uses rpact design objects and interfaces; optconerrf is not required to run these functions.
See also
Optimal Conditional Error Designs with rpact for a worked example with stopping rules, information constraints, interim estimates, and conditional power functions.
Examples
# Create a single-arm design with fixed parameter for the likelihood ratio
# and a fixed effect for conditional power. 80 patients are observed in the
# first-stage (firstStageInformation = 80 in the one-sample test, variance 1).
# The second-stage information is restricted to be between 40 and 160.
getDesignOptimalConditionalError(
alpha = 0.025, efficacyBounds = 0.001, futilityBounds = 0.5, conditionalPower = 0.9,
thetaH1 = 0.25, likelihoodRatioDistribution = "fixed", thetaLR = 0.25,
firstStageInformation = 80, useInterimEstimate = FALSE,
minInformationPerStage = 40, maxInformationPerStage = 160
)
#> Optimal Conditional Error Design:
#>
#> General design parameters:
#> Overall significance level: 0.025
#> First-stage efficacy boundary (p-value scale): 0.001
#> Binding first-stage futility boundary (p-value scale): 0.5
#> Constraints on second-stage information: [40, 160]
#>
#> Conditional power specification:
#> Target conditional power: 0.9
#> Alternative: 0.25
#> First-stage non-centrality parameter: 2.236068
#> First-stage information: 80
#>
#> Likelihood ratio specification:
#> Fixed parameter(s) in likelihood ratio: 0.25
#> Parameter weights: 1
#>
#> Level constant:
#> Constant: 7.61398
#> Searched on interval: [0, 10]
# Create a design comparing two groups using the maximum likelihood ratio
# and an interim estimate for the effect for conditional power.
# 160 patients per arm are observed in the first stage
# (firstStageInformation = 80 in the balanced two-sample test, variance 1).
getDesignOptimalConditionalError(
alpha = 0.025, efficacyBounds = 0.001, futilityBounds = 0.5, conditionalPower = 0.9,
minThetaH1 = 0.25, likelihoodRatioDistribution = "maxlr",
firstStageInformation = 80, useInterimEstimate = TRUE
)
#> Optimal Conditional Error Design:
#>
#> General design parameters:
#> Overall significance level: 0.025
#> First-stage efficacy boundary (p-value scale): 0.001
#> Binding first-stage futility boundary (p-value scale): 0.5
#>
#> Conditional power specification:
#> Target conditional power: 0.9
#> Alternative: interim estimate restricted to [0.25, Inf]
#> First-stage non-centrality parameter restricted to [2.23606797749979, Inf]
#> First-stage information: 80
#>
#> Likelihood ratio specification:
#> Maximum likelihood ratio
#>
#> Level constant:
#> Constant: 7.68814
#> Searched on interval: [0, 10]
# Weight several effects for the optimisation; retain a separate power target.
weightedDesign <- getDesignOptimalConditionalError(
alpha = 0.025, efficacyBounds = 0.001, futilityBounds = 0.5, conditionalPower = 0.9,
thetaH1 = 0.25, useInterimEstimate = FALSE, firstStageInformation = 80,
likelihoodRatioDistribution = "fixed", thetaLR = c(0, 0.25, 0.5),
weightsLR = c(0.25, 0.5, 0.25)
)
getStageInformation(pValue = c(0.05, 0.1, 0.3), design = weightedDesign)
#> [1] 110.6716 142.3435 185.2514
# Allow a lower conditional power target for less promising interim results.
# Leave conditionalPower unspecified when supplying a callback.
flexibleDesign <- getDesignOptimalConditionalError(
alpha = 0.025, efficacyBounds = 0.001, futilityBounds = 0.5,
conditionalPowerFunction = function(p) pnorm(1 - p),
thetaH1 = 0.25, useInterimEstimate = FALSE, firstStageInformation = 80,
likelihoodRatioDistribution = "maxlr"
)
getConditionalError(pValue = c(0.05, 0.1, 0.3), design = flexibleDesign)
#> [1] 0.08343571 0.04767596 0.02220325