R/class_design_plan.R

Defines functions plot.TrialDesignPlan .warnInCaseOfUnusedValuesForPlotting .warnInCaseOfUnusedValuesForPlottingSurvival .warnInCaseOfUnusedValuesForPlottingRates .warnInCaseOfUnusedValuesForPlottingMeans .plotSurvivalFunction .getSurvivalFunctionPlotCommand .plotTrialDesignPlan .assertIsValidVariedParameterVectorForPlotting .addPlotSubTitleItems as.data.frame.TrialDesignPlan

Documented in as.data.frame.TrialDesignPlan plot.TrialDesignPlan

## |
## |  *Trial design plan classes*
## |
## |  This file is part of the R package rpact:
## |  Confirmatory Adaptive Clinical Trial Design and Analysis
## |
## |  Author: Gernot Wassmer, PhD, and Friedrich Pahlke, PhD
## |  Licensed under "GNU Lesser General Public License" version 3
## |  License text can be found here: https://www.r-project.org/Licenses/LGPL-3
## |
## |  RPACT company website: https://www.rpact.com
## |  rpact package website: https://www.rpact.org
## |
## |  Contact us for information about our services: info@rpact.com
## |
## |  File version: $Revision: 7126 $
## |  Last changed: $Date: 2023-06-23 14:26:39 +0200 (Fr, 23 Jun 2023) $
## |  Last changed by: $Author: pahlke $
## |

#' @include f_core_constants.R
#' @include f_design_utilities.R
NULL

C_VARIABLE_DESIGN_PLAN_PARAMETERS <- c("lambda1", "pi1", "median1", "alternative", "hazardRatio")

C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_MEANS <- list(
    normalApproximation = FALSE,
    meanRatio = FALSE,
    thetaH0 = 0,
    alternative = seq(0.2, 1, 0.2),
    stDev = 1,
    groups = 2L,
    allocationRatioPlanned = 1
)

C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_RATES <- list(
    normalApproximation = TRUE,
    riskRatio = FALSE,
    thetaH0 = 0,
    pi1 = C_PI_1_SAMPLE_SIZE_DEFAULT,
    pi2 = C_PI_2_DEFAULT,
    groups = 2L,
    allocationRatioPlanned = 1
)

C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_SURVIVAL <- list(
    typeOfComputation = "Schoenfeld",
    thetaH0 = 1,
    pi2 = C_PI_2_DEFAULT,
    pi1 = C_PI_1_SAMPLE_SIZE_DEFAULT,
    allocationRatioPlanned = 1,
    accountForObservationTimes = NA,
    eventTime = 12,
    accrualTime = C_ACCRUAL_TIME_DEFAULT,
    accrualIntensity = C_ACCRUAL_INTENSITY_DEFAULT,
    kappa = 1,
    piecewiseSurvivalTime = NA_real_,
    lambda2 = NA_real_,
    lambda1 = NA_real_,
    followUpTime = C_FOLLOW_UP_TIME_DEFAULT,
    maxNumberOfSubjects = 0,
    dropoutRate1 = 0,
    dropoutRate2 = 0,
    dropoutTime = 12
)

#'
#' @name TrialDesignPlan
#'
#' @title
#' Basic Trial Design Plan
#'
#' @description
#' Basic class for trial design plans.
#'
#' @details
#' \code{TrialDesignPlan} is the basic class for
#' \itemize{
#'   \item \code{\link{TrialDesignPlanMeans}},
#'   \item \code{\link{TrialDesignPlanRates}}, and
#'   \item \code{\link{TrialDesignPlanSurvival}}.
#' }
#'
#' @include f_core_constants.R
#' @include f_core_utilities.R
#' @include class_core_parameter_set.R
#' @include class_core_plot_settings.R
#' @include class_design.R
#' @include class_design_set.R
#' @include f_core_plot.R
#'
#' @keywords internal
#'
#' @importFrom methods new
#'
TrialDesignPlan <- setRefClass("TrialDesignPlan",
    contains = "ParameterSet",
    fields = list(
        .plotSettings = "PlotSettings",
        .design = "TrialDesign",
        .objectType = "character" # "sampleSize" or "power"
    ),
    methods = list(
        initialize = function(design, ...) {
            callSuper(.design = design, ...)

            .plotSettings <<- PlotSettings()
            .parameterNames <<- .getParameterNames(design = design, designPlan = .self)
            .parameterFormatFunctions <<- C_PARAMETER_FORMAT_FUNCTIONS

            if (.isTrialDesignPlanMeans(.self)) {
                defaultValueList <- C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_MEANS
            } else if (.isTrialDesignPlanRates(.self)) {
                defaultValueList <- C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_RATES
            } else if (.isTrialDesignPlanSurvival(.self)) {
                defaultValueList <- C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_SURVIVAL
            }
            for (parameterName in .getVisibleFieldNames()) {
                defaultValue <- defaultValueList[[parameterName]]
                existingValue <- .self[[parameterName]]
                if (all(is.na(existingValue))) {
                    .setParameterType(parameterName, C_PARAM_DEFAULT_VALUE)
                } else if (!is.null(defaultValue) && length(defaultValue) == length(existingValue) &&
                        !any(is.na(defaultValue)) && !any(is.na(existingValue)) &&
                        sum(defaultValue == existingValue) == length(defaultValue)) {
                    .setParameterType(parameterName, C_PARAM_DEFAULT_VALUE)
                } else {
                    .setParameterType(parameterName, C_PARAM_USER_DEFINED)
                }
            }
            .setParameterType("optimumAllocationRatio", C_PARAM_NOT_APPLICABLE)
        },
        .setSampleSizeObject = function(objectType) {
            if (length(objectType) == 0 || !(objectType %in% c("sampleSize", "power"))) {
                stop(
                    C_EXCEPTION_TYPE_RUNTIME_ISSUE, "'.objectType' (", objectType,
                    ") must be specified as 'sampleSize' or 'power'"
                )
            }
            .objectType <<- objectType
        },
        .isSampleSizeObject = function() {
            if (length(.objectType) == 0 || !(.objectType %in% c("sampleSize", "power"))) {
                stop(C_EXCEPTION_TYPE_RUNTIME_ISSUE, "'.objectType' must be specified as 'sampleSize' or 'power'")
            }
            return(.objectType == "sampleSize")
        },
        .isPowerObject = function() {
            if (length(.objectType) == 0 || !(.objectType %in% c("sampleSize", "power"))) {
                stop(C_EXCEPTION_TYPE_RUNTIME_ISSUE, "'.objectType' must be specified as 'sampleSize' or 'power'")
            }
            return(.objectType == "power")
        },
        getPlotSettings = function() {
            return(.plotSettings)
        },
        show = function(showType = 1, digits = NA_integer_) {
            .show(showType = showType, digits = digits, consoleOutputEnabled = TRUE)
        },
        .show = function(showType = 1, digits = NA_integer_, consoleOutputEnabled = TRUE) {
            "Method for automatically printing trial plan objects"
            .resetCat()
            if (showType == 3) {
                .createSummary(.self, digits = digits)$.show(
                    showType = 1,
                    digits = digits, consoleOutputEnabled = consoleOutputEnabled
                )
            } else if (showType == 2) {
                callSuper(showType = showType, digits = digits, consoleOutputEnabled = consoleOutputEnabled)
            } else {
                .cat("Design plan parameters and output for ", .toString(), ":\n\n",
                    heading = 1,
                    consoleOutputEnabled = consoleOutputEnabled
                )

                .showParametersOfOneGroup(.getDesignParametersToShow(.self), "Design parameters",
                    orderByParameterName = FALSE, consoleOutputEnabled = consoleOutputEnabled
                )

                .showParametersOfOneGroup(.getUserDefinedParameters(), "User defined parameters",
                    orderByParameterName = FALSE, consoleOutputEnabled = consoleOutputEnabled
                )
                .showParametersOfOneGroup(.getDefaultParameters(), "Default parameters",
                    orderByParameterName = FALSE, consoleOutputEnabled = consoleOutputEnabled
                )
                .showParametersOfOneGroup(.getGeneratedParameters(), "Sample size and output",
                    orderByParameterName = FALSE, consoleOutputEnabled = consoleOutputEnabled
                )

                .showUnknownParameters(consoleOutputEnabled = consoleOutputEnabled)

                if (inherits(.self, "TrialDesignPlanSurvival") || groups == 2 || .design$kMax > 1) {
                    .cat("Legend:\n",
                        heading = 2,
                        consoleOutputEnabled = consoleOutputEnabled
                    )
                    if (inherits(.self, "TrialDesignPlanSurvival") || groups == 2) {
                        .cat("  (i): values of treatment arm i\n",
                            consoleOutputEnabled = consoleOutputEnabled
                        )
                    }
                    if (.design$kMax > 1) {
                        .cat("  [k]: values at stage k\n", consoleOutputEnabled = consoleOutputEnabled)
                    }
                }

                .cat("\n", consoleOutputEnabled = consoleOutputEnabled)
            }
        },
        getAlpha = function() {
            return(.design$alpha)
        },
        getBeta = function() {
            if (.isTrialDesignInverseNormalOrGroupSequential(.design)) {
                return(.design$beta)
            }
            return(NA_real_)
        },
        getSided = function() {
            return(.design$sided)
        },
        getTwoSidedPower = function() {
            if (.isTrialDesignInverseNormalOrGroupSequential(.design)) {
                return(.design$twoSidedPower)
            }
            return(NA)
        },
        .toString = function(startWithUpperCase = FALSE) {
            if (.isTrialDesignPlanMeans(.self)) {
                s <- "means"
            } else if (.isTrialDesignPlanRates(.self)) {
                s <- "rates"
            } else if (.isTrialDesignPlanSurvival(.self)) {
                s <- "survival data"
            } else {
                s <- paste0("unknown data class '", .getClassName(.self), "'")
            }
            return(ifelse(startWithUpperCase, .firstCharacterToUpperCase(s), s))
        }
    )
)

#'
#' @title
#' Coerce Trial Design Plan to a Data Frame
#'
#' @description
#' Returns the \code{\link{TrialDesignPlan}} as data frame.
#'
#' @param x A \code{\link{TrialDesignPlan}} object.
#' @inheritParams param_niceColumnNamesEnabled
#' @inheritParams param_includeAllParameters
#' @inheritParams param_three_dots
#'
#' @details
#' Coerces the design plan to a data frame.
#'
#' @template return_dataframe
#'
#' @examples
#' as.data.frame(getSampleSizeMeans())
#'
#' @export
#'
#' @keywords internal
#'
as.data.frame.TrialDesignPlan <- function(x, row.names = NULL,
        optional = FALSE, niceColumnNamesEnabled = FALSE, includeAllParameters = FALSE, ...) {
    return(.getAsDataFrame(
        parameterSet = x,
        parameterNames = NULL,
        niceColumnNamesEnabled = niceColumnNamesEnabled,
        includeAllParameters = includeAllParameters
    ))
}

#'
#' @name TrialDesignPlanMeans
#'
#' @title
#' Trial Design Plan Means
#'
#' @description
#' Trial design plan for means.
#'
#' @template field_meanRatio
#' @template field_thetaH0
#' @template field_normalApproximation
#' @template field_alternative
#' @template field_stDev
#' @template field_groups
#' @template field_allocationRatioPlanned
#' @template field_optimumAllocationRatio
#' @template field_directionUpper
#' @template field_effect
#' @template field_overallReject
#' @template field_rejectPerStage
#' @template field_futilityStop
#' @template field_futilityPerStage
#' @template field_earlyStop
#' @template field_expectedNumberOfSubjects
#' @template field_nFixed
#' @template field_nFixed1
#' @template field_nFixed2
#' @template field_informationRates
#' @template field_maxNumberOfSubjects
#' @template field_maxNumberOfSubjects1
#' @template field_maxNumberOfSubjects2
#' @template field_numberOfSubjects
#' @template field_numberOfSubjects1
#' @template field_numberOfSubjects2
#' @template field_expectedNumberOfSubjectsH0
#' @template field_expectedNumberOfSubjectsH01
#' @template field_expectedNumberOfSubjectsH1
#' @template field_criticalValuesEffectScale
#' @template field_criticalValuesEffectScaleLower
#' @template field_criticalValuesEffectScaleUpper
#' @template field_criticalValuesPValueScale
#' @template field_futilityBoundsEffectScale
#' @template field_futilityBoundsEffectScaleLower
#' @template field_futilityBoundsEffectScaleUpper
#' @template field_futilityBoundsPValueScale
#'
#' @details
#' This object cannot be created directly; use \code{\link[=getSampleSizeMeans]{getSampleSizeMeans()}}
#' with suitable arguments to create a design plan for a dataset of means.
#'
#' @include class_core_parameter_set.R
#' @include class_design.R
#' @include class_design_set.R
#' @include f_core_constants.R
#'
#' @keywords internal
#'
#' @importFrom methods new
#'
TrialDesignPlanMeans <- setRefClass("TrialDesignPlanMeans",
    contains = "TrialDesignPlan",
    fields = list(
        meanRatio = "logical",
        thetaH0 = "numeric",
        normalApproximation = "logical",
        alternative = "numeric",
        stDev = "numeric",
        groups = "numeric",
        allocationRatioPlanned = "numeric",
        optimumAllocationRatio = "logical",
        directionUpper = "logical",
        effect = "numeric",
        overallReject = "numeric",
        rejectPerStage = "matrix",
        futilityStop = "numeric",
        futilityPerStage = "matrix",
        earlyStop = "numeric",
        expectedNumberOfSubjects = "numeric",
        nFixed = "numeric",
        nFixed1 = "numeric",
        nFixed2 = "numeric",
        informationRates = "matrix",
        maxNumberOfSubjects = "numeric",
        maxNumberOfSubjects1 = "numeric",
        maxNumberOfSubjects2 = "numeric",
        numberOfSubjects = "matrix",
        numberOfSubjects1 = "matrix",
        numberOfSubjects2 = "matrix",
        expectedNumberOfSubjectsH0 = "numeric",
        expectedNumberOfSubjectsH01 = "numeric",
        expectedNumberOfSubjectsH1 = "numeric",
        criticalValuesEffectScale = "matrix",
        criticalValuesEffectScaleLower = "matrix",
        criticalValuesEffectScaleUpper = "matrix",
        criticalValuesPValueScale = "matrix",
        futilityBoundsEffectScale = "matrix",
        futilityBoundsEffectScaleLower = "matrix",
        futilityBoundsEffectScaleUpper = "matrix",
        futilityBoundsPValueScale = "matrix"
    ),
    methods = list(
        initialize = function(...,
                normalApproximation = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_MEANS[["normalApproximation"]],
                meanRatio = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_MEANS[["meanRatio"]],
                thetaH0 = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_MEANS[["thetaH0"]],
                alternative = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_MEANS[["alternative"]],
                stDev = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_MEANS[["stDev"]],
                groups = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_MEANS[["groups"]],
                allocationRatioPlanned = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_MEANS[["allocationRatioPlanned"]]) {
            callSuper(...,
                normalApproximation = normalApproximation,
                meanRatio = meanRatio,
                thetaH0 = thetaH0,
                alternative = alternative,
                stDev = stDev,
                groups = groups,
                allocationRatioPlanned = allocationRatioPlanned
            )

            optimumAllocationRatio <<- FALSE
            visibleFieldNames <- .getVisibleFieldNames()
            startIndex <- which(visibleFieldNames == "directionUpper")
            for (i in startIndex:length(visibleFieldNames)) {
                .setParameterType(visibleFieldNames[i], C_PARAM_NOT_APPLICABLE)
            }

            if (groups == 1) {
                .setParameterType("meanRatio", C_PARAM_NOT_APPLICABLE)
                .setParameterType("allocationRatioPlanned", C_PARAM_NOT_APPLICABLE)
            }

            .setParameterType("maxNumberOfSubjects1", C_PARAM_NOT_APPLICABLE)
            .setParameterType("maxNumberOfSubjects2", C_PARAM_NOT_APPLICABLE)

            .setParameterType("criticalValuesEffectScale", C_PARAM_NOT_APPLICABLE)
            .setParameterType("criticalValuesEffectScaleLower", C_PARAM_NOT_APPLICABLE)
            .setParameterType("criticalValuesEffectScaleUpper", C_PARAM_NOT_APPLICABLE)

            .setParameterType("futilityBoundsEffectScale", C_PARAM_NOT_APPLICABLE)
            .setParameterType("futilityBoundsEffectScaleLower", C_PARAM_NOT_APPLICABLE)
            .setParameterType("futilityBoundsEffectScaleUpper", C_PARAM_NOT_APPLICABLE)
        },
        clone = function(alternative = NA_real_) {
            alternativeTemp <- alternative
            if (any(is.na(alternative))) {
                alternativeTemp <- .self$alternative
            }
            if (.objectType == "sampleSize") {
                result <- getSampleSizeMeans(
                    design = .self$.design,
                    normalApproximation = .self$.getParameterValueIfUserDefinedOrDefault("normalApproximation"),
                    meanRatio = .self$meanRatio, # .getParameterValueIfUserDefinedOrDefault("meanRatio"),
                    thetaH0 = .self$.getParameterValueIfUserDefinedOrDefault("thetaH0"),
                    alternative = alternativeTemp,
                    stDev = .self$.getParameterValueIfUserDefinedOrDefault("stDev"),
                    groups = .self$.getParameterValueIfUserDefinedOrDefault("groups"),
                    allocationRatioPlanned = .self$.getParameterValueIfUserDefinedOrDefault("allocationRatioPlanned")
                )
            } else {
                result <- getPowerMeans(
                    design = .self$.design,
                    normalApproximation = .self$.getParameterValueIfUserDefinedOrDefault("normalApproximation"),
                    meanRatio = .self$meanRatio, # .getParameterValueIfUserDefinedOrDefault("meanRatio"),
                    thetaH0 = .self$.getParameterValueIfUserDefinedOrDefault("thetaH0"),
                    alternative = alternativeTemp,
                    stDev = .self$.getParameterValueIfUserDefinedOrDefault("stDev"),
                    directionUpper = .self$.getParameterValueIfUserDefinedOrDefault("directionUpper"),
                    maxNumberOfSubjects = .self$.getParameterValueIfUserDefinedOrDefault("maxNumberOfSubjects"),
                    groups = .self$.getParameterValueIfUserDefinedOrDefault("groups"),
                    allocationRatioPlanned = .self$.getParameterValueIfUserDefinedOrDefault("allocationRatioPlanned")
                )
            }
            result$.plotSettings <- .self$.plotSettings
            return(result)
        },
        show = function(showType = 1, digits = NA_integer_) {
            "Method for automatically printing trial plan objects"
            callSuper(showType = showType, digits = digits)
        }
    )
)

#'
#' @name TrialDesignPlanRates
#'
#' @title
#' Trial Design Plan Rates
#'
#' @description
#' Trial design plan for rates.
#'
#' @template field_riskRatio
#' @template field_thetaH0
#' @template field_normalApproximation
#' @template field_pi1
#' @template field_pi2
#' @template field_groups
#' @template field_allocationRatioPlanned
#' @template field_optimumAllocationRatio
#' @template field_directionUpper
#' @template field_effect
#' @template field_overallReject
#' @template field_rejectPerStage
#' @template field_futilityStop
#' @template field_futilityPerStage
#' @template field_earlyStop
#' @template field_expectedNumberOfSubjects
#' @template field_nFixed
#' @template field_nFixed1
#' @template field_nFixed2
#' @template field_informationRates
#' @template field_maxNumberOfSubjects
#' @template field_maxNumberOfSubjects1
#' @template field_maxNumberOfSubjects2
#' @template field_numberOfSubjects
#' @template field_numberOfSubjects1
#' @template field_numberOfSubjects2
#' @template field_expectedNumberOfSubjectsH0
#' @template field_expectedNumberOfSubjectsH01
#' @template field_expectedNumberOfSubjectsH1
#' @template field_criticalValuesEffectScale
#' @template field_criticalValuesEffectScaleLower
#' @template field_criticalValuesEffectScaleUpper
#' @template field_criticalValuesPValueScale
#' @template field_futilityBoundsEffectScale
#' @template field_futilityBoundsEffectScaleLower
#' @template field_futilityBoundsEffectScaleUpper
#' @template field_futilityBoundsPValueScale
#'
#' @details
#' This object cannot be created directly; use \code{\link[=getSampleSizeRates]{getSampleSizeRates()}}
#' with suitable arguments to create a design plan for a dataset of rates.
#'
#' @include class_core_parameter_set.R
#' @include class_design.R
#' @include class_design_set.R
#' @include f_core_constants.R
#'
#' @keywords internal
#'
#' @importFrom methods new
#'
TrialDesignPlanRates <- setRefClass("TrialDesignPlanRates",
    contains = "TrialDesignPlan",
    fields = list(
        riskRatio = "logical",
        thetaH0 = "numeric",
        normalApproximation = "logical",
        pi1 = "numeric",
        pi2 = "numeric",
        groups = "numeric",
        allocationRatioPlanned = "numeric",
        optimumAllocationRatio = "logical",
        directionUpper = "logical",
        effect = "numeric",
        expectedNumberOfSubjects = "numeric",
        nFixed = "numeric",
        nFixed1 = "numeric",
        nFixed2 = "numeric",
        overallReject = "numeric",
        rejectPerStage = "matrix",
        futilityStop = "numeric",
        futilityPerStage = "matrix",
        earlyStop = "numeric",
        informationRates = "matrix",
        maxNumberOfSubjects = "numeric",
        maxNumberOfSubjects1 = "numeric",
        maxNumberOfSubjects2 = "numeric",
        numberOfSubjects = "matrix",
        numberOfSubjects1 = "matrix",
        numberOfSubjects2 = "matrix",
        expectedNumberOfSubjectsH0 = "numeric",
        expectedNumberOfSubjectsH01 = "numeric",
        expectedNumberOfSubjectsH1 = "numeric",
        criticalValuesEffectScale = "matrix",
        criticalValuesEffectScaleLower = "matrix",
        criticalValuesEffectScaleUpper = "matrix",
        criticalValuesPValueScale = "matrix",
        futilityBoundsEffectScale = "matrix",
        futilityBoundsEffectScaleLower = "matrix",
        futilityBoundsEffectScaleUpper = "matrix",
        futilityBoundsPValueScale = "matrix"
    ),
    methods = list(
        initialize = function(...,
                normalApproximation = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_RATES[["normalApproximation"]],
                riskRatio = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_RATES[["riskRatio"]],
                thetaH0 = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_RATES[["thetaH0"]],
                pi1 = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_RATES[["pi1"]],
                pi2 = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_RATES[["pi2"]],
                groups = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_RATES[["groups"]],
                allocationRatioPlanned = C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_RATES[["allocationRatioPlanned"]]) {
            callSuper(...,
                normalApproximation = normalApproximation,
                riskRatio = riskRatio,
                thetaH0 = thetaH0,
                pi1 = pi1,
                pi2 = pi2,
                groups = groups,
                allocationRatioPlanned = allocationRatioPlanned
            )

            optimumAllocationRatio <<- FALSE
            visibleFieldNames <- .getVisibleFieldNames()
            startIndex <- which(visibleFieldNames == "directionUpper")
            for (i in startIndex:length(visibleFieldNames)) {
                .setParameterType(visibleFieldNames[i], C_PARAM_NOT_APPLICABLE)
            }

            if (groups == 1) {
                .setParameterType("meanRatio", C_PARAM_NOT_APPLICABLE)
                .setParameterType("allocationRatioPlanned", C_PARAM_NOT_APPLICABLE)
            }

            .setParameterType("maxNumberOfSubjects1", C_PARAM_NOT_APPLICABLE)
            .setParameterType("maxNumberOfSubjects2", C_PARAM_NOT_APPLICABLE)

            .setParameterType("criticalValuesEffectScale", C_PARAM_NOT_APPLICABLE)
            .setParameterType("criticalValuesEffectScaleLower", C_PARAM_NOT_APPLICABLE)
            .setParameterType("criticalValuesEffectScaleUpper", C_PARAM_NOT_APPLICABLE)

            .setParameterType("futilityBoundsEffectScale", C_PARAM_NOT_APPLICABLE)
            .setParameterType("futilityBoundsEffectScaleLower", C_PARAM_NOT_APPLICABLE)
            .setParameterType("futilityBoundsEffectScaleUpper", C_PARAM_NOT_APPLICABLE)
        },
        clone = function(pi1 = NA_real_) {
            pi1Temp <- pi1
            if (any(is.na(pi1))) {
                pi1Temp <- .self$pi1
            }
            if (.objectType == "sampleSize") {
                return(getSampleSizeRates(
                    design = .self$.design,
                    normalApproximation = .self$.getParameterValueIfUserDefinedOrDefault("normalApproximation"),
                    riskRatio = .self$riskRatio, # .getParameterValueIfUserDefinedOrDefault("riskRatio"),
                    thetaH0 = .self$.getParameterValueIfUserDefinedOrDefault("thetaH0"),
                    pi1 = pi1Temp,
                    pi2 = .self$.getParameterValueIfUserDefinedOrDefault("pi2"),
                    groups = .self$.getParameterValueIfUserDefinedOrDefault("groups"),
                    allocationRatioPlanned = .self$.getParameterValueIfUserDefinedOrDefault("allocationRatioPlanned")
                ))
            } else {
                return(getPowerRates(
                    design = .self$.design,
                    riskRatio = .self$riskRatio, # .getParameterValueIfUserDefinedOrDefault("riskRatio"),
                    thetaH0 = .self$.getParameterValueIfUserDefinedOrDefault("thetaH0"),
                    pi1 = pi1Temp,
                    pi2 = .self$.getParameterValueIfUserDefinedOrDefault("pi2"),
                    directionUpper = .self$.getParameterValueIfUserDefinedOrDefault("directionUpper"),
                    maxNumberOfSubjects = .self$.getParameterValueIfUserDefinedOrDefault("maxNumberOfSubjects"),
                    groups = .self$.getParameterValueIfUserDefinedOrDefault("groups"),
                    allocationRatioPlanned = .self$.getParameterValueIfUserDefinedOrDefault("allocationRatioPlanned")
                ))
            }
        },
        show = function(showType = 1, digits = NA_integer_) {
            "Method for automatically printing trial plan objects"
            callSuper(showType = showType, digits = digits)
        }
    )
)

#'
#' @name TrialDesignPlanSurvival
#'
#' @title
#' Trial Design Plan Survival
#'
#' @description
#' Trial design plan for survival data.
#'
#' @template field_thetaH0
#' @template field_typeOfComputation
#' @template field_directionUpper
#' @template field_pi1_survival
#' @template field_pi2_survival
#' @template field_median1
#' @template field_median2
#' @template field_lambda1
#' @template field_lambda2
#' @template field_hazardRatio
#' @template field_maxNumberOfSubjects
#' @template field_maxNumberOfSubjects1
#' @template field_maxNumberOfSubjects2
#' @template field_maxNumberOfEvents
#' @template field_allocationRatioPlanned
#' @template field_optimumAllocationRatio
#' @template field_accountForObservationTimes
#' @template field_eventTime
#' @template field_accrualTime
#' @template field_totalAccrualTime
#' @template field_accrualIntensity
#' @template field_accrualIntensityRelative
#' @template field_kappa
#' @template field_piecewiseSurvivalTime
#' @template field_followUpTime
#' @template field_dropoutRate1
#' @template field_dropoutRate2
#' @template field_dropoutTime
#' @template field_chi
#' @template field_expectedNumberOfEvents
#' @template field_eventsFixed
#' @template field_nFixed
#' @template field_nFixed1
#' @template field_nFixed2
#' @template field_overallReject
#' @template field_rejectPerStage
#' @template field_futilityStop
#' @template field_futilityPerStage
#' @template field_earlyStop
#' @template field_informationRates
#' @template field_analysisTime
#' @template field_studyDurationH1
#' @template field_studyDuration
#' @template field_maxStudyDuration
#' @template field_eventsPerStage
#' @template field_expectedEventsH0
#' @template field_expectedEventsH01
#' @template field_expectedEventsH1
#' @template field_numberOfSubjects
#' @template field_numberOfSubjects1
#' @template field_numberOfSubjects2
#' @template field_expectedNumberOfSubjectsH1
#' @template field_expectedNumberOfSubjects
#' @template field_criticalValuesEffectScale
#' @template field_criticalValuesEffectScaleLower
#' @template field_criticalValuesEffectScaleUpper
#' @template field_criticalValuesPValueScale
#' @template field_futilityBoundsEffectScale
#' @template field_futilityBoundsEffectScaleLower
#' @template field_futilityBoundsEffectScaleUpper
#' @template field_futilityBoundsPValueScale
#'
#' @details
#' This object cannot be created directly; use \code{\link[=getSampleSizeSurvival]{getSampleSizeSurvival()}}
#' with suitable arguments to create a design plan for a dataset of survival data.
#'
#' @include class_core_parameter_set.R
#' @include class_design.R
#' @include class_design_set.R
#' @include class_time.R
#' @include f_core_constants.R
#'
#' @keywords internal
#'
#' @importFrom methods new
#'
TrialDesignPlanSurvival <- setRefClass("TrialDesignPlanSurvival",
    contains = "TrialDesignPlan",
    fields = list(
        .piecewiseSurvivalTime = "PiecewiseSurvivalTime",
        .accrualTime = "AccrualTime",
        .calculateFollowUpTime = "logical",
        thetaH0 = "numeric",
        typeOfComputation = "character",
        directionUpper = "logical",
        pi1 = "numeric",
        pi2 = "numeric",
        median1 = "numeric",
        median2 = "numeric",
        lambda1 = "numeric",
        lambda2 = "numeric",
        hazardRatio = "numeric",
        maxNumberOfSubjects = "numeric",
        maxNumberOfSubjects1 = "numeric",
        maxNumberOfSubjects2 = "numeric",
        maxNumberOfEvents = "numeric",
        allocationRatioPlanned = "numeric",
        optimumAllocationRatio = "logical",
        accountForObservationTimes = "logical",
        eventTime = "numeric",
        accrualTime = "numeric",
        totalAccrualTime = "numeric",
        accrualIntensity = "numeric",
        accrualIntensityRelative = "numeric",
        kappa = "numeric",
        piecewiseSurvivalTime = "numeric",
        followUpTime = "numeric",
        dropoutRate1 = "numeric",
        dropoutRate2 = "numeric",
        dropoutTime = "numeric",
        chi = "numeric",
        expectedNumberOfEvents = "numeric",
        eventsFixed = "numeric",
        nFixed = "numeric",
        nFixed1 = "numeric",
        nFixed2 = "numeric",
        overallReject = "numeric",
        rejectPerStage = "matrix",
        futilityStop = "numeric",
        futilityPerStage = "matrix",
        earlyStop = "numeric",
        informationRates = "matrix",
        analysisTime = "matrix",
        studyDurationH1 = "numeric",
        studyDuration = "numeric",
        maxStudyDuration = "numeric",
        eventsPerStage = "matrix",
        expectedEventsH0 = "numeric",
        expectedEventsH01 = "numeric",
        expectedEventsH1 = "numeric",
        numberOfSubjects = "matrix",
        numberOfSubjects1 = "matrix",
        numberOfSubjects2 = "matrix",
        expectedNumberOfSubjectsH1 = "numeric",
        expectedNumberOfSubjects = "numeric",
        criticalValuesEffectScale = "matrix",
        criticalValuesEffectScaleLower = "matrix",
        criticalValuesEffectScaleUpper = "matrix",
        criticalValuesPValueScale = "matrix",
        futilityBoundsEffectScale = "matrix",
        futilityBoundsEffectScaleLower = "matrix",
        futilityBoundsEffectScaleUpper = "matrix",
        futilityBoundsPValueScale = "matrix"
    ),
    methods = list(
        initialize = function(...) {
            callSuper(...)

            optimumAllocationRatio <<- FALSE
            visibleFieldNames <- .getVisibleFieldNames()
            startIndex <- which(visibleFieldNames == "hazardRatio")
            for (i in startIndex:length(visibleFieldNames)) {
                .setParameterType(visibleFieldNames[i], C_PARAM_NOT_APPLICABLE)
            }

            .setParameterType("maxNumberOfSubjects", C_PARAM_NOT_APPLICABLE)
            .setParameterType("maxNumberOfSubjects1", C_PARAM_NOT_APPLICABLE)
            .setParameterType("maxNumberOfSubjects2", C_PARAM_NOT_APPLICABLE)
            .setParameterType("median1", C_PARAM_NOT_APPLICABLE)
            .setParameterType("median2", C_PARAM_NOT_APPLICABLE)
            .setParameterType("accountForObservationTimes", C_PARAM_NOT_APPLICABLE)
            .setParameterType("chi", C_PARAM_NOT_APPLICABLE)
            .setParameterType("maxStudyDuration", C_PARAM_NOT_APPLICABLE)
            .setParameterType("accrualIntensityRelative", C_PARAM_NOT_APPLICABLE)

            .setParameterType("criticalValuesEffectScale", C_PARAM_NOT_APPLICABLE)
            .setParameterType("criticalValuesEffectScaleLower", C_PARAM_NOT_APPLICABLE)
            .setParameterType("criticalValuesEffectScaleUpper", C_PARAM_NOT_APPLICABLE)

            .setParameterType("futilityBoundsEffectScale", C_PARAM_NOT_APPLICABLE)
            .setParameterType("futilityBoundsEffectScaleLower", C_PARAM_NOT_APPLICABLE)
            .setParameterType("futilityBoundsEffectScaleUpper", C_PARAM_NOT_APPLICABLE)

            # set default values
            for (parameterName in c(
                "eventTime", "accrualTime", "accrualIntensity",
                "kappa", "piecewiseSurvivalTime", "lambda1", "lambda2",
                "followUpTime", "dropoutTime"
            )) {
                .setDefaultValue(parameterName)
            }
        },
        clone = function(hazardRatio = NA_real_, pi1 = NA_real_) {
            hr <- NA_real_
            if (.getParameterType("hazardRatio") == C_PARAM_USER_DEFINED) {
                hr <- hazardRatio
                if (any(is.na(hazardRatio))) {
                    hr <- .self$hazardRatio
                }
            }
            pi1Temp <- NA_real_
            if (.getParameterType("pi1") == C_PARAM_USER_DEFINED) {
                pi1Temp <- pi1
                if (any(is.na(pi1))) {
                    pi1Temp <- .self$pi1
                }
            }
            accrualTimeTemp <- .self$.getParameterValueIfUserDefinedOrDefault("accrualTime")
            if (!is.null(accrualTimeTemp) && length(accrualTimeTemp) > 0 &&
                    !all(is.na(accrualTimeTemp)) && accrualTimeTemp[1] != 0) {
                accrualTimeTemp <- c(0, accrualTimeTemp)
            }
            accrualIntensityTemp <- .self$.getParameterValueIfUserDefinedOrDefault("accrualIntensity")
            if (all(is.na(accrualIntensityTemp))) {
                accrualIntensityTemp <- C_ACCRUAL_INTENSITY_DEFAULT
            }
            if (.objectType == "sampleSize") {
                return(getSampleSizeSurvival(
                    design = .self$.design,
                    typeOfComputation = .self$.getParameterValueIfUserDefinedOrDefault("typeOfComputation"),
                    thetaH0 = .self$.getParameterValueIfUserDefinedOrDefault("thetaH0"),
                    pi1 = pi1Temp,
                    pi2 = .self$.getParameterValueIfUserDefinedOrDefault("pi2"),
                    allocationRatioPlanned = .self$allocationRatioPlanned,
                    accountForObservationTimes = .self$.getParameterValueIfUserDefinedOrDefault("accountForObservationTimes"),
                    eventTime = .self$eventTime,
                    accrualTime = accrualTimeTemp,
                    accrualIntensity = accrualIntensityTemp,
                    kappa = .self$kappa,
                    piecewiseSurvivalTime = .self$.getParameterValueIfUserDefinedOrDefault("piecewiseSurvivalTime"),
                    lambda2 = .self$.getParameterValueIfUserDefinedOrDefault("lambda2"),
                    lambda1 = .self$.getParameterValueIfUserDefinedOrDefault("lambda1"),
                    followUpTime = .self$.getParameterValueIfUserDefinedOrDefault("followUpTime"),
                    maxNumberOfSubjects = .self$.getParameterValueIfUserDefinedOrDefault("maxNumberOfSubjects"),
                    dropoutRate1 = .self$dropoutRate1,
                    dropoutRate2 = .self$dropoutRate2,
                    dropoutTime = .self$dropoutTime,
                    hazardRatio = hr
                ))
            } else {
                directionUpperTemp <- directionUpper
                if (length(directionUpperTemp) > 1) {
                    directionUpperTemp <- directionUpperTemp[1]
                }
                return(getPowerSurvival(
                    design = .self$.design,
                    typeOfComputation = .self$.getParameterValueIfUserDefinedOrDefault("typeOfComputation"),
                    thetaH0 = .self$.getParameterValueIfUserDefinedOrDefault("thetaH0"),
                    pi1 = pi1Temp,
                    pi2 = .self$.getParameterValueIfUserDefinedOrDefault("pi2"),
                    directionUpper = directionUpperTemp,
                    allocationRatioPlanned = .self$allocationRatioPlanned,
                    eventTime = .self$eventTime,
                    accrualTime = accrualTimeTemp,
                    accrualIntensity = accrualIntensityTemp,
                    kappa = .self$kappa,
                    piecewiseSurvivalTime = .self$.getParameterValueIfUserDefinedOrDefault("piecewiseSurvivalTime"),
                    lambda2 = .self$.getParameterValueIfUserDefinedOrDefault("lambda2"),
                    lambda1 = .self$.getParameterValueIfUserDefinedOrDefault("lambda1"),
                    hazardRatio = hr,
                    maxNumberOfSubjects = .self$.getParameterValueIfUserDefinedOrDefault("maxNumberOfSubjects"),
                    maxNumberOfEvents = .self$.getParameterValueIfUserDefinedOrDefault("maxNumberOfEvents"),
                    dropoutRate1 = .self$dropoutRate1,
                    dropoutRate2 = .self$dropoutRate2,
                    dropoutTime = .self$dropoutTime
                ))
            }
        },
        .setDefaultValue = function(argumentName) {
            if (is.null(.self[[argumentName]]) || all(is.na(.self[[argumentName]]))) {
                .self[[argumentName]] <<- C_TRIAL_DESIGN_PLAN_DEFAULT_VALUES_SURVIVAL[[argumentName]]
                .setParameterType(argumentName, C_PARAM_DEFAULT_VALUE)
            }
        },
        show = function(showType = 1, digits = NA_integer_) {
            "Method for automatically printing trial plan objects"
            callSuper(showType = showType, digits = digits)
        },
        .warnInCaseArgumentExists = function(argument, argumentName) {
            if (!all(is.na(argument)) && any(argument > 0)) {
                warning(sprintf(
                    "Specified '%s' (%s) not taken into account",
                    argumentName, .arrayToString(argument)
                ), call. = FALSE)
            }
        }
    )
)

.addPlotSubTitleItems <- function(designPlan, designMaster, items, type) {
    if (type %in% c(1, 3, 4)) {
        return(invisible())
    }

    if (.isTrialDesignPlanMeans(designPlan)) {
        nMax <- designPlan$maxNumberOfSubjects[1] # use first value for plotting

        if (!(type %in% c(5))) {
            items$add("N", round(nMax, 1), "max")
        }

        if ((type %in% c(5)) && !(items$title == "Sample Size")) {
            items$add("N", round(nMax, 1), "max")
        }

        if (designPlan$meanRatio) {
            items$add("coefficient of variation", designPlan$stDev)
        } else {
            items$add("standard deviation", designPlan$stDev)
        }

        if (designPlan$groups == 1) {
            if (type %in% c(2, (5:9))) {
                items$add("H0: mu", designPlan$thetaH0)
                items$add("allocation ratio", round(designPlan$allocationRatioPlanned, 2))
            }
        } else {
            if (type %in% c(2, (5:9))) {
                if (designPlan$meanRatio) {
                    items$add("H0: mean ratio", designPlan$thetaH0)
                } else {
                    items$add("H0: mean difference", designPlan$thetaH0)
                }
                items$add("allocation ratio", round(designPlan$allocationRatioPlanned, 2))
            }
        }
    } else if (.isTrialDesignPlanRates(designPlan)) {
        nMax <- designPlan$maxNumberOfSubjects[1] # use first value for plotting

        if (!(type %in% c(5))) {
            items$add("N", round(nMax, 1), "max")
        }

        if ((type %in% c(5)) && !(items$title == "Sample Size")) {
            items$add("N", round(nMax, 1), "max")
        }

        if (designPlan$groups == 2 && !(type %in% c(3, 4)) &&
                length(designPlan$pi2) == 1 && !is.na(designPlan$pi2)) {
            items$add("pi", designPlan$pi2, 2)
        }

        if (designPlan$groups == 1) {
            if (type %in% c(2, (5:9))) {
                items$add("H0: pi", designPlan$thetaH0)
            }
        } else {
            if (type %in% c(2, (5:9))) {
                if (designPlan$riskRatio) {
                    items$add("H0: risk ratio", designPlan$thetaH0)
                } else {
                    items$add("H0: risk difference", designPlan$thetaH0)
                }
                items$add("allocation ratio", round(designPlan$allocationRatioPlanned, 2))
            }
        }
    } else if (.isTrialDesignPlanSurvival(designPlan)) {
        if (designPlan$.isPowerObject() && !(type %in% (13:14))) {
            items$add("maximum number of events", designPlan$maxNumberOfEvents[1])
        }
        if (type %in% (10:12)) {
            items$add("maximum number of subjects", designPlan$maxNumberOfSubjects[1])
        }
        if (type %in% c(2, (5:12))) {
            items$add("H0: hazard ratio", designPlan$thetaH0)
            items$add("allocation ratio", round(designPlan$allocationRatioPlanned, 2))
        }
    }
}

.assertIsValidVariedParameterVectorForPlotting <- function(designPlan, plotType) {
    if (.isTrialDesignPlanMeans(designPlan)) {
        if (is.null(designPlan$alternative) || any(is.na(designPlan$alternative)) ||
                length(designPlan$alternative) <= 1) {
            stop(
                C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "plot type ", plotType,
                " is only available if 'alternative' with length > 1 is defined"
            )
        }
    } else if (.isTrialDesignPlanRates(designPlan)) {
        if (is.null(designPlan$pi1) || any(is.na(designPlan$pi1)) ||
                length(designPlan$pi1) <= 1) {
            stop(
                C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "plot type ", plotType,
                " is only available if 'pi1' with length > 1 is defined"
            )
        }
    } else if (.isTrialDesignPlanSurvival(designPlan)) {
        if (is.null(designPlan$hazardRatio) || any(is.na(designPlan$hazardRatio)) ||
                length(designPlan$hazardRatio) <= 1) {
            stop(
                C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "plot type ", plotType,
                " is only available if 'hazardRatio' with length > 1 is defined"
            )
        }
    }
}

.plotTrialDesignPlan <- function(designPlan, type = 1L, main = NA_character_,
        xlab = NA_character_, ylab = NA_character_, palette = "Set1",
        theta = seq(-1, 1, 0.02), plotPointsEnabled = NA,
        legendPosition = NA_integer_, showSource = FALSE,
        designPlanName = NA_character_, plotSettings = NULL, ...) {
    .assertGgplotIsInstalled()
    .assertIsTrialDesignPlan(designPlan)
    .assertIsValidLegendPosition(legendPosition)
    .assertIsSingleInteger(type, "type", naAllowed = FALSE, validateType = FALSE)
    theta <- .assertIsValidThetaRange(thetaRange = theta)

    survivalDesignPlanEnabled <- .isTrialDesignPlanSurvival(designPlan)

    nMax <- ifelse(survivalDesignPlanEnabled, designPlan$maxNumberOfEvents[1],
        designPlan$maxNumberOfSubjects[1]
    ) # use first value for plotting

    if (is.null(plotSettings)) {
        plotSettings <- designPlan$.plotSettings
    }

    designMaster <- designPlan$.design

    if (designMaster$kMax == 1 && (type %in% c(1:4))) {
        stop(
            C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "'type' (", type,
            ") is not available for 'kMax' = 1"
        )
    }

    if (designPlan$.isSampleSizeObject()) {
        if (survivalDesignPlanEnabled) {
            if (!(type %in% c(1:5, 13, 14))) {
                stop(
                    C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "'type' (", type,
                    ") is not allowed; must be 1, 2, 3, 4, 5, 13 or 14"
                )
            }
        } else {
            if (!(type %in% c(1:5))) {
                stop(
                    C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "'type' (", type,
                    ") is not allowed; must be 1, 2, 3, 4, 5"
                )
            }
        }
    }

    if (is.na(plotPointsEnabled)) {
        plotPointsEnabled <- type < 4
    }

    ratioEnabled <- (survivalDesignPlanEnabled ||
        (.isTrialDesignPlanMeans(designPlan) && designPlan$meanRatio) ||
        (.isTrialDesignPlanRates(designPlan) && designPlan$riskRatio))

    variedParameters <- logical(0)

    showSourceHint <- ""
    if (type %in% c(5:12)) {
        if (.isTrialDesignPlanMeans(designPlan) && length(designPlan$alternative) == 2 &&
                designPlan$.getParameterType("alternative") == C_PARAM_USER_DEFINED) {
            if (!is.logical(showSource) || isTRUE(showSource)) {
                showSourceHint <- .getVariedParameterHint(designPlan$alternative, "alternative")
            }
            designPlan <- designPlan$clone(
                alternative =
                    .getVariedParameterVector(designPlan$alternative, "alternative")
            )
        } else if ((.isTrialDesignPlanRates(designPlan) || survivalDesignPlanEnabled) &&
                length(designPlan$pi1) == 2 &&
                designPlan$.getParameterType("pi1") == C_PARAM_USER_DEFINED) {
            if (!is.logical(showSource) || isTRUE(showSource)) {
                showSourceHint <- .getVariedParameterHint(designPlan$pi1, "pi1")
            }
            designPlan <- designPlan$clone(
                pi1 =
                    .getVariedParameterVector(designPlan$pi1, "pi1")
            )
        } else if (survivalDesignPlanEnabled && length(designPlan$hazardRatio) == 2 &&
                designPlan$.getParameterType("hazardRatio") == C_PARAM_USER_DEFINED) {
            if (!is.logical(showSource) || isTRUE(showSource)) {
                showSourceHint <- .getVariedParameterHint(designPlan$hazardRatio, "hazardRatio")
            }
            designPlan <- designPlan$clone(
                hazardRatio =
                    .getVariedParameterVector(designPlan$hazardRatio, "hazardRatio")
            )
        }
    }

    srcCmd <- NULL

    reducedParam <- NULL
    if (type %in% c(1:4)) {
        reducedParam <- .warnInCaseOfUnusedValuesForPlotting(designPlan)
    }

    if (type == 1) { # Boundary plot
        if (survivalDesignPlanEnabled) {
            if (is.na(main)) {
                main <- PlotSubTitleItems(title = "Boundaries Z Scale")
                .addPlotSubTitleItems(designPlan, designMaster, main, type)
                if (!is.null(reducedParam)) {
                    main$add(reducedParam$title, reducedParam$value, reducedParam$subscript)
                }
            }

            if (designMaster$sided == 1) {
                designPlan <- data.frame(
                    eventsPerStage = designPlan$eventsPerStage[, 1],
                    criticalValues = designMaster$criticalValues,
                    futilityBounds = c(designMaster$futilityBounds, designMaster$criticalValues[designMaster$kMax])
                )
            } else {
                designPlan <- data.frame(
                    eventsPerStage = designPlan$eventsPerStage[, 1],
                    criticalValues = designMaster$criticalValues,
                    criticalValuesMirrored = -designMaster$criticalValues
                )
            }

            xParameterName <- "eventsPerStage"
            if (designMaster$sided == 1) {
                if (any(designMaster$futilityBounds > C_FUTILITY_BOUNDS_DEFAULT)) {
                    yParameterNames <- c("futilityBounds", "criticalValues")
                } else {
                    yParameterNames <- "criticalValues"
                }
                yParameterNamesSrc <- yParameterNames
            } else {
                yParameterNames <- c("criticalValues", "criticalValuesMirrored")
                yParameterNamesSrc <- c("criticalValues", paste0("-", designPlanName, "$.design$criticalValues"))
            }

            if (is.na(legendPosition)) {
                legendPosition <- C_POSITION_RIGHT_TOP
            }

            srcCmd <- .showPlotSourceInformation(
                objectName = paste0(designPlanName, "$.design"),
                xParameterName = paste0(designPlanName, "$", xParameterName, "[, 1]"),
                yParameterNames = yParameterNamesSrc,
                hint = showSourceHint, nMax = nMax,
                type = type, showSource = showSource
            )
        } else {
            if (is.na(main)) {
                main <- PlotSubTitleItems(title = "Boundaries")
                .addPlotSubTitleItems(designPlan, designMaster, main, type)
                if (!is.null(reducedParam)) {
                    main$add(reducedParam$title, reducedParam$value, reducedParam$subscript)
                }
            }

            designSet <- TrialDesignSet(design = designMaster, singleDesign = TRUE)
            designSet$.plotSettings <- designPlan$.plotSettings
            designPlanName <- paste0(designPlanName, "$.design")
            return(.plotTrialDesignSet(
                x = designSet, y = NULL, main = main,
                xlab = xlab, ylab = ylab, type = type,
                palette = palette, theta = theta, nMax = nMax,
                plotPointsEnabled = plotPointsEnabled, legendPosition = legendPosition,
                designSetName = designPlanName, showSource = showSource,
                plotSettings = plotSettings # , ...
            ))
        }
    } else if (type == 2) { # Effect Scale Boundary plot
        if (is.na(main)) {
            main <- PlotSubTitleItems(title = "Boundaries Effect Scale")
            .addPlotSubTitleItems(designPlan, designMaster, main, type)
            if (!is.null(reducedParam)) {
                main$add(reducedParam$title, reducedParam$value, reducedParam$subscript)
            }
        }

        if (is.na(ylab)) {
            if (.isTrialDesignPlanMeans(designPlan)) {
                if (designPlan$groups == 1) {
                    ylab <- "Mean"
                } else if (!designPlan$meanRatio) {
                    ylab <- "Mean Difference"
                } else {
                    ylab <- "Mean Ratio"
                }
            } else if (.isTrialDesignPlanRates(designPlan)) {
                if (designPlan$groups == 1) {
                    ylab <- "Rate"
                } else if (!designPlan$riskRatio) {
                    ylab <- "Rate Difference"
                } else {
                    ylab <- "Risk Ratio"
                }
            } else if (survivalDesignPlanEnabled) {
                ylab <- "Hazard Ratio"
            }
        }

        groupedPlotEnabled <- FALSE
        yParameterNamesSrc <- c()
        if (designMaster$sided == 1) {
            if (any(designMaster$futilityBounds > C_FUTILITY_BOUNDS_DEFAULT)) {
                data <- data.frame(
                    criticalValuesEffectScale = designPlan$criticalValuesEffectScale[, 1],
                    futilityBoundsEffectScale = c(
                        designPlan$futilityBoundsEffectScale[, 1],
                        designPlan$criticalValuesEffectScale[designMaster$kMax, 1]
                    )
                )
                yParameterNamesSrc <- c(yParameterNamesSrc, "criticalValuesEffectScale[, 1]")
                yParameterNamesSrc <- c(yParameterNamesSrc, paste0(
                    "c(", designPlanName, "$futilityBoundsEffectScale[, 1], ",
                    designPlanName, "$criticalValuesEffectScale[nrow(", designPlanName, "$criticalValuesEffectScale), 1])"
                ))
            } else {
                data <- data.frame(
                    criticalValuesEffectScale = designPlan$criticalValuesEffectScale[, 1]
                )
                yParameterNamesSrc <- c(yParameterNamesSrc, "criticalValuesEffectScale[, 1]")
            }
        } else if (designMaster$typeOfDesign == C_TYPE_OF_DESIGN_PT) {
            data <- data.frame(
                criticalValues = designPlan$criticalValuesEffectScaleUpper[, 1],
                criticalValuesMirrored = designPlan$criticalValuesEffectScaleLower[, 1],
                futilityBounds = c(
                    designPlan$futilityBoundsEffectScaleUpper[, 1],
                    designPlan$criticalValuesEffectScaleUpper[designMaster$kMax, 1]
                ),
                futilityBoundsMirrored = c(
                    designPlan$futilityBoundsEffectScaleLower[, 1],
                    designPlan$criticalValuesEffectScaleLower[designMaster$kMax, 1]
                )
            )
            yParameterNamesSrc <- c(yParameterNamesSrc, "criticalValuesEffectScaleUpper[, 1]")
            yParameterNamesSrc <- c(yParameterNamesSrc, "criticalValuesEffectScaleLower[, 1]")
            yParameterNamesSrc <- c(yParameterNamesSrc, paste0(
                "c(", designPlanName, "$futilityBoundsEffectScaleUpper[, 1], ",
                designPlanName, "$criticalValuesEffectScaleUpper[nrow(", designPlanName, "$criticalValuesEffectScaleUpper), 1])"
            ))
            yParameterNamesSrc <- c(yParameterNamesSrc, paste0(
                "c(", designPlanName, "$futilityBoundsEffectScaleLower[, 1], ",
                designPlanName, "$criticalValuesEffectScaleLower[nrow(", designPlanName, "$criticalValuesEffectScaleLower), 1])"
            ))
            groupedPlotEnabled <- TRUE
        } else {
            data <- data.frame(
                criticalValuesEffectScale = designPlan$criticalValuesEffectScaleUpper[, 1],
                criticalValuesEffectScaleMirrored = designPlan$criticalValuesEffectScaleLower[, 1]
            )
            yParameterNamesSrc <- c(yParameterNamesSrc, "criticalValuesEffectScaleUpper[, 1]")
            yParameterNamesSrc <- c(yParameterNamesSrc, "criticalValuesEffectScaleLower[, 1]")
        }

        if (survivalDesignPlanEnabled) {
            xParameterName <- "eventsPerStage"
            xParameterNameSrc <- paste0(designPlanName, "$", xParameterName, "[, 1]")
            data <- cbind(data.frame(eventsPerStage = designPlan$eventsPerStage[, 1]), data)
        } else {
            xParameterName <- "informationRates"
            xParameterNameSrc <- paste0(designPlanName, "$.design$", xParameterName)
            data <- cbind(data.frame(informationRates = designMaster$informationRates), data)
        }
        if (designMaster$sided == 1 || designMaster$typeOfDesign == C_TYPE_OF_DESIGN_PT) {
            if (any(designMaster$futilityBounds > C_FUTILITY_BOUNDS_DEFAULT)) {
                yParameterNames <- c("futilityBoundsEffectScale", "criticalValuesEffectScale")
            } else {
                yParameterNames <- "criticalValuesEffectScale"
            }
        } else {
            yParameterNames <- c("criticalValuesEffectScale", "criticalValuesEffectScaleMirrored")
        }

        if (is.na(legendPosition)) {
            legendPosition <- C_POSITION_RIGHT_TOP
        }

        if (is.na(legendPosition)) {
            legendPosition <- C_POSITION_RIGHT_TOP
        }

        srcCmd <- .showPlotSourceInformation(
            objectName = designPlanName,
            xParameterName = xParameterNameSrc,
            yParameterNames = yParameterNamesSrc,
            hint = showSourceHint, nMax = nMax,
            type = type, showSource = showSource
        )

        if (groupedPlotEnabled) {
            tableColumnNames <- C_TABLE_COLUMN_NAMES
            criticalValuesName <- designPlan$.getDataFrameColumnCaption("criticalValuesEffectScale", tableColumnNames, TRUE)
            futilityBoundsName <- designPlan$.getDataFrameColumnCaption("futilityBoundsEffectScale", tableColumnNames, TRUE)

            designPlan <- data.frame(
                xValues = rep(data[[xParameterName]], 4),
                yValues = c(
                    data$criticalValues, data$criticalValuesMirrored,
                    data$futilityBounds, data$futilityBoundsMirrored
                ),
                categories = c(
                    rep(criticalValuesName, nrow(data)), rep("criticalValuesMirrored", nrow(data)),
                    rep(futilityBoundsName, nrow(data)), rep("futilityBoundsMirrored", nrow(data))
                ),
                groups = c(rep(criticalValuesName, 2 * nrow(data)), rep(futilityBoundsName, 2 * nrow(data)))
            )
        } else {
            designPlan <- data
        }
    } else if (type == 3) { # Stage Levels
        if (is.na(main)) {
            main <- PlotSubTitleItems(title = "Boundaries p Values Scale")
            .addPlotSubTitleItems(designPlan, designMaster, main, type)
            if (!is.null(reducedParam)) {
                main$add(reducedParam$title, reducedParam$value, reducedParam$subscript)
            }
        }

        if (survivalDesignPlanEnabled) {
            xParameterName <- "eventsPerStage"
            yParameterNames <- "stageLevels"
            designPlan <- data.frame(
                eventsPerStage = designPlan$eventsPerStage[, 1],
                stageLevels = designMaster$stageLevels
            )
            xParameterNameSrc <- "eventsPerStage[, 1]"
            yParameterNamesSrc <- ".design$stageLevels"
        } else {
            xParameterName <- "informationRates"
            yParameterNames <- "stageLevels"
            designPlan <- TrialDesignSet(design = designMaster, singleDesign = TRUE)
            xParameterNameSrc <- ".design$informationRates"
            yParameterNamesSrc <- ".design$stageLevels"
        }

        srcCmd <- .showPlotSourceInformation(
            objectName = designPlanName,
            xParameterName = xParameterNameSrc,
            yParameterNames = yParameterNamesSrc,
            hint = showSourceHint, nMax = nMax,
            type = type, showSource = showSource
        )
    } else if (type == 4) { # Alpha Spending
        if (is.na(main)) {
            main <- PlotSubTitleItems(title = "Error Spending")
            .addPlotSubTitleItems(designPlan, designMaster, main, type)
            if (!is.null(reducedParam)) {
                main$add(reducedParam$title, reducedParam$value, reducedParam$subscript)
            }
        }
        if (survivalDesignPlanEnabled) {
            xParameterName <- "eventsPerStage"
            yParameterNames <- "alphaSpent"
            designPlan <- data.frame(
                eventsPerStage = designPlan$eventsPerStage[, 1],
                alphaSpent = designMaster$alphaSpent
            )
            xParameterNameSrc <- "eventsPerStage[, 1]"
            yParameterNamesSrc <- ".design$alphaSpent"
        } else {
            xParameterName <- "informationRates"
            yParameterNames <- "alphaSpent"
            designPlan <- TrialDesignSet(design = designMaster, singleDesign = TRUE)
            xParameterNameSrc <- ".design$informationRates"
            yParameterNamesSrc <- ".design$alphaSpent"
        }
        plotPointsEnabled <- ifelse(is.na(plotPointsEnabled), FALSE, plotPointsEnabled)

        srcCmd <- .showPlotSourceInformation(
            objectName = designPlanName,
            xParameterName = xParameterNameSrc,
            yParameterNames = yParameterNamesSrc,
            hint = showSourceHint, nMax = nMax,
            type = type, showSource = showSource
        )
    } else if (type == 5) { # Power and Stopping Probabilities

        .assertIsValidVariedParameterVectorForPlotting(designPlan, type)

        if (designPlan$.isSampleSizeObject()) {
            if (is.na(main)) {
                main <- PlotSubTitleItems(title = "Sample Size")
                .addPlotSubTitleItems(designPlan, designMaster, main, type)
            }

            yAxisScalingEnabled <- TRUE

            if (.isTrialDesignPlanMeans(designPlan)) {
                xParameterName <- "alternative"
                yParameterNames <- c("nFixed")
                if (designMaster$kMax > 1) {
                    yParameterNames <- c(yParameterNames, "maxNumberOfSubjects", "expectedNumberOfSubjectsH1")
                }
                if (is.na(ylab)) {
                    ylab <- "Sample Size"
                }
                yAxisScalingEnabled <- FALSE
                if (is.na(legendPosition)) {
                    legendPosition <- C_POSITION_RIGHT_TOP
                }
                yParameterNamesSrc <- yParameterNames
            } else if (.isTrialDesignPlanRates(designPlan)) {
                xParameterName <- "pi1"
                yParameterNames <- c("nFixed")
                if (designMaster$kMax > 1) {
                    yParameterNames <- c(yParameterNames, "maxNumberOfSubjects", "expectedNumberOfSubjectsH1")
                }
                if (is.na(ylab)) {
                    ylab <- "Sample Size"
                }
                yAxisScalingEnabled <- FALSE
                if (is.na(legendPosition)) {
                    legendPosition <- C_POSITION_RIGHT_TOP
                }
                yParameterNamesSrc <- yParameterNames
            } else if (survivalDesignPlanEnabled) {
                designPlan <- data.frame(
                    hazardRatio = designPlan$hazardRatio,
                    eventsFixed = designPlan$eventsFixed,
                    maxNumberOfEvents = designPlan$eventsPerStage[designMaster$kMax, ],
                    expectedEventsH1 = designPlan$expectedEventsH1
                )
                xParameterName <- "hazardRatio"
                yParameterNames <- c("eventsFixed")
                if (designMaster$kMax > 1) {
                    yParameterNames <- c(yParameterNames, "maxNumberOfEvents", "expectedEventsH1")
                }
                if (is.na(ylab)) {
                    ylab <- "# Events"
                }

                if (is.na(legendPosition)) {
                    legendPosition <- C_POSITION_RIGHT_TOP
                }
                yParameterNamesSrc <- c(
                    "eventsFixed",
                    paste0("eventsPerStage[", designMaster$kMax, ", ]"), "expectedEventsH1"
                )
            }

            srcCmd <- .showPlotSourceInformation(
                objectName = designPlanName,
                xParameterName = xParameterName,
                yParameterNames = yParameterNamesSrc,
                hint = showSourceHint, nMax = nMax,
                type = type, showSource = showSource
            )
            if (!is.null(srcCmd)) {
                if (.isSpecialPlotShowSourceArgument(showSource)) {
                    return(invisible(srcCmd))
                }
                return(srcCmd)
            }

            return(.plotParameterSet(
                parameterSet = designPlan, designMaster = designMaster,
                xParameterName = xParameterName,
                yParameterNames = yParameterNames, mainTitle = main, xlab = xlab, ylab = ylab,
                palette = palette, theta = theta, nMax = nMax, plotPointsEnabled = plotPointsEnabled,
                legendPosition = legendPosition, variedParameters = variedParameters,
                qnormAlphaLineEnabled = FALSE, yAxisScalingEnabled = FALSE,
                plotSettings = plotSettings # , ...
            ))
        } else {
            if (is.na(main)) {
                main <- PlotSubTitleItems(title = "Overall Power and Early Stopping")
                .addPlotSubTitleItems(designPlan, designMaster, main, type)
            }
            if (survivalDesignPlanEnabled) {
                xParameterName <- "hazardRatio"
            } else {
                xParameterName <- "effect"
            }
            yParameterNames <- c("overallReject", "futilityStop", "earlyStop")

            if (is.na(ylab)) {
                ylab <- ""
            }
            if (is.na(legendPosition)) {
                legendPosition <- C_POSITION_LEFT_TOP
            }

            srcCmd <- .showPlotSourceInformation(
                objectName = designPlanName,
                xParameterName = xParameterName,
                yParameterNames = yParameterNames,
                hint = showSourceHint, nMax = nMax,
                type = type, showSource = showSource
            )
            if (!is.null(srcCmd)) {
                if (.isSpecialPlotShowSourceArgument(showSource)) {
                    return(invisible(srcCmd))
                }
                return(srcCmd)
            }

            if (is.null(list(...)[["ylim"]])) {
                ylim <- c(0, 1)
                return(.plotParameterSet(
                    parameterSet = designPlan, designMaster = designMaster,
                    xParameterName = xParameterName,
                    yParameterNames = yParameterNames, mainTitle = main, xlab = xlab, ylab = ylab,
                    palette = palette, theta = theta, nMax = nMax, plotPointsEnabled = plotPointsEnabled,
                    legendPosition = legendPosition, variedParameters = variedParameters,
                    qnormAlphaLineEnabled = FALSE, yAxisScalingEnabled = FALSE,
                    plotSettings = plotSettings, ylim = ylim # , ...
                ))
            } else {
                return(.plotParameterSet(
                    parameterSet = designPlan, designMaster = designMaster,
                    xParameterName = xParameterName,
                    yParameterNames = yParameterNames, mainTitle = main, xlab = xlab, ylab = ylab,
                    palette = palette, theta = theta, nMax = nMax, plotPointsEnabled = plotPointsEnabled,
                    legendPosition = legendPosition, variedParameters = variedParameters,
                    qnormAlphaLineEnabled = FALSE, yAxisScalingEnabled = FALSE,
                    plotSettings = plotSettings # , ...
                ))
            }
        }
    } else if (type == 6) { # Average Sample Size / Average Event Number
        .assertIsValidVariedParameterVectorForPlotting(designPlan, type)

        if (is.na(main)) {
            titlePart <- ifelse(survivalDesignPlanEnabled, "Number of Events", "Sample Size")
            main <- PlotSubTitleItems(title = paste0("Expected ", titlePart, " and Power / Early Stop"))
            .addPlotSubTitleItems(designPlan, designMaster, main, type)
        }

        if (survivalDesignPlanEnabled) {
            xParameterName <- "hazardRatio"
            yParameterNames <- "expectedNumberOfEvents"
            expectedNumberOfEvents <- designPlan[["expectedNumberOfEvents"]]
            if (is.null(expectedNumberOfEvents) || length(expectedNumberOfEvents) == 0) {
                yParameterNames <- "expectedEventsH1"
            }
            yParameterNames <- c(yParameterNames, "overallReject", "earlyStop") # overallReject = power
            if (is.na(legendPosition)) {
                legendPosition <- C_POSITION_RIGHT_CENTER
            }
        } else {
            xParameterName <- "effect"
            yParameterNames <- c("expectedNumberOfSubjects", "overallReject", "earlyStop") # overallReject = power
        }
        srcCmd <- .showPlotSourceInformation(
            objectName = designPlanName,
            xParameterName = xParameterName,
            yParameterNames = yParameterNames,
            hint = showSourceHint, nMax = nMax,
            type = type, showSource = showSource
        )
    } else if (type == 7) {
        .assertIsValidVariedParameterVectorForPlotting(designPlan, type)

        if (is.na(main)) {
            main <- PlotSubTitleItems(title = "Overall Power")
            .addPlotSubTitleItems(designPlan, designMaster, main, type)
        }

        if (survivalDesignPlanEnabled) {
            xParameterName <- "hazardRatio"
        } else {
            xParameterName <- "effect"
        }
        yParameterNames <- "overallReject"
        if (is.na(legendPosition)) {
            legendPosition <- C_POSITION_RIGHT_CENTER
        }
        srcCmd <- .showPlotSourceInformation(
            objectName = designPlanName,
            xParameterName = xParameterName,
            yParameterNames = yParameterNames,
            hint = showSourceHint, nMax = nMax,
            type = type, showSource = showSource
        )
    } else if (type == 8) {
        .assertIsValidVariedParameterVectorForPlotting(designPlan, type)

        if (is.na(main)) {
            main <- PlotSubTitleItems(title = "Overall Early Stopping")
            .addPlotSubTitleItems(designPlan, designMaster, main, type)
        }

        if (survivalDesignPlanEnabled) {
            xParameterName <- "hazardRatio"
        } else {
            xParameterName <- "effect"
        }
        yParameterNames <- c("earlyStop", "futilityStop")
        if (is.na(legendPosition)) {
            legendPosition <- C_POSITION_RIGHT_CENTER
        }
        srcCmd <- .showPlotSourceInformation(
            objectName = designPlanName,
            xParameterName = xParameterName,
            yParameterNames = yParameterNames,
            hint = showSourceHint, nMax = nMax,
            type = type, showSource = showSource
        )
    } else if (type == 9) {
        .assertIsValidVariedParameterVectorForPlotting(designPlan, type)

        if (is.na(main)) {
            if (survivalDesignPlanEnabled) {
                main <- PlotSubTitleItems(title = "Expected Number of Events")
            } else {
                main <- PlotSubTitleItems(title = "Expected Sample Size")
            }
            .addPlotSubTitleItems(designPlan, designMaster, main, type)
        }

        if (survivalDesignPlanEnabled) {
            xParameterName <- "hazardRatio"
            yParameterNames <- "expectedNumberOfEvents"
            expectedNumberOfEvents <- designPlan[["expectedNumberOfEvents"]]
            if (is.null(expectedNumberOfEvents) || length(expectedNumberOfEvents) == 0) {
                yParameterNames <- c("expectedEventsH0", "expectedEventsH1")
                if (is.na(legendPosition)) {
                    legendPosition <- C_POSITION_RIGHT_CENTER
                }
            }
        } else {
            xParameterName <- "effect"
            yParameterNames <- "expectedNumberOfSubjects"
        }
        srcCmd <- .showPlotSourceInformation(
            objectName = designPlanName,
            xParameterName = xParameterName,
            yParameterNames = yParameterNames,
            hint = showSourceHint, nMax = nMax,
            type = type, showSource = showSource
        )
    } else if (survivalDesignPlanEnabled) {
        if (type == 10) { # Study Duration
            .assertIsValidVariedParameterVectorForPlotting(designPlan, type)
            if (is.na(main)) {
                main <- PlotSubTitleItems(title = "Study Duration")
                .addPlotSubTitleItems(designPlan, designMaster, main, type)
            }
            xParameterName <- "hazardRatio"
            yParameterNames <- "studyDuration"
            srcCmd <- .showPlotSourceInformation(
                objectName = designPlanName,
                xParameterName = xParameterName,
                yParameterNames = yParameterNames,
                hint = showSourceHint, nMax = nMax,
                type = type, showSource = showSource
            )
        } else if (type == 11) {
            .assertIsValidVariedParameterVectorForPlotting(designPlan, type)
            if (is.na(main)) {
                main <- PlotSubTitleItems(title = "Expected Number of Subjects")
                .addPlotSubTitleItems(designPlan, designMaster, main, type)
            }
            xParameterName <- "hazardRatio"
            yParameterNames <- "expectedNumberOfSubjects"
            srcCmd <- .showPlotSourceInformation(
                objectName = designPlanName,
                xParameterName = xParameterName,
                yParameterNames = yParameterNames,
                hint = showSourceHint, nMax = nMax,
                type = type, showSource = showSource
            )
        } else if (type == 12) { # Analysis Time
            .assertIsValidVariedParameterVectorForPlotting(designPlan, type)
            if (is.na(main)) {
                main <- PlotSubTitleItems(title = "Analysis Time")
                .addPlotSubTitleItems(designPlan, designMaster, main, type)
            }

            xParameterName <- "hazardRatio"
            yParameterNames <- "analysisTime"
            yParameterNamesSrc <- c()
            for (i in 1:nrow(designPlan[["analysisTime"]])) {
                yParameterNamesSrc <- c(yParameterNamesSrc, paste0("analysisTime[", i, ", ]"))
            }

            data <- NULL
            for (k in 1:designMaster$kMax) {
                part <- data.frame(
                    categories = rep(k, length(designPlan$hazardRatio)),
                    xValues = designPlan$hazardRatio,
                    yValues = designPlan$analysisTime[k, ]
                )
                if (is.null(data)) {
                    data <- part
                } else {
                    data <- rbind(data, part)
                }
            }

            srcCmd <- .showPlotSourceInformation(
                objectName = designPlanName,
                xParameterName = xParameterName,
                yParameterNames = yParameterNamesSrc,
                hint = showSourceHint,
                type = type, showSource = showSource
            )
            if (!is.null(srcCmd)) {
                if (.isSpecialPlotShowSourceArgument(showSource)) {
                    return(invisible(srcCmd))
                }
                return(srcCmd)
            }

            return(.plotDataFrame(data,
                mainTitle = main,
                xlab = NA_character_, ylab = NA_character_, xAxisLabel = "Hazard Ratio",
                yAxisLabel1 = "Analysis Time", yAxisLabel2 = NA_character_,
                plotPointsEnabled = TRUE, legendTitle = "Stage",
                legendPosition = legendPosition, sided = designMaster$sided,
                plotSettings = plotSettings, ...
            ))
        } else if (type == 13 || type == 14) { # Cumulative Distribution Function / Survival function
            return(.plotSurvivalFunction(designPlan,
                designMaster = designMaster, type = type, main = main,
                xlab = xlab, ylab = ylab, palette = palette,
                legendPosition = legendPosition, showSource = showSource,
                designPlanName = designPlanName,
                plotSettings = plotSettings, ...
            ))
        } else {
            stop(C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "'type' (", type, ") is not allowed; must be 1, 2, ..., 14")
        }
    } else {
        stop(C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "'type' (", type, ") is not allowed; must be 1, 2, ..., 9")
    }

    if (!is.null(srcCmd)) {
        if (.isSpecialPlotShowSourceArgument(showSource)) {
            return(invisible(srcCmd))
        }
        return(srcCmd)
    }

    p <- .plotParameterSet(
        parameterSet = designPlan, designMaster = designMaster,
        xParameterName = xParameterName,
        yParameterNames = yParameterNames, mainTitle = main, xlab = xlab, ylab = ylab,
        palette = palette, theta = theta, nMax = nMax, plotPointsEnabled = plotPointsEnabled,
        legendPosition = legendPosition, variedParameters = variedParameters,
        qnormAlphaLineEnabled = (type != 2), ratioEnabled = ratioEnabled,
        plotSettings = plotSettings # , ...
    )

    if (type == 1 && survivalDesignPlanEnabled) {
        p <- .addDecistionCriticalValuesToPlot(p = p, designMaster = designMaster, type = type, nMax = nMax)
    }
    return(p)
}

.getSurvivalFunctionPlotCommand <- function(functionType = c("pwExpDist", "lambdaStep"), timeValues, lambda,
        designPlan, type, piecewiseSurvivalEnabled, multiplyByHazardRatio = FALSE) {
    functionType <- match.arg(functionType)
    signPrefix <- ifelse(type == 13, "", "-")
    if (functionType == "pwExpDist") {
        functionName <- "getPiecewiseExponentialDistribution"
    } else {
        functionName <- "getLambdaStepFunction"
    }
    cmd <- paste0(
        signPrefix, functionName,
        "(", .reconstructSequenceCommand(timeValues),
        ", piecewiseLambda = ", .arrayToString(lambda, vectorLookAndFeelEnabled = TRUE)
    )
    if (piecewiseSurvivalEnabled) {
        cmd <- paste0(
            cmd, ", piecewiseSurvivalTime = ",
            .arrayToString(designPlan$piecewiseSurvivalTime, vectorLookAndFeelEnabled = TRUE)
        )
    }
    if (functionType == "pwExpDist") {
        cmd <- paste0(cmd, ", kappa = ", designPlan$kappa)
    }
    cmd <- paste0(cmd, ")")
    if (multiplyByHazardRatio) {
        cmd <- paste0(cmd, " * ", designPlan$hazardRatio[1])
    }
    return(cmd)
}

# Cumulative Distribution Function / Survival function
.plotSurvivalFunction <- function(designPlan, ..., designMaster, type = c(13, 14), main = NA_character_,
        xlab = NA_character_, ylab = NA_character_, palette = "Set1",
        legendPosition = NA_integer_, showSource = FALSE,
        designPlanName = NA_character_, plotSettings = NULL) {
    startTime <- Sys.time()
    if (is.null(designPlan$piecewiseSurvivalTime) ||
            length(designPlan$piecewiseSurvivalTime) == 0) {
        stop(C_EXCEPTION_TYPE_MISSING_ARGUMENT, "'piecewiseSurvivalTime' must be specified")
    }

    type <- type[1]
    if (!(type %in% c(13, 14))) {
        stop(C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "'type' must be 13 or 14")
    }

    lambda1 <- designPlan[["lambda1"]]
    lambda2 <- designPlan[["lambda2"]]
    if (is.null(lambda2) || length(lambda2) == 0) {
        stop(C_EXCEPTION_TYPE_MISSING_ARGUMENT, "'lambda2' must be specified")
    }

    if (is.null(designPlan$kappa) || length(designPlan$kappa) == 0) {
        stop(C_EXCEPTION_TYPE_MISSING_ARGUMENT, "'kappa' must be specified")
    }

    if (is.null(designPlan$hazardRatio) || length(designPlan$hazardRatio) == 0) {
        stop(C_EXCEPTION_TYPE_MISSING_ARGUMENT, "'hazardRatio' must be specified")
    }

    piecewiseSurvivalEnabled <- designPlan$.piecewiseSurvivalTime$piecewiseSurvivalEnabled

    if (is.na(main)) {
        if (type == 13) {
            main <- PlotSubTitleItems(title = "Cumulative Distribution Function")
        } else {
            main <- PlotSubTitleItems(title = "Survival Function")
        }
        .addPlotSubTitleItems(designPlan, designMaster, main, type)
        if (!piecewiseSurvivalEnabled) {
            if (designPlan$.piecewiseSurvivalTime$.isLambdaBased(minNumberOfLambdas = 1)) {
                main$add("lambda", round(designPlan$lambda1[1], 4), 1)
                main$add("lambda", round(designPlan$lambda2, 4), 2)
            } else {
                main$add("pi", round(designPlan$pi1[1], 3), 1)
                main$add("pi", round(designPlan$pi2, 3), 2)
            }
        } else if (length(designPlan$hazardRatio) == 1) {
            main$add("Hazard Ratio", round(designPlan$hazardRatio[1], 3))
        }
    }

    if (!piecewiseSurvivalEnabled || (length(designPlan$piecewiseSurvivalTime) == 1 &&
            designPlan$piecewiseSurvivalTime[1] == 0)) {
        timeTo <- max(designPlan$analysisTime[designMaster$kMax, ])
    } else {
        timeTo <- max(designPlan$piecewiseSurvivalTime)
    }
    if (is.na(timeTo) || !is.numeric(timeTo) || is.infinite(timeTo)) {
        # warning("Unable to determine upper bound of time values", call. = FALSE)
        timeTo <- 0
    }

    timeTo <- timeTo + 10
    by <- timeTo / 1000
    timeValues <- seq(from = 0, to = timeTo, by = by)

    data <- data.frame(
        time = timeValues,
        lambdaGroup1 = rep(-1, length(timeValues)),
        lambdaGroup2 = rep(-1, length(timeValues)),
        survival1 = rep(-1, length(timeValues)),
        survival2 = rep(-1, length(timeValues)),
        survivalGroup1 = rep(-1, length(timeValues)),
        survivalGroup2 = rep(-1, length(timeValues))
    )

    signPrefix <- ifelse(type == 13, "", "-")
    if (piecewiseSurvivalEnabled) {
        data$survival2 <- .getPiecewiseExponentialDistribution(
            timeValues,
            lambda2, designPlan$piecewiseSurvivalTime, designPlan$kappa
        )

        yParameterNames <- .getSurvivalFunctionPlotCommand(
            "pwExpDist",
            timeValues, lambda2, designPlan, type, piecewiseSurvivalEnabled
        )

        if (!is.null(lambda1) && !is.na(lambda1) &&
                length(lambda1) == length(lambda2)) {
            data$survival1 <- .getPiecewiseExponentialDistribution(
                timeValues,
                lambda1, designPlan$piecewiseSurvivalTime, designPlan$kappa
            )
            yParameterNames <- c(
                yParameterNames,
                .getSurvivalFunctionPlotCommand(
                    "pwExpDist",
                    timeValues, lambda1, designPlan, type, piecewiseSurvivalEnabled
                )
            )
        } else {
            .warnInCaseOfUnusedValuesForPlottingSurvival(designPlan$hazardRatio)
            data$survival1 <- data$survival2 * designPlan$hazardRatio[1]
            yParameterNames <- c(
                yParameterNames,
                .getSurvivalFunctionPlotCommand("pwExpDist", timeValues, lambda2,
                    designPlan, type, piecewiseSurvivalEnabled,
                    multiplyByHazardRatio = TRUE
                )
            )
        }

        yParameterNames <- c(
            yParameterNames,
            .getSurvivalFunctionPlotCommand(
                "lambdaStep",
                timeValues, lambda2, designPlan, type, piecewiseSurvivalEnabled
            )
        )
        if (!is.null(lambda1) && !is.na(lambda1) &&
                length(lambda1) == length(lambda2)) {
            yParameterNames <- c(
                yParameterNames,
                .getSurvivalFunctionPlotCommand(
                    "lambdaStep",
                    timeValues, lambda1, designPlan, type, piecewiseSurvivalEnabled
                )
            )
        } else {
            yParameterNames <- c(
                yParameterNames,
                .getSurvivalFunctionPlotCommand("lambdaStep", timeValues, lambda2,
                    designPlan, type, piecewiseSurvivalEnabled,
                    multiplyByHazardRatio = TRUE
                )
            )
        }
    } else {
        if (designPlan$.piecewiseSurvivalTime$.isLambdaBased(minNumberOfLambdas = 1)) {
            if (length(designPlan$lambda1) > 1) {
                lambda1 <- designPlan$lambda1[1]
                warning("Only the first 'lambda1' (", round(lambda1, 4),
                    ") was used for plotting",
                    call. = FALSE
                )
            }
        } else {
            .warnInCaseOfUnusedValuesForPlottingRates(designPlan$pi1)
        }

        if (!is.na(designPlan$pi1[1]) && !is.na(designPlan$pi2) && !is.na(designPlan$eventTime)) {
            lambda2 <- (-log(1 - designPlan$pi2))^(1 / designPlan$kappa) / designPlan$eventTime
            lambda1 <- (-log(1 - designPlan$pi1[1]))^(1 / designPlan$kappa) / designPlan$eventTime
        }

        data$survival2 <- .getPiecewiseExponentialDistribution(
            timeValues,
            lambda2, 0, designPlan$kappa
        )
        data$survival1 <- .getPiecewiseExponentialDistribution(
            timeValues,
            lambda1, 0, designPlan$kappa
        )

        yParameterNames <- .getSurvivalFunctionPlotCommand(
            "pwExpDist",
            timeValues, lambda2, designPlan, type, piecewiseSurvivalEnabled
        )
        yParameterNames <- c(
            yParameterNames,
            .getSurvivalFunctionPlotCommand(
                "pwExpDist",
                timeValues, lambda1, designPlan, type, piecewiseSurvivalEnabled
            )
        )
        yParameterNames <- c(
            yParameterNames,
            .getSurvivalFunctionPlotCommand(
                "lambdaStep",
                timeValues, lambda2, designPlan, type, piecewiseSurvivalEnabled
            )
        )
        yParameterNames <- c(
            yParameterNames,
            .getSurvivalFunctionPlotCommand(
                "lambdaStep", timeValues, lambda1,
                designPlan, type, piecewiseSurvivalEnabled
            )
        )
    }

    # two groups: 1 = treatment, 2 = control
    if (type == 14) {
        data$survival1 <- 1 - data$survival1
        data$survival2 <- 1 - data$survival2
    }

    if (piecewiseSurvivalEnabled) {
        data$lambdaGroup2 <- .getLambdaStepFunction(
            timeValues,
            designPlan$piecewiseSurvivalTime, lambda2
        )
        if (length(lambda1) == 1) {
            if (!is.na(lambda1)) {
                data$lambdaGroup1 <- rep(lambda1, length(data$lambdaGroup2))
            } else {
                data$lambdaGroup1 <- data$lambdaGroup2 * designPlan$hazardRatio[1]
            }
        } else {
            data$lambdaGroup1 <- .getLambdaStepFunction(
                timeValues,
                designPlan$piecewiseSurvivalTime, lambda1
            )
        }
    } else {
        data$lambdaGroup2 <- .getLambdaStepFunction(timeValues, 0, lambda2)
        data$lambdaGroup1 <- .getLambdaStepFunction(timeValues, 0, lambda1)
    }

    scalingBaseValues1 <- na.omit(c(data$survival1, data$survival2))
    scalingBaseValues2 <- na.omit(c(data$lambdaGroup1, data$lambdaGroup2))
    scalingFactor <- 1
    if (length(scalingBaseValues1) > 0 && length(scalingBaseValues2) > 0) {
        scalingFactor <- max(scalingBaseValues1) / max(.getNextHigherValue(scalingBaseValues2))
    }
    data2 <- data.frame(
        categories = c(
            rep("Treatm. piecew. exp.", nrow(data)),
            rep("Control piecew. exp.", nrow(data)),
            rep("Treatm. piecew. lambda", nrow(data)),
            rep("Control piecew. lambda", nrow(data))
        ),
        xValues = rep(data$time, 4),
        yValues = c(
            data$survival1,
            data$survival2,
            data$lambdaGroup1 * scalingFactor,
            data$lambdaGroup2 * scalingFactor
        )
    )

    if (is.na(legendPosition)) {
        if (type == 13) {
            legendPosition <- C_POSITION_LEFT_TOP
        } else {
            legendPosition <- C_POSITION_RIGHT_TOP
        }
    }

    if (is.na(palette) || palette == "Set1") {
        palette <- "Paired"
    }

    if (type == 13) {
        yAxisLabel1 <- "Cumulative Distribution Function"
    } else {
        yAxisLabel1 <- "Survival Function"
    }

    srcCmd <- .showPlotSourceInformation(
        objectName = designPlanName,
        xParameterName = "time",
        yParameterNames = yParameterNames,
        showSource = showSource,
        xValues = timeValues
    )
    if (!is.null(srcCmd)) {
        if (.isSpecialPlotShowSourceArgument(showSource)) {
            return(invisible(srcCmd))
        }
        return(srcCmd)
    }

    if (is.null(plotSettings)) {
        plotSettings <- designPlan$.plotSettings
    }

    return(.plotDataFrame(data2,
        mainTitle = main,
        xlab = xlab, ylab = ylab, xAxisLabel = "Time",
        yAxisLabel1 = yAxisLabel1, yAxisLabel2 = "Lambda",
        plotPointsEnabled = FALSE, legendTitle = NA_character_,
        legendPosition = legendPosition, scalingFactor1 = 1,
        scalingFactor2 = scalingFactor, palette = palette, sided = designMaster$sided,
        plotSettings = plotSettings
    ))
}

.warnInCaseOfUnusedValuesForPlottingMeans <- function(alternative) {
    if (length(alternative) > 1) {
        warning("Only the first 'alternative' (", round(alternative[1], 3),
            ") was used for plotting",
            call. = FALSE
        )
        return(list(title = "alternative", value = alternative[1], subscript = NA_character_))
    }
    return(NULL)
}

.warnInCaseOfUnusedValuesForPlottingRates <- function(pi1) {
    if (length(pi1) > 1) {
        warning("Only the first 'pi1' (", round(pi1[1], 3),
            ") was used for plotting",
            call. = FALSE
        )
        return(list(title = "pi", value = pi1[1], subscript = "1"))
    }
    return(NULL)
}

.warnInCaseOfUnusedValuesForPlottingSurvival <- function(hazardRatio) {
    if (length(hazardRatio) > 1) {
        warning("Only the first 'hazardRatio' (", round(hazardRatio[1], 3),
            ") was used for plotting",
            call. = FALSE
        )
        return(list(title = "hazardRatio", value = hazardRatio[1], subscript = NA_character_))
    }
    return(NULL)
}

.warnInCaseOfUnusedValuesForPlotting <- function(designPlan) {
    if (.isTrialDesignPlanMeans(designPlan) && designPlan$.isSampleSizeObject()) {
        return(.warnInCaseOfUnusedValuesForPlottingMeans(designPlan$alternative))
    }
    if (.isTrialDesignPlanRates(designPlan) && designPlan$.isSampleSizeObject()) {
        return(.warnInCaseOfUnusedValuesForPlottingRates(designPlan$pi1))
    }
    if (.isTrialDesignPlanSurvival(designPlan) && designPlan$.isSampleSizeObject()) {
        return(.warnInCaseOfUnusedValuesForPlottingSurvival(designPlan$hazardRatio))
    }
    return(NULL)
}

#'
#' @title
#' Trial Design Plan Plotting
#'
#' @param x The trial design plan, obtained from \cr
#'        \code{\link[=getSampleSizeMeans]{getSampleSizeMeans()}}, \cr
#'        \code{\link[=getSampleSizeRates]{getSampleSizeRates()}}, \cr
#'        \code{\link[=getSampleSizeSurvival]{getSampleSizeSurvival()}}, \cr
#'        \code{\link[=getPowerMeans]{getPowerMeans()}}, \cr
#'        \code{\link[=getPowerRates]{getPowerRates()}} or \cr
#'        \code{\link[=getPowerSurvival]{getPowerSurvival()}}.
#' @param y Not available for this kind of plot (is only defined to be compatible to the generic plot function).
#' @param main The main title.
#' @param xlab The x-axis label.
#' @param ylab The y-axis label.
#' @inheritParams param_palette
#' @inheritParams param_theta
#' @inheritParams param_plotPointsEnabled
#' @inheritParams param_showSource
#' @inheritParams param_plotSettings
#' @inheritParams param_legendPosition
#' @inheritParams param_grid
#' @param type The plot type (default = \code{1}). The following plot types are available:
#' \itemize{
#'   \item \code{1}: creates a 'Boundaries' plot
#'   \item \code{2}: creates a 'Boundaries Effect Scale' plot
#'   \item \code{3}: creates a 'Boundaries p Values Scale' plot
#'   \item \code{4}: creates a 'Error Spending' plot
#'   \item \code{5}: creates a 'Sample Size' or 'Overall Power and Early Stopping' plot
#'   \item \code{6}: creates a 'Number of Events' or 'Sample Size' plot
#'   \item \code{7}: creates an 'Overall Power' plot
#'   \item \code{8}: creates an 'Overall Early Stopping' plot
#'   \item \code{9}: creates an 'Expected Number of Events' or 'Expected Sample Size' plot
#'   \item \code{10}: creates a 'Study Duration' plot
#'   \item \code{11}: creates an 'Expected Number of Subjects' plot
#'   \item \code{12}: creates an 'Analysis Times' plot
#'   \item \code{13}: creates a 'Cumulative Distribution Function' plot
#'   \item \code{14}: creates a 'Survival Function' plot
#'   \item \code{"all"}: creates all available plots and returns it as a grid plot or list
#' }
#' @inheritParams param_three_dots_plot
#'
#' @description
#' Plots a trial design plan.
#'
#' @details
#' Generic function to plot all kinds of trial design plans.
#'
#' @examples
#' \dontrun{
#' if (require(ggplot2)) plot(getSampleSizeMeans())
#' }
#'
#' @template return_object_ggplot
#'
#' @export
#'
plot.TrialDesignPlan <- function(x, y, ..., main = NA_character_,
        xlab = NA_character_, ylab = NA_character_,
        type = ifelse(x$.design$kMax == 1, 5L, 1L), palette = "Set1",
        theta = seq(-1, 1, 0.01), plotPointsEnabled = NA,
        legendPosition = NA_integer_, showSource = FALSE,
        grid = 1, plotSettings = NULL) {
    fCall <- match.call(expand.dots = FALSE)
    designPlanName <- deparse(fCall$x)
    .assertGgplotIsInstalled()
    .assertIsSingleInteger(grid, "grid", validateType = FALSE)

    nMax <- list(...)[["nMax"]]
    if (!is.null(nMax)) {
        warning(
            C_EXCEPTION_TYPE_ILLEGAL_ARGUMENT, "'nMax' (", nMax,
            ") will be ignored because it will be taken from design plan"
        )
    }

    typeNumbers <- .getPlotTypeNumber(type, x)
    if (is.null(plotSettings)) {
        plotSettings <- .getGridPlotSettings(x, typeNumbers, grid)
    }
    p <- NULL
    plotList <- list()
    for (typeNumber in typeNumbers) {
        p <- .plotTrialDesignPlan(
            designPlan = x,
            main = main, xlab = xlab, ylab = ylab, type = typeNumber,
            palette = palette, theta = theta, plotPointsEnabled = plotPointsEnabled,
            legendPosition = .getGridLegendPosition(legendPosition, typeNumbers, grid),
            showSource = showSource, designPlanName = designPlanName,
            plotSettings = plotSettings, ...
        )
        .printPlotShowSourceSeparator(showSource, typeNumber, typeNumbers)
        if (length(typeNumbers) > 1) {
            caption <- .getPlotCaption(x, typeNumber, stopIfNotFound = TRUE)
            plotList[[caption]] <- p
        }
    }
    if (length(typeNumbers) == 1) {
        if (.isSpecialPlotShowSourceArgument(showSource)) {
            return(invisible(p))
        }

        return(p)
    }

    if (length(plotList) == 0) {
        message("No plots available for the specified design plan for ", x$.toString())
    }

    if (.isSpecialPlotShowSourceArgument(showSource)) {
        return(invisible(plotList))
    }

    return(.createPlotResultObject(plotList, grid))
}

Try the rpact package in your browser

Any scripts or data that you put into this service are public.

rpact documentation built on July 9, 2023, 6:30 p.m.