---
title: "Creating a PK NCA ADaM (ADPC/ADNCA)"
output: 
  rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Creating a PK NCA ADaM (ADPC/ADNCA)}
  %\VignetteEncoding{UTF-8}
  %\VignetteEngine{knitr::rmarkdown}
editor_options: 
  markdown: 
    wrap: 72
---

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

library(admiraldev)
```

# Introduction

This article describes creating a Pharmacokinetics (PK)
Non-compartmental analysis (NCA) ADaM (ADNCA/ADPC) using the CDISC
Implementation Guide
(<https://www.cdisc.org/standards/foundational/adam/adamig-non-compartmental-analysis-input-data-v1-0>).
This example presented uses underlying `EX` and `PC` domains where the
`EX` and `PC` domains represent data as collected and the `ADPC` ADaM is
output. However, the example can be applied to situations where an `EC`
domain is used as input instead of `EX` and/or `ADNCA` or another ADaM
is created.

One of the important aspects of the dataset is the derivation of
relative timing variables. These variables consist of nominal and actual
times, and refer to the time from first dose or time from most recent
reference dose. The reference dose for pre-dose records may be the
upcoming dose. The CDISC Implementation Guide makes use of duplicated
records for analysis, which allows the same record to be used both with
respect to the previous dose and the next upcoming dose. This is
illustrated later in this vignette.

Here are the relative time variables we will use. These correspond to
the names in the CDISC Implementation Guide.

| Variable | Variable Label                         |
|----------|----------------------------------------|
| NFRLT    | Nom. Rel. Time from Analyte First Dose |
| AFRLT    | Act. Rel. Time from Analyte First Dose |
| NRRLT    | Nominal Rel. Time from Ref. Dose       |
| ARRLT    | Actual Rel. Time from Ref. Dose        |
| MRRLT    | Modified Rel. Time from Ref. Dose      |

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

# Programming Workflow

-   [Read in Data](#readdata)

-   [Expand Dosing Records](#expand)

-   [Find First Dose and Calculate `AFRLT`](#firstdose)

-   [Find Reference Dose Dates Corresponding to PK Records](#dosedates)

-   [Combine `PC` and `EX` Records and Derive Relative Time
    Variables](#relative)

-   [Derive Analysis Variables](#analysis)

-   [Create Duplicated Records for Analysis](#copy)

-   [Combine `ADPC` data with Duplicated Records](#combine)

-   [Calculate Change from Baseline and Assign `ASEQ`](#aseq)

-   [Add Additional Baseline Variables](#baselines)

-   [Add ADSL variables](#adsl_vars)

-   [Add Labels and Attributes](#attributes)

## Read in Data {#readdata}

To start, all data frames needed for the creation of `ADPC` should be
read into the environment. This will be a company specific process. Some
of the data frames needed may be `PC`, `EX`, and `ADSL`.

Additional domains such as `VS` and `LB` may be used for additional
baseline variables if needed. These may come from either the SDTM or
ADaM source.

For the purpose of example, the CDISC Pilot SDTM and ADaM
datasets---which are included in `{admiral.test}`---are used.

```{r message=FALSE}
library(dplyr, warn.conflicts = FALSE)
library(admiral)
library(admiral.test)
library(lubridate)
library(stringr)
library(tibble)

data("admiral_adsl")
data("admiral_ex")
data("admiral_pc")
data("admiral_vs")

adsl <- admiral_adsl
ex <- convert_blanks_to_na(admiral_ex)

# Load PC

pc <- convert_blanks_to_na(admiral_pc)

# Load VS for baseline height and weight

vs <- convert_blanks_to_na(admiral_vs)

# ---- Lookup tables ----
param_lookup <- tibble::tribble(
  ~PCTESTCD, ~PARAMCD, ~PARAM, ~PARAMN,
  "XAN", "XAN", "Pharmacokinetic concentration of Xanomeline", 1,
  "DOSE", "DOSE", "Xanomeline Patch Dose", 2,
)
```

```{r echo=FALSE}
ex <- filter(ex, USUBJID %in% c("01-701-1028", "01-701-1033", "01-701-1442", "01-714-1288", "01-718-1101"))
pc <- filter(pc, USUBJID %in% c("01-701-1028", "01-701-1033", "01-701-1442", "01-714-1288", "01-718-1101"))
```

At this step, it may be useful to join `ADSL` to your `PC` and `EX`
domains as well. Only the `ADSL` variables used for derivations are
selected at this step. The rest of the relevant `ADSL` variables will be
added later.

In this case we will keep `TRTSDT`/`TRTSDTM` for day derivation and
`TRT01P`/`TRT01A` for planned and actual treatments.

In this segment we will use `derive_vars_merged()` to join the `ADSL`
variables and the following `{admiral}` functions to derive analysis
dates, times and days: `derive_vars_dtm()`, `derive_vars_dtm_to_dt()`,
`derive_vars_dtm_to_tm()`, `derive_vars_dy()`. We will also create
`NFRLT` for `PC` data based on `PCTPTNUM`. We will create an event ID
(`EVID`) of 0 for concentration records and 1 for dosing records. This
is a traditional variable that will provide a handy tool to identify
records but will be dropped from the final dataset in this example.

```{r eval=TRUE}

adsl_vars <- exprs(TRTSDT, TRTSDTM, TRT01P, TRT01A)

adpc <- pc %>%
  # Join ADSL with PC (need TRTSDT for ADY derivation)
  derive_vars_merged(
    dataset_add = adsl,
    new_vars = adsl_vars,
    by_vars = exprs(STUDYID, USUBJID)
  ) %>%
  # Derive analysis date/time
  # Impute missing time to 00:00:00
  derive_vars_dtm(
    new_vars_prefix = "A",
    dtc = PCDTC,
    time_imputation = "00:00:00"
  ) %>%
  # Derive dates and times from date/times
  derive_vars_dtm_to_dt(exprs(ADTM)) %>%
  derive_vars_dtm_to_tm(exprs(ADTM)) %>%
  derive_vars_dy(reference_date = TRTSDT, source_vars = exprs(ADT)) %>%
  # Derive event ID and nominal relative time from first dose (NFRLT)
  mutate(
    EVID = 0,
    DRUG = PCTEST,
    NFRLT = if_else(PCTPTNUM < 0, 0, PCTPTNUM), .after = USUBJID
  )
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  adpc,
  display_vars = exprs(
    USUBJID, PCTEST, ADTM, VISIT, PCTPT, NFRLT
  )
)
```

Next we will also join `ADSL` data with `EX` and derive dates/times.
This section uses the `{admiral}` functions `derive_vars_merged()`,
`derive_vars_dtm()`, and `derive_vars_dtm_to_dt()`. Time is imputed to
00:00:00 here for reasons specific to the sample data. Other imputation
times may be used based on study details. Here we create `NFRLT` for
`EX` data based on `VISITDY` using the formula `(VISITDY - 1) * 24`
using `dplyr::mutate`.

```{r eval=TRUE, echo=TRUE}

# ---- Get dosing information ----

ex <- ex %>%
  derive_vars_merged(
    dataset_add = adsl,
    new_vars = adsl_vars,
    by_vars = exprs(STUDYID, USUBJID)
  ) %>%
  # Keep records with nonzero dose
  filter(EXDOSE > 0) %>%
  # Add time and set missing end date to start date
  # Impute missing time to 00:00:00
  # Note all times are missing for dosing records in this example data
  # Derive Analysis Start and End Dates
  derive_vars_dtm(
    new_vars_prefix = "AST",
    dtc = EXSTDTC,
    time_imputation = "00:00:00"
  ) %>%
  derive_vars_dtm(
    new_vars_prefix = "AEN",
    dtc = EXENDTC,
    time_imputation = "00:00:00"
  ) %>%
  # Derive event ID and nominal relative time from first dose (NFRLT)
  mutate(
    EVID = 1,
    NFRLT = 24 * (VISITDY - 1), .after = USUBJID
  ) %>%
  # Set missing end dates to start date
  mutate(AENDTM = case_when(
    is.na(AENDTM) ~ ASTDTM,
    TRUE ~ AENDTM
  )) %>%
  # Derive dates from date/times
  derive_vars_dtm_to_dt(exprs(ASTDTM)) %>%
  derive_vars_dtm_to_dt(exprs(AENDTM))
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  ex,
  display_vars = exprs(
    USUBJID, EXTRT, EXDOSFRQ, ASTDTM, AENDTM, VISIT, VISITDY, NFRLT
  )
)
```

## Expand Dosing Records {#expand}

The function `create_single_dose_dataset()` can be used to expand dosing
records between the start date and end date. The nominal time will also
be expanded based on the values of `EXDOSFRQ`, for example "QD" will
result in nominal time being incremented by 24 hours and "BID" will
result in nominal time being incremented by 12 hours. This is a new
feature of `create_single_dose_dataset()`.

Dates and times will be derived after expansion using
`derive_vars_dtm_to_dt()` and `derive_vars_dtm_to_tm()`.

For this example study we will define analysis visit (`AVISIT)` based on
the nominal day value from `NFRLT` and give it the format, "Day 1", "Day
2", "Day 3", etc. This is important for creating the `BASETYPE` variable
later. `DRUG` is created from `EXTRT` here. This will be useful for
linking treatment data with concentration data if there are multiple
drugs and/or analytes, but this variable will also be dropped from the
final dataset in this example.

```{r eval=TRUE, echo=TRUE}
# ---- Expand dosing records between start and end dates ----

ex_exp <- ex %>%
  create_single_dose_dataset(
    dose_freq = EXDOSFRQ,
    start_date = ASTDT,
    start_datetime = ASTDTM,
    end_date = AENDT,
    end_datetime = AENDTM,
    nominal_time = NFRLT,
    lookup_table = dose_freq_lookup,
    lookup_column = CDISC_VALUE,
    keep_source_vars = exprs(
      STUDYID, USUBJID, EVID, EXDOSFRQ, EXDOSFRM,
      NFRLT, EXDOSE, EXDOSU, EXTRT, ASTDT, ASTDTM, AENDT, AENDTM,
      VISIT, VISITNUM, VISITDY,
      TRT01A, TRT01P, DOMAIN, EXSEQ, !!!adsl_vars
    )
  ) %>%
  # Derive AVISIT based on nominal relative time
  # Derive AVISITN to nominal time in whole days using integer division
  # Define AVISIT based on nominal day
  mutate(
    AVISITN = NFRLT %/% 24 + 1,
    AVISIT = paste("Day", AVISITN),
    ADTM = ASTDTM,
    DRUG = EXTRT,
  ) %>%
  # Derive dates and times from datetimes
  derive_vars_dtm_to_dt(exprs(ADTM)) %>%
  derive_vars_dtm_to_tm(exprs(ADTM)) %>%
  derive_vars_dtm_to_tm(exprs(ASTDTM)) %>%
  derive_vars_dtm_to_tm(exprs(AENDTM)) %>%
  derive_vars_dy(reference_date = TRTSDT, source_vars = exprs(ADT))
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  ex_exp,
  display_vars = exprs(USUBJID, DRUG, EXDOSFRQ, ASTDTM, AENDTM, AVISIT, NFRLT)
)
```

## Find First Dose and Calculate `AFRLT` {#firstdose}

In this section we will find the first dose for each subject and drug,
using `derive_vars_merged()`. We also create an analysis visit
(`AVISIT`) based on `NFRLT`. The first dose datetime for an analyte
`FANLDTM` is calculated as the minimum `ADTM` from the dosing records by
subject and drug.

```{r eval=TRUE, echo=TRUE, message=FALSE}
# ---- Find first dose per treatment per subject ----
# ---- Join with ADPC data and keep only subjects with dosing ----

adpc <- adpc %>%
  derive_vars_merged(
    dataset_add = ex_exp,
    filter_add = (EXDOSE > 0 & !is.na(ADTM)),
    new_vars = exprs(FANLDTM = ADTM),
    order = exprs(ADTM, EXSEQ),
    mode = "first",
    by_vars = exprs(STUDYID, USUBJID, DRUG)
  ) %>%
  filter(!is.na(FANLDTM)) %>%
  # Derive AVISIT based on nominal relative time
  # Derive AVISITN to nominal time in whole days using integer division
  # Define AVISIT based on nominal day
  mutate(
    AVISITN = NFRLT %/% 24 + 1,
    AVISIT = paste("Day", AVISITN),
  )
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  adpc,
  display_vars = exprs(USUBJID, FANLDTM, AVISIT, ADTM, PCTPT)
)
```

## Find Reference Dose Dates Corresponding to PK Records {#dosedates}

Use `derive_vars_joined()` to find the previous dose data. This will
join the expanded `EX` data with the `ADPC` based on the analysis date
`ADTM`. Note the `filter_join` parameter. In addition to the date of the
previous dose (`ADTM_prev)`, we also keep the actual dose amount
`EXDOSE_prev` and the analysis visit of the dose `AVISIT_prev`.

```{r eval=TRUE, echo=TRUE}
# ---- Find previous dose  ----
# Use derive_vars_joined() for consistency with other variables
# This is equivalent to derive_vars_last_dose() in this case

adpc <- adpc %>%
  derive_vars_joined(
    dataset_add = ex_exp,
    by_vars = exprs(USUBJID),
    order = exprs(ADTM),
    new_vars = exprs(
      ADTM_prev = ADTM, EXDOSE_prev = EXDOSE, AVISIT_prev = AVISIT,
      AENDTM_prev = AENDTM
    ),
    join_vars = exprs(ADTM),
    filter_add = NULL,
    filter_join = ADTM > ADTM.join,
    mode = "last",
    check_type = "none"
  )
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  adpc,
  display_vars = exprs(
    USUBJID,
    VISIT, ADTM, VISIT, PCTPT, ADTM_prev, EXDOSE_prev, AVISIT_prev
  )
)
```

Similarly, find next dose information using `derive_vars_joined()` with
the `filter_join` parameter as `ADTM <= ADTM.join`. Here we keep the
next dose analysis date `ADTM_next`, the next actual dose `EXDOSE_next`,
and the next analysis visit `AVISIT_next`.

```{r eval=TRUE, echo=TRUE}
# ---- Find next dose  ----

adpc <- adpc %>%
  derive_vars_joined(
    dataset_add = ex_exp,
    by_vars = exprs(USUBJID),
    order = exprs(ADTM),
    new_vars = exprs(
      ADTM_next = ADTM, EXDOSE_next = EXDOSE, AVISIT_next = AVISIT,
      AENDTM_next = AENDTM
    ),
    join_vars = exprs(ADTM),
    filter_add = NULL,
    filter_join = ADTM <= ADTM.join,
    mode = "first",
    check_type = "none"
  )
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  adpc,
  display_vars = exprs(
    USUBJID,
    VISIT, ADTM, VISIT, PCTPT, ADTM_next, EXDOSE_next, AVISIT_next
  )
)
```

Use the same method to find the previous and next nominal times. Note
that here the data are sorted by nominal time rather than the actual
time. This will tell us when the previous dose and the next dose were
supposed to occur. Sometimes this will differ from the actual times in a
study. Here we keep the previous nominal dose time `NFRLT_prev` and the
next nominal dose time `NFRLT_next`. Note that the `filter_join`
parameter uses the nominal relative times, e.g. `NFRLT > NFRLT.join`.

```{r eval=TRUE, echo=TRUE}
# ---- Find previous nominal time ----

adpc <- adpc %>%
  derive_vars_joined(
    dataset_add = ex_exp,
    by_vars = exprs(USUBJID),
    order = exprs(NFRLT),
    new_vars = exprs(NFRLT_prev = NFRLT),
    join_vars = exprs(NFRLT),
    filter_add = NULL,
    filter_join = NFRLT > NFRLT.join,
    mode = "last",
    check_type = "none"
  )

# ---- Find next nominal time ----

adpc <- adpc %>%
  derive_vars_joined(
    dataset_add = ex_exp,
    by_vars = exprs(USUBJID),
    order = exprs(NFRLT),
    new_vars = exprs(NFRLT_next = NFRLT),
    join_vars = exprs(NFRLT),
    filter_add = NULL,
    filter_join = NFRLT <= NFRLT.join,
    mode = "first",
    check_type = "none"
  )
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  adpc,
  display_vars = exprs(
    USUBJID, NFRLT, PCTPT, NFRLT_prev, NFRLT_next
  )
)
```

## Combine PC and EX Records and Derive Relative Time Variables {#relative}

Combine `PC` and `EX` records and derive the additional relative time
variables. Often NCA data will keep both dosing and concentration
records. We will keep both here. Sometimes you will see `ADPC` with only
the concentration records. If this is desired, the dosing records can be
dropped before saving the final dataset. We will use the `{admiral}`
function `derive_vars_duration()` to calculate the actual relative time
from first dose (`AFRLT`) and the actual relative time from most recent
dose (`ARRLT`). Note that we use the parameter `add_one = FALSE` here.
We will also create a variable representing actual time to next dose
(`AXRLT`) which is not kept, but will be used when we create duplicated
records for analysis for the pre-dose records. For now, we will update
missing values of `ARRLT` corresponding to the pre-dose records with
`AXRLT`, and dosing records will be set to zero.

We also calculate the reference dates `FANLDTM` (First Datetime of Dose
for Analyte) and `PCRFTDTM` (Reference Datetime of Dose for Analyte) and
their corresponding date and time variables.

We calculate the maximum date for concentration records and only keep
the dosing records up to that date.

```{r eval=TRUE, echo=TRUE}

# ---- Combine ADPC and EX data ----
# Derive Relative Time Variables


adpc <- bind_rows(adpc, ex_exp) %>%
  group_by(USUBJID, DRUG) %>%
  mutate(
    FANLDTM = min(FANLDTM, na.rm = TRUE),
    min_NFRLT = min(NFRLT_prev, na.rm = TRUE),
    maxdate = max(ADT[EVID == 0], na.rm = TRUE), .after = USUBJID
  ) %>%
  arrange(USUBJID, ADTM) %>%
  ungroup() %>%
  filter(ADT <= maxdate) %>%
  # Derive Actual Relative Time from First Dose (AFRLT)
  derive_vars_duration(
    new_var = AFRLT,
    start_date = FANLDTM,
    end_date = ADTM,
    out_unit = "hours",
    floor_in = FALSE,
    add_one = FALSE
  ) %>%
  # Derive Actual Relative Time from Reference Dose (ARRLT)
  derive_vars_duration(
    new_var = ARRLT,
    start_date = ADTM_prev,
    end_date = ADTM,
    out_unit = "hours",
    floor_in = FALSE,
    add_one = FALSE
  ) %>%
  # Derive Actual Relative Time from Next Dose (AXRLT not kept)
  derive_vars_duration(
    new_var = AXRLT,
    start_date = ADTM_next,
    end_date = ADTM,
    out_unit = "hours",
    floor_in = FALSE,
    add_one = FALSE
  ) %>%
  mutate(
    ARRLT = case_when(
      EVID == 1 ~ 0,
      is.na(ARRLT) ~ AXRLT,
      TRUE ~ ARRLT
    ),

    # Derive Reference Dose Date
    PCRFTDTM = case_when(
      EVID == 1 ~ ADTM,
      is.na(ADTM_prev) ~ ADTM_next,
      TRUE ~ ADTM_prev
    )
  ) %>%
  # Derive dates and times from datetimes
  derive_vars_dtm_to_dt(exprs(FANLDTM)) %>%
  derive_vars_dtm_to_tm(exprs(FANLDTM)) %>%
  derive_vars_dtm_to_dt(exprs(PCRFTDTM)) %>%
  derive_vars_dtm_to_tm(exprs(PCRFTDTM))
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  adpc,
  display_vars = exprs(USUBJID, FANLDTM, AVISIT, PCTPT, AFRLT, ARRLT, AXRLT)
)
```

For nominal relative times we calculate `NRRLT` generally as
`NFRLT - NFRLT_prev` and `NXRLT` as `NFRLT - NFRLT_next`.

```{r eval=TRUE, echo=TRUE}

adpc <- adpc %>%
  # Derive Nominal Relative Time from Reference Dose (NRRLT)
  mutate(
    NRRLT = case_when(
      EVID == 1 ~ 0,
      is.na(NFRLT_prev) ~ NFRLT - min_NFRLT,
      TRUE ~ NFRLT - NFRLT_prev
    ),
    NXRLT = case_when(
      EVID == 1 ~ 0,
      TRUE ~ NFRLT - NFRLT_next
    )
  )
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  adpc,
  display_vars = exprs(USUBJID, AVISIT, PCTPT, NFRLT, NRRLT, NXRLT)
)
```

## Derive Analysis Variables {#analysis}

Using `dplyr::mutate` we derive a number of analysis variables including
analysis value (`AVAL`), analysis time point (`ATPT`) analysis timepoint
reference (`ATPTREF`) and baseline type (`BASETYPE`).

We set `ATPT` to `PCTPT` for concentration records and to "Dose" for
dosing records. The analysis timepoint reference `ATPTREF` will
correspond to the dosing visit. We will use `AVISIT_prev` and
`AVISIT_next` to derive. The baseline type will be a concatenation of
`ATPTREF` and "Baseline" with values such as "Day 1 Baseline", "Day 2
Baseline", etc. The baseline flag `ABLFL` will be set to "Y" for
pre-dose records.

Analysis value `AVAL` in this example comes from `PCSTRESN` for
concentration records. In addition we are including the dose value
`EXDOSE` for dosing records and setting BLQ (Below Limit of
Quantitation) records to 0 before the first dose and to 1/2 of LLOQ
(Lower Limit of Quantitation) for records after first dose. (Additional
tests such as whether more than 1/3 of records are BLQ may be required
and are not done in this example.) We also create a listing-ready
variable `AVALCAT1` which includes the "BLQ" record indicator and
formats the numeric values to three significant digits.

We derive actual dose `DOSEA` based on `EXDOSE_prev` and `EXDOSE_next`
and planned dose `DOSEP` based on the planned treatment `TRT01P`. In
addition we add the units for the dose variables and the relative time
variables.

```{r eval=TRUE, echo=TRUE}
# ---- Derive Analysis Variables ----
# Derive ATPTN, ATPT, ATPTREF, ABLFL and BASETYPE
# Derive planned dose DOSEP, actual dose DOSEA and units
# Derive PARAMCD and relative time units
# Derive AVAL, AVALU and AVALCAT1

adpc <- adpc %>%
  mutate(
    ATPTN = case_when(
      EVID == 1 ~ 0,
      TRUE ~ PCTPTNUM
    ),
    ATPT = case_when(
      EVID == 1 ~ "Dose",
      TRUE ~ PCTPT
    ),
    ATPTREF = case_when(
      EVID == 1 ~ AVISIT,
      is.na(AVISIT_prev) ~ AVISIT_next,
      TRUE ~ AVISIT_prev
    ),
    # Derive baseline flag for pre-dose records
    ABLFL = case_when(
      ATPT == "Pre-dose" ~ "Y",
      TRUE ~ NA_character_
    ),
    # Derive BASETYPE
    BASETYPE = paste(ATPTREF, "Baseline"),

    # Derive Actual Dose
    DOSEA = case_when(
      EVID == 1 ~ EXDOSE,
      is.na(EXDOSE_prev) ~ EXDOSE_next,
      TRUE ~ EXDOSE_next
    ),
    # Derive Planned Dose
    DOSEP = case_when(
      TRT01P == "Xanomeline High Dose" ~ 81,
      TRT01P == "Xanomeline Low Dose" ~ 54
    ),
    DOSEU = "mg",
  ) %>%
  # Derive relative time units
  mutate(
    FRLTU = "h",
    RRLTU = "h",
    # Derive PARAMCD
    PARAMCD = coalesce(PCTESTCD, "DOSE"),
    ALLOQ = PCLLOQ,
    # Derive AVAL
    AVAL = case_when(
      EVID == 1 ~ EXDOSE,
      PCSTRESC == "<BLQ" & NFRLT == 0 ~ 0,
      PCSTRESC == "<BLQ" & NFRLT > 0 ~ 0.5 * ALLOQ,
      TRUE ~ PCSTRESN
    ),
    AVALU = case_when(
      EVID == 1 ~ EXDOSU,
      TRUE ~ PCSTRESU
    ),
    AVALCAT1 = if_else(PCSTRESC == "<BLQ", PCSTRESC, prettyNum(signif(AVAL, digits = 3))),
  ) %>%
  # Add SRCSEQ
  mutate(
    SRCDOM = DOMAIN,
    SRCVAR = "SEQ",
    SRCSEQ = coalesce(PCSEQ, EXSEQ)
  )
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  adpc,
  display_vars = exprs(USUBJID, NFRLT, AVISIT, ATPT, ABLFL, ATPTREF, AVAL, AVALCAT1)
)
```

## Create Duplicated Records for Analysis {#copy}

As mentioned above, the CDISC ADaM Implementation Guide for
Non-compartmental Analysis uses duplicated records for analysis when a
record needs to be used in more than one way. In this example the 24
hour post-dose record will also be used a the pre-dose record for the
"Day 2" dose. In addition to 24 hour post-dose records, other situations
may include pre-dose records for "Cycle 2 Day 1", etc.

In general, we will select the records of interest and then update the
relative time variables for the duplicated records. In this case we will
select where the nominal relative time to next dose is zero. (Note that
we do not need to duplicate the first dose record since there is no
prior dose.)

`DTYPE` is set to "COPY" for the duplicated records and the original
`PCSEQ` value is retained. In this case we change "24h Post-dose" to
"Pre-dose". `ABLFL` is set to "Y" since these records will serve as
baseline for the "Day 2" dose. `DOSEA` is set to `EXDOSE_next` and
`PCRFTDTM` is set to `ADTM_next`.

```{r eval=TRUE, echo=TRUE}
# ---- Create DTYPE copy records ----

dtype <- adpc %>%
  filter(NFRLT > 0 & NXRLT == 0 & EVID == 0 & !is.na(AVISIT_next)) %>%
  select(-PCRFTDT, -PCRFTTM) %>%
  # Re-derive variables in for DTYPE copy records
  mutate(
    ABLFL = NA_character_,
    ATPTREF = AVISIT_next,
    ARRLT = AXRLT,
    NRRLT = NXRLT,
    PCRFTDTM = ADTM_next,
    DOSEA = EXDOSE_next,
    BASETYPE = paste(AVISIT_next, "Baseline"),
    ATPT = "Pre-dose",
    ATPTN = NFRLT,
    ABLFL = "Y",
    DTYPE = "COPY"
  ) %>%
  derive_vars_dtm_to_dt(exprs(PCRFTDTM)) %>%
  derive_vars_dtm_to_tm(exprs(PCRFTDTM))
```

```{r, eval=TRUE, echo=FALSE}
dataset_vignette(
  dtype,
  display_vars = exprs(USUBJID, DTYPE, ATPT, NFRLT, NRRLT, AFRLT, ARRLT, BASETYPE)
)
```

## Combine `ADPC` data with Duplicated Records {#combine}

Now the duplicated records are combined with the original records. We
also derive the modified relative time from reference dose `MRRLT`. In
this case, negative values of `ARRLT` are set to zero.

This is also an opportunity to derive analysis flags e.g. `ANL01FL` ,
`ANL02FL` etc. In this example `ANL01FL` is set to "Y" for all records
and `ANL02FL` is set to "Y" for all records except the duplicated
records with `DTYPE` = "COPY". Additional flags may be used to select
full profile records and/or to select records included in the tables and
figures, etc.

```{r eval=TRUE, echo=TRUE}
# ---- Combine original records and DTYPE copy records ----

adpc <- bind_rows(adpc, dtype) %>%
  arrange(STUDYID, USUBJID, BASETYPE, ADTM, NFRLT) %>%
  mutate(
    # Derive MRRLT, ANL01FL and ANL02FL
    MRRLT = if_else(ARRLT < 0, 0, ARRLT),
    ANL01FL = "Y",
    ANL02FL = if_else(is.na(DTYPE), "Y", NA_character_),
  )
```

```{r, eval=TRUE, echo=FALSE}
adpc %>%
  dataset_vignette(display_vars = exprs(STUDYID, USUBJID, BASETYPE, ADTM, ATPT, NFRLT, NRRLT, ARRLT, MRRLT))
```

## Calculate Change from Baseline and Assign `ASEQ` {#aseq}

The `{admiral}` function `derive_var_base()` is used to derive `BASE`
and the function `derive_var_chg()` is used to derive change from
baseline `CHG`.

We also now derive `ASEQ` using `derive_var_obs_number()` and we drop
intermediate variables such as those ending with "\_prev" and "\_next".

Finally we derive `PARAM` and `PARAMN` from a lookup table.

```{r eval=TRUE, echo=TRUE}

# ---- Derive BASE and Calculate Change from Baseline ----

adpc <- adpc %>%
  # Derive BASE
  derive_var_base(
    by_vars = exprs(STUDYID, USUBJID, PARAMCD, BASETYPE),
    source_var = AVAL,
    new_var = BASE,
    filter = ABLFL == "Y"
  )

adpc <- derive_var_chg(adpc)

# ---- Add ASEQ ----

adpc <- adpc %>%
  # Calculate ASEQ
  derive_var_obs_number(
    new_var = ASEQ,
    by_vars = exprs(STUDYID, USUBJID),
    order = exprs(ADTM, BASETYPE, EVID, AVISITN, ATPTN, DTYPE),
    check_type = "error"
  ) %>%
  # Remove temporary variables
  select(
    -DOMAIN, -PCSEQ, -starts_with("orig"), -starts_with("min"),
    -starts_with("max"), -starts_with("EX"), -ends_with("next"),
    -ends_with("prev"), -DRUG, -EVID, -AXRLT, -NXRLT, -VISITDY
  ) %>%
  # Derive PARAM and PARAMN
  derive_vars_merged(dataset_add = select(param_lookup, -PCTESTCD), by_vars = exprs(PARAMCD))
```

```{r, eval=TRUE, echo=FALSE}
adpc %>%
  dataset_vignette(display_vars = exprs(
    USUBJID, BASETYPE, DTYPE, AVISIT, ATPT, AVAL, NFRLT, NRRLT, AFRLT, ARRLT, BASE, CHG
  ))
```

## Add Additional Baseline Variables {#baselines}

Here we derive additional baseline values from `VS` for baseline height
`HTBL` and weight `WTBL` and compute the body mass index (BMI) with
`compute_bmi()`. These values could also be obtained from `ADVS` if
available. Baseline lab values could also be derived from `LB` or `ADLB`
in a similar manner.

```{r eval=TRUE, echo=TRUE}

# Derive additional baselines from VS
adpc <- adpc %>%
  derive_vars_merged(
    dataset_add = vs,
    filter_add = VSTESTCD == "HEIGHT",
    by_vars = exprs(STUDYID, USUBJID),
    new_vars = exprs(HTBL = VSSTRESN, HTBLU = VSSTRESU)
  ) %>%
  derive_vars_merged(
    dataset_add = vs,
    filter_add = VSTESTCD == "WEIGHT" & VSBLFL == "Y",
    by_vars = exprs(STUDYID, USUBJID),
    new_vars = exprs(WTBL = VSSTRESN, WTBLU = VSSTRESU)
  ) %>%
  mutate(
    BMIBL = compute_bmi(height = HTBL, weight = WTBL),
    BMIBLU = "kg/m^2"
  )
```

```{r, eval=TRUE, echo=FALSE}
adpc %>%
  dataset_vignette(display_vars = exprs(
    USUBJID, HTBL, HTBLU, WTBL, WTBLU, BMIBL, BMIBLU, BASETYPE, ATPT, AVAL
  ))
```

## Add the `ADSL` variables {#adsl_vars}

If needed, the other `ADSL` variables can now be added:

```{r eval=TRUE, echo=TRUE}
# Add all ADSL variables
adpc <- adpc %>%
  derive_vars_merged(
    dataset_add = select(adsl, !!!negate_vars(adsl_vars)),
    by_vars = exprs(STUDYID, USUBJID)
  )
```

## Add Labels and Attributes {#attributes}

Adding labels and attributes for SAS transport files is supported by the
following packages:

-   [metacore](https://atorus-research.github.io/metacore/): establish a
    common foundation for the use of metadata within an R session.

-   [metatools](https://pharmaverse.github.io/metatools/): enable the
    use of metacore objects. Metatools can be used to build datasets or
    enhance columns in existing datasets as well as checking datasets
    against the metadata.

-   [xportr](https://atorus-research.github.io/xportr/): functionality
    to associate all metadata information to a local R data frame,
    perform data set level validation checks and convert into a
    [transport v5
    file(xpt)](https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/movefile/n1xbwdre0giahfn11c99yjkpi2yb.htm).

NOTE: All these packages are in the experimental phase, but the vision
is to have them associated with an End to End pipeline under the
umbrella of the [pharmaverse](https://github.com/pharmaverse). An
example of applying metadata and perform associated checks can be found
at the [pharmaverse E2E
example](https://examples.pharmaverse.org/data/adsl/).

# Example Scripts {#example}

| ADaM | Sample Code                                                                                             |
|------------------|------------------------------------------------------|
| ADPC | [ad_adpc.R](https://github.com/pharmaverse/admiral/blob/main/inst/templates/ad_adpc.R){target="_blank"} |
