---
title: "Wrapper Functions of Common Statistical Methods in TrialSimulator"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Wrapper Functions of Common Statistical Methods in TrialSimulator}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  cache.path = 'cache/wrapper/',
  comment = '#>',
  dpi = 300,
  out.width = '100%'
)
```

```{r setup, echo = FALSE, message = FALSE}
library(dplyr)
library(TrialSimulator)
```

The `TrialSimulator` package provides a unified set of wrapper functions that encapsulate statistical methods commonly used in clinical trial simulations. These functions facilitate model fitting, treatment comparisons, and covariate adjustments within a standardized interface.

When multiple active treatment arms are present, each wrapper function automatically performs pairwise comparisons between each active arm and the designated reference (e.g., placebo, control, or standard-of-care). All wrapper functions share a consistent syntax and output structure. Most of them support model specification via an R formula interface, and covariate adjustment is available where appropriate.

Pairwise average treatment effects (ATEs) are estimated using the `emmeans` package under the hood. All tests are one-sided, and the ellipsis (`...`) argument can be used to define data subsets, enabling flexible analyses such as those needed in enrichment designs.

Below is a summary of the available wrapper functions included in this vignette, along with their corresponding statistical methods, output metrics, and support for covariate adjustment.

+------------------------+-------------------------+------------------------+------------------------+
| Function               | Method                  | Statistics in Outputs  | Covariate adjustment   |
+:=======================+:========================+:=======================+:=======================+
| `fitLinear`            | Linear model            | ATE                    | Yes                    |
+------------------------+-------------------------+------------------------+------------------------+
| `fitLogistic`          | Logistic model          | regression coefficient | Yes                    |
|                        |                         |                        |                        |
|                        |                         | log odds ratio         |                        |
|                        |                         |                        |                        |
|                        |                         | odds ratio             |                        |
|                        |                         |                        |                        |
|                        |                         | risk ratio             |                        |
|                        |                         |                        |                        |
|                        |                         | risk difference        |                        |
+------------------------+-------------------------+------------------------+------------------------+
| `fitCoxph`             | Cox PH model            | log hazard ratio       | Yes                    |
|                        |                         |                        |                        |
|                        |                         | hazard ratio           |                        |
+------------------------+-------------------------+------------------------+------------------------+
| `fitLogrank`           | logrank test            |                        | No but supports strata |
+------------------------+-------------------------+------------------------+------------------------+
| `fitFarringtonManning` | Farrington-Manning test |                        | No                     |
+------------------------+-------------------------+------------------------+------------------------+

## Example

To demonstrate the usage of the wrapper functions, we simulate a hypothetical three-arm trial with one control (`pbo`) and two active doses (`low` and `high`). The trial includes a continuous covariate `x`, three endpoint types (time-to-event, continuous, and binary), and a binary biomarker used to define subgroups.

The placebo arm is constructed as follows:

```{r ioeajfls}
## time-to-event endpoint
pfs <- endpoint(name = 'pfs', type = 'tte', generator = rexp, rate = .07)
## continuous endpoint
cep <- endpoint(name = 'cep', type = 'non-tte', 
                readout = c(cep = 0), generator = rnorm)
## binary endpoint
bep <- endpoint(name = 'bep', type = 'non-tte', 
                readout = c(bep = 0), generator = rbinom, size = 1, prob = .1)

## biomarker
bm <- endpoint(name = 'biomarker', type = 'non-tte', 
               readout = c(biomarker = 0), generator = rbinom, 
               size = 1, prob = .7)

## covariate
covar <- endpoint(name = 'x', type = 'non-tte', 
                  readout = c(x = 0), generator = rnorm)

pbo <- arm(name = 'pbo')
pbo$add_endpoints(pfs, cep, bep, bm, covar)
```

For brevity, the code for the low and high dose arms and the trial definition are hidden in this vignette. Refer to the source of this vignette for full code. A single milestone for final analysis is defined, with an empty action `doNothing.` This is because we will explicitly request locked data outside of the action function when demonstrating the wrapper functions.


```{r eualgha, echo=FALSE}
## time-to-event endpoint
pfs <- endpoint(name = 'pfs', type = 'tte', generator = rexp, rate = .06)
## continuous endpoint
cep <- endpoint(name = 'cep', type = 'non-tte', 
                readout = c(cep = 0), generator = rnorm, mean = 1.2)
## binary endpoint
bep <- endpoint(name = 'bep', type = 'non-tte', 
                readout = c(bep = 0), generator = rbinom, size = 1, prob = .2)

## biomarker
bm <- endpoint(name = 'biomarker', type = 'non-tte', 
               readout = c(biomarker = 0), generator = rbinom, 
               size = 1, prob = .7)

## covariate
covar <- endpoint(name = 'x', type = 'non-tte', 
                  readout = c(x = 0), generator = rnorm)

low <- arm(name = 'low')
low$add_endpoints(pfs, cep, bep, bm, covar)

## time-to-event endpoint
pfs <- endpoint(name = 'pfs', type = 'tte', generator = rexp, rate = .04)
## continuous endpoint
cep <- endpoint(name = 'cep', type = 'non-tte', 
                readout = c(cep = 0), generator = rnorm, mean = 1.3)
## binary endpoint
bep <- endpoint(name = 'bep', type = 'non-tte', 
                readout = c(bep = 0), generator = rbinom, size = 1, prob = .35)

## biomarker
bm <- endpoint(name = 'biomarker', type = 'non-tte', 
               readout = c(biomarker = 0), generator = rbinom, 
               size = 1, prob = .7)

## covariate
covar <- endpoint(name = 'x', type = 'non-tte', 
                  readout = c(x = 0), generator = rnorm)

high <- arm(name = 'high')
high$add_endpoints(pfs, cep, bep, bm, covar)

accrual_rate <- data.frame(end_time = c(10, Inf),
                           piecewise_rate = c(30, 50))
trial <- trial(
  name = 'Trial-3415', n_patients = 300,
  seed = 1727811904, duration = 1000,
  enroller = StaggeredRecruiter, accrual_rate = accrual_rate,
  dropout = rexp, rate = -log(1 - 0.1)/18, ## 10% by month 18
  silent = TRUE
)

trial$add_arms(sample_ratio = c(1, 1, 1), pbo, low, high)

final <- milestone(name = 'final', action = doNothing, when = calendarTime(1000))

listener <- listener()
listener$add_milestones(final)

controller <- controller(trial, listener)
```

Now we execute the trial. After simulation, locked data can be retrieved using the `get_locked_data()` method with the milestone name `"final"`.

```{r ieoajf}
controller$run(n = 1, plot_event = FALSE, silent = TRUE)
locked_data <- trial$get_locked_data('final')
head(locked_data)

table(locked_data$arm)
```

## Analyze Time-to-Event Endpoint

We begin by analyzing the time-to-event endpoint `pfs` using both a Cox proportional hazards model and a log-rank test. When performing analysis on a subset defined via the `...` argument, the syntax must be compatible with that of `dplyr::filter()`.

```{r ghkaljf}
## adjust for covariate x
fitCoxph(Surv(pfs, pfs_event) ~ arm + x, placebo = 'pbo', 
         data = locked_data, alternative = 'less', 
         scale = 'hazard ratio')

fitLogrank(Surv(pfs, pfs_event) ~ arm, placebo = 'pbo', 
           data = locked_data, alternative = 'less')

## more details
fitLogrank(Surv(pfs, pfs_event) ~ arm, placebo = 'pbo', 
           data = locked_data, alternative = 'less', tidy = FALSE)

## with strata
fitLogrank(Surv(pfs, pfs_event) ~ arm + strata(biomarker), placebo = 'pbo', 
           data = locked_data, alternative = 'less')

## analyze a subset
fitCoxph(Surv(pfs, pfs_event) ~ arm + strata(biomarker), placebo = 'pbo', 
         data = locked_data, alternative = 'less', 
         scale = 'log hazard ratio', 
         x > -2 & x < 3) ## define a subset
```

## Analyze Continuous Endpoint

We analyze the continuous endpoint `cep` using linear models, with and without covariate adjustment.

```{r saljfh}
## ATE accounting for covariate x
fitLinear(cep ~ arm * x, placebo = 'pbo', 
          data = locked_data, alternative = 'greater')

## marginal model
fitLinear(cep ~ arm, placebo = 'pbo', 
          data = locked_data, alternative = 'greater')

## analyze a sub-group
fitLinear(cep ~ arm, placebo = 'pbo', 
          data = locked_data, alternative = 'greater', 
          biomarker == 1) ## define the subgroup
```

## Analyze Binary Endpoint

We analyze the binary endpoint `bep` using logistic regression. Multiple estimands (e.g., odds ratio, risk ratio, risk difference) can be computed by specifying the `scale` argument.

```{r pqeir}
## compute regression coefficient of arm
fitLogistic(bep ~ arm * x + biomarker, placebo = 'pbo', 
            data = locked_data, alternative = 'greater', 
            scale = 'coefficient')

## compute odds ratio (ATE)
fitLogistic(bep ~ arm + x*biomarker, placebo = 'pbo', 
            data = locked_data, alternative = 'greater', 
            scale = 'odds ratio')

## compute risk ratio (ATE)
fitLogistic(bep ~ arm + x + biomarker, placebo = 'pbo', 
            data = locked_data, alternative = 'greater', 
            scale = 'risk ratio')
```

The risk difference can also be estimated using logistic regression or the Farrington-Manning test. Note that the latter does not support covariate adjustment.

```{r uyta}
## compute risk difference (ATE)
fitLogistic(bep ~ arm + x * biomarker, placebo = 'pbo', 
            data = locked_data, alternative = 'greater', 
            scale = 'risk difference')

## compute risk difference without covariate
fitLogistic(bep ~ arm, placebo = 'pbo', 
            data = locked_data, alternative = 'greater', 
            scale = 'risk difference')

## analyze a sub-group
fitLogistic(bep ~ arm, placebo = 'pbo', 
            data = locked_data, alternative = 'greater', 
            scale = 'risk difference', 
            x < 2 & biomarker != 1) ## define a subgroup

## analyze the same sub-group using the FM test,
## same estimate but different p-values
fitFarringtonManning(endpoint = 'bep', placebo = 'pbo', 
                     data = locked_data, alternative = 'greater', 
                     x < 2 & biomarker != 1)
```
