---
title: "Creating ADTTE"
output:
  rmarkdown::html_vignette:
vignette: >
  %\VignetteIndexEntry{Creating ADTTE}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(admiraldev)
```

# Introduction

This article describes creating an `ADTTE` (time-to-event) ADaM with common oncology
endpoint parameters.

The main part in programming a time-to-event dataset is the definition of the
events and censoring times. `{admiral}`/`{admiralonco}` supports single events like
death (Overall Survival) or composite events like disease progression or death (Progression
Free Survival). More than one source dataset can be used for the definition of the event
and censoring times.

The majority of the functions used here exist from `{admiral}`, except for the
`tte_sources` helper object, provided as an example from `{admiralonco}`.
In practice, each company would create their own version of this, as likely the
exact specifications such as filtering condition or description metadata will vary.

**Note**: *All examples assume CDISC SDTM and/or ADaM format as input unless
otherwise specified.*

## Required Packages

The examples of this vignette require the following packages.

```{r, warning=FALSE, message=FALSE}
library(admiral)
library(admiralonco)
library(pharmaverseadam)
library(dplyr)
library(lubridate)
```

# Programming Workflow

* [Read in Data](#readdata)
* [Derive Parameters (`CNSR`, `ADT`, `STARTDT`)](#parameters)
* [Derive Analysis Value (`AVAL`)](#aval)
* [Derive Analysis Sequence Number (`ASEQ`)](#aseq)
* [Add ADSL Variables](#adslvars)

## Read in Data {#readdata}

To start, all datasets needed for the creation of the time-to-event dataset
should be read into the environment. This will be a company specific process.

For example purpose, the ADaM datasets---which are included in
`{pharmaverseadam}`---are used. An alternative might be to use `ADEVENT` as
input[^1].

[^1]: The subjects are restricted to `"01-701-1015"`, `"01-701-1028"`,
`"01-701-1034"`, `"01-701-1097"`, `"01-701-1115"`, `"01-701-1118"`,
`"01-701-1130"`, `"01-701-1133"`, `"01-701-1146"`, `"01-701-1211"`.

```{r}
adsl <- pharmaverseadam::adsl
adrs <- pharmaverseadam::adrs_onco
```

```{r, echo=FALSE}
cm <- tribble(
  ~STUDYID, ~USUBJID, ~CMCAT, ~CMSCAT, ~CMTRT, ~CMSTDTC,
  "CDISCPILOT01", "01-701-1015", "PRIOR TREATMENT", "CHEMOTHERAPY", "DEXRAZOXANE", NA,
  "CDISCPILOT01", "01-701-1015", "ON TREATMENT", "CHEMOTHERAPY", "DEXROZOXANE", "2014-07-02",
  "CDISCPILOT01", "01-701-1015", "ON TREATMENT", "CHEMOTHERAPY", "DEXROZOXANE", "2014-06-19",
  "CDISCPILOT01", "01-701-1028", "PRIOR TREATMENT", "CHEMOTHERAPY", "METHOTREXATE", NA,
  "CDISCPILOT01", "01-701-1028", "ON TREATMENT", "CHEMOTHERAPY", "METHOTREXATE", "2014-01-14",
  "CDISCPILOT01", "01-701-1034", "PRIOR TREATMENT", "CHEMOTHERAPY", "OLAPARIB", NA,
  "CDISCPILOT01", "01-701-1034", "ON TREATMENT", "CHEMOTHERAPY", "OLAPARIB", "2014-12-30",
  "CDISCPILOT01", "01-701-1097", "PRIOR TREATMENT", "CHEMOTHERAPY", "TEMODAL", NA,
  "CDISCPILOT01", "01-701-1097", "ON TREATMENT", "CHEMOTHERAPY", "TEMODAL", "2013-12-31",
)

adsl <- adsl %>%
  filter(USUBJID %in% c(
    "01-701-1015", "01-701-1028", "01-701-1034", "01-701-1097", "01-701-1115",
    "01-701-1118", "01-701-1130", "01-701-1133", "01-701-1146", "01-701-1211"
  )) %>%
  derive_vars_merged(
    dataset_add = cm,
    by_vars = get_admiral_option("subject_keys"),
    order = exprs(NACTDT),
    mode = "first",
    new_vars = exprs(NACTDT = convert_dtc_to_dt(CMSTDTC)),
    filter_add = CMSCAT == "CHEMOTHERAPY" & CMCAT == "ON TREATMENT"
  )
```

## Derive Parameters (`CNSR`, `ADT`, `STARTDT`) {#parameters}

To derive the parameter dependent variables like `CNSR`, `ADT`, `STARTDT`,
`EVNTDESC`, `SRCDOM`, `PARAMCD`, ... the `admiral::derive_param_tte()` function can be
used. It adds one parameter to the input dataset with one observation per
subject. Usually it is called several times.

For each subject it is determined if an event occurred. In the affirmative the
analysis date `ADT` is set to the earliest event date. If no event occurred, the
analysis date is set to the latest censoring date.

The events and censorings are defined by the `admiral::event_source()` and the
`admiral::censor_source()` class respectively. It defines

- which observations (`filter` parameter) of a source dataset (`dataset_name`
parameter) are potential events or censorings,
- the value of the `CNSR` variable (`censor` parameter), and
- which variable provides the date (`date` parameter).

The date can be provided as a date (`*DT` variable) or a datetime (`*DTM`
variable).

CDISC strongly recommends `CNSR = 0` for events and positive integers for
censorings. `{admiral}`/`{admiralonco}` enforce this recommendation. Therefore the `censor`
parameter is available for `admiral::censor_source()` only. It is defaulted to `1`.

The `dataset_name` parameter expects a character value which is used as an
identifier. The actual data which is used for the derivation of the parameter is
provided via the `source_datasets` parameter of `admiral::derive_param_tte()`. It expects
a named list of datasets. The names correspond to the identifiers specified for
the `dataset_name` parameter. This allows to define events and censoring
independent of the data.

### Pre-Defined Time-to-Event Source Objects

The table below shows all pre-defined `tte_source` objects which should cover the most
common oncology use cases.

```{r echo=FALSE}
knitr::kable(list_tte_source_objects(package = "admiralonco"))
```

As mentioned in the introduction, each company would create their own version of this with
the required filtering conditions and metadata as per your company approach. An example of
a possible different approach could be as follows, where death is sourced from `ADSL`,
instead of `ADRS`, and the given `EVNTDESC` is different.

```{r, eval=FALSE}
adsl_death_event <- event_source(
  dataset_name = "adsl",
  date = DTHDT,
  set_values_to = exprs(
    EVNTDESC = "STUDY DEATH",
    SRCDOM = "ADSL",
    SRCVAR = "DTHDT"
  )
)
```

An optional step at this stage would be required to enable derivation of duration of
response: If using `ADRS` / `ADEVENT` parameters as input for any response dates
(instead of a variable in `ADSL`) then you would need to use `admiral::derive_vars_merged()`
to add the response date as a temporary variable (e.g. `TEMP_RESPDT`) to be able to feed
into `admiral::derive_param_tte()` as the start date. You would also need to use this
to filter the source `ADSL` dataset so as to only derive the records for responders.
This could also be repeated as needed for IRF/BICR and confirmed responses.

Here is an example of the code needed.

```{r}
adsl <- adsl %>%
  derive_vars_merged(
    dataset_add = adrs,
    filter_add = PARAMCD == "RSP" & AVALC == "Y" & ANL01FL == "Y",
    by_vars = get_admiral_option("subject_keys"),
    new_vars = exprs(TEMP_RESPDT = ADT)
  )
```
```{r, echo=FALSE}
dataset_vignette(
  adsl,
  display_vars = exprs(USUBJID, RANDDT, TEMP_RESPDT, NACTDT, EOSDT)
)
```

The pre-defined objects can be passed directly to `admiral::derive_param_tte()` to create
a new time-to-event parameter. Below shows example calls for Overall Survival (OS), Progression
Free Survival (PFS), and duration of response (as above, this is only derived for responder
patients so we have to filter source `ADSL` dataset). Note that the reason for including a
randomization date censor is to catch those patients that never have a tumor assessment.

```{r}
adtte <- derive_param_tte(
  dataset_adsl = adsl,
  start_date = RANDDT,
  event_conditions = list(death_event),
  censor_conditions = list(lastalive_censor, rand_censor),
  source_datasets = list(adsl = adsl, adrs = adrs),
  set_values_to = exprs(PARAMCD = "OS", PARAM = "Overall Survival")
) %>%
  derive_param_tte(
    dataset_adsl = adsl,
    start_date = RANDDT,
    event_conditions = list(pd_event, death_event),
    censor_conditions = list(lasta_censor, rand_censor),
    source_datasets = list(adsl = adsl, adrs = adrs),
    set_values_to = exprs(PARAMCD = "PFS", PARAM = "Progression Free Survival")
  ) %>%
  derive_param_tte(
    dataset_adsl = filter(adsl, !is.na(TEMP_RESPDT)),
    start_date = TEMP_RESPDT,
    event_conditions = list(pd_event, death_event),
    censor_conditions = list(lasta_censor),
    source_datasets = list(adsl = adsl, adrs = adrs),
    set_values_to = exprs(PARAMCD = "RSD", PARAM = "Duration of Response")
  )
```
```{r, echo=FALSE}
dataset_vignette(
  adtte,
  display_vars = exprs(USUBJID, PARAMCD, PARAM, STARTDT, ADT, CNSR)
)
```

### Creating Your Own Time-to-Event Source Objects {#tteobj}

We advise you to consult the `{admiral}` [Creating a BDS Time-to-Event ADaM
vignette](https://pharmaverse.github.io/admiral/cran-release/articles/bds_tte.html)
and [Time-to-Event
Analyses](https://pharmaverse.github.io/admiral/cran-release/articles/tte_analyses_web.html)
for further guidance on the different options available and more examples.

One additional common oncology use case described here involves PFS when
censoring at new anti-cancer therapy. This can be controlled either by using
`ANLzzFL` as explained in the ADRS vignette, so that records after new
anti-cancer therapy never contribute to the PD and DEATH parameters, or by
using the `end_dates` argument of `derive_param_tte()` on the `ADTTE` side.

For `end_dates`, you can specify whichever date your analysis requires, e.g.,
the start date of new anti-cancer therapy or the date of surgery. The argument
expects a list of `censor_source()` objects. The earliest date is used as the
end of the observation period, and events or censorings occurring after this
date are not considered. If the `end_dates` argument is used, "Overall Response
by Investigator" parameter (`OVR`) should be used instead of the "Last Disease
Assessment by Investigator" parameter (`LSTA`) to ensure all valid assessments
are considered.

In the example below, the `end_dates` argument is used to restrict the events
and censorings to those occurring on or before the start of new anti-cancer
therapy. `NACTDT` would be pre-derived as the first date of new anti-cancer
therapy. See `{admiralonco}` [Creating and Using New Anti-Cancer Start
Date](nactdt.html) for deriving `NACTDT`. In addition, `EOSDT` is included in
`end_dates` to populate `EVNTDESC` when no new anti-cancer therapy was started.
For censored subjects, `EVNTDESC` will be set to `"Start of New Anti-Cancer
Therapy"` if the subject started new anti-cancer therapy and set to `"End of
Study"` otherwise.

```{r}
eosdt <- censor_source(
  dataset_name = "adsl",
  date = EOSDT,
  set_values_to = exprs(
    EVNTDESC = "End of Study"
  )
)

nactdt <- censor_source(
  dataset_name = "adsl",
  date = NACTDT,
  set_values_to = exprs(
    EVNTDESC = "Start of New Anti-Cancer Therapy"
  )
)

valid_assessment <- censor_source(
  dataset_name = "adrs",
  filter = PARAMCD == "OVR" & AVALC != "NE",
  date = ADT,
  set_values_to = exprs(
    CNSDTDSC = "Last Valid Tumor Assessment",
    SRCDOM = "ADRS",
    SRCVAR = "ADT"
  )
)

adtte <- adtte %>% derive_param_tte(
  dataset_adsl = adsl,
  start_date = RANDDT,
  end_dates = list(nactdt, eosdt),
  event_conditions = list(pd_event, death_event),
  censor_conditions = list(valid_assessment, rand_censor),
  source_datasets = list(adsl = adsl, adrs = adrs),
  set_values_to = exprs(
    PARAMCD = "PFSNACT",
    PARAM = "Progression Free Survival prior to NACT"
  )
)
```
```{r, echo=FALSE}
dataset_vignette(
  adtte %>% filter(PARAMCD == "PFSNACT"),
  display_vars = exprs(USUBJID, PARAMCD, PARAM, STARTDT, ADT, CNSR, EVNTDESC, CNSDTDSC)
)
```

## Derive Analysis Value (`AVAL`) {#aval}

The analysis value (`AVAL`) can be derived by calling `admiral::derive_vars_duration()`.

This example derives the time to event in days. 

```{r eval=TRUE}
adtte <- adtte %>%
  derive_vars_duration(
    new_var = AVAL,
    start_date = STARTDT,
    end_date = ADT
  )
```

```{r, echo=FALSE}
dataset_vignette(
  adtte
)
```

Other time units, such as months that we commonly see in oncology analyses, can be requested
by specifying the `out_unit` parameter. See the example below. Note that because of the underlying
`lubridate::time_length()` function that is used here this may perform slightly differently to
your expectations, e.g. both `time_length(ymd("2021-01-01") %--% ymd("2021-02-01"), "month")`
and `time_length(ymd("2021-02-01") %--% ymd("2021-03-01"), "month")` results in exactly 1 month,
which is a logical approach but it gives a different result to the convention of assuming every
month has exactly equal days and just using `/30.4375` here or some other such convention. The
difference would only be noticed for small durations, but if the user prefers an alternative
approach they could calculate in the default days and then add extra processing to convert to months
with their company-specific convention.

```{r, eval=FALSE}
adtte_months <- adtte %>%
  derive_vars_duration(
    new_var = AVAL,
    start_date = STARTDT,
    end_date = ADT,
    out_unit = "months"
  )
```

## Derive Analysis Sequence Number (`ASEQ`) {#aseq}

The `{admiral}` function `admiral::derive_var_obs_number()` can be used to derive `ASEQ`:

```{r eval=TRUE}
adtte <- adtte %>%
  derive_var_obs_number(
    by_vars = get_admiral_option("subject_keys"),
    order = exprs(PARAMCD),
    check_type = "error"
  )
```

```{r, echo=FALSE}
dataset_vignette(adtte)
```

## Add ADSL Variables {#adslvars}

Variables from ADSL which are required for time-to-event analyses, e.g.,
treatment variables or covariates can be added using `admiral::derive_vars_merged()`.

```{r eval=TRUE}
adtte <- adtte %>%
  derive_vars_merged(
    dataset_add = adsl,
    new_vars = exprs(ARMCD, ARM, ACTARMCD, ACTARM, AGE, SEX),
    by_vars = get_admiral_option("subject_keys")
  )
```

```{r, echo=FALSE}
dataset_vignette(
  adtte,
  display_vars = exprs(USUBJID, PARAMCD, CNSR, AVAL, ARMCD, AGE, SEX)
)
```

# Example Script {#example}

ADaM | Sample Code
---- | --------------
`ADTTE` | `admiral::use_ad_template("ADTTE", package = "admiralonco")`
