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

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

library(admiraldev)
```

# Introduction

This article describes creating a laboratory ADaM for neuroscience clinical trials.

We advise you first consult the `{admiral}` [Creating a BDS Finding ADaM vignette](https://pharmaverse.github.io/admiral/cran-release/articles/bds_finding.html).
The programming workflow around creating the general set-up of an `ADLB` using `{admiral}` functions is the same. 
In this vignette, we focus on common ADLB derivations in neuroscience studies and avoid repeating information and maintaining the same content in two places. 

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

## Required Packages

The following packages are required to run the examples in this vignette.

```{r, warning=FALSE, message=FALSE}
library(admiral)
library(admiralneuro)
library(pharmaversesdtm)
library(dplyr)
library(stringr)
```

# Programming Workflow

-   [Read in Data](#readdata)
-   [Define Lookup Tables](#lookups)
-   [Derive Core ADLB Variables](#derive_core)
-   [Derive Log Transformation of Biomarkers](#neuro_params)
-   [Remaining ADLB Set-up](#adlb_end)
-   [Example Script](#example)

## Read in Data {#readdata}

To start, all data frames needed for the creation of the ADaM dataset should be loaded into the global environment. Reading data will usually be a company specific process, however, for the purpose of this vignette, we will use example data from `{pharmaversesdtm}` and `{admiralneuro}`. We will utilize `LB` and `ADSL` data.

```{r, message=FALSE, warning=FALSE}
lb <- convert_blanks_to_na(pharmaversesdtm::lb_neuro)
adsl <- convert_blanks_to_na(admiralneuro::adsl_neuro)
```

## Define Lookup Tables {#lookups}

Define parameter lookup table used to derive `PARAMCD`, `PARAM`, and `PARAMN` variables. 

```{r}
# Assign PARAMCD, PARAM, and PARAMN
param_lookup <- tibble::tribble(
  ~LBTESTCD, ~PARAMCD, ~PARAM, ~PARAMN,
  "PTAU217", "PTAU217", "Lumipulse G pTau 217 Plasma (pg/mL)", 1,
  "AMYLB42", "AMYLB42", "Lumipulse G Beta-Amyloid 1-42-N Plasma (pg/mL)", 2,
  "PTAB42R", "PTAB42R", "Lumipulse G pTau 217/Beta-Amyloid 1-42 Plasma Ratio", 3,
  "ASYNASAA", "ASYNASAA", "Alpha Synuclein Seed Amplification Assay (CSF)", 4,
  "TAU181P", "TAU181P", "Elecsys Tau Protein Phosphorylated 181", 5
)
```

## Derive Core ADLB Variables {#derive_core}

The basic parameters and timing variables can be derived similarly to other BDS finding ADaMs.
For the derivation of analysis values, various variable types and significant figures need to be considered. 

```{r, message=FALSE}
# Get list of ADSL vars required for derivations
adsl_vars <- exprs(TRTSDT, TRTEDT, TRT01A, TRT01P)

adlb <- lb %>%
  # Join ADSL with LB data (need TRTSDT for ADY derivation) ----
  derive_vars_merged(
    dataset_add = adsl,
    new_vars = adsl_vars,
    by_vars = get_admiral_option("subject_keys")
  )

adlb <- adlb %>%
  # Add PARAMCD, PARAM and PARAMN ----
  derive_vars_merged_lookup(
    dataset_add = param_lookup,
    new_vars = exprs(PARAMCD, PARAM, PARAMN),
    by_vars = exprs(LBTESTCD)
  )

# Add analysis date (ADT)
adlb <- adlb %>%
  derive_vars_dt(new_vars_prefix = "A", dtc = LBDTC) %>%
  derive_vars_dy(reference_date = TRTSDT, source_vars = exprs(ADT))

# Derive analysis visit (AVISIT, AVISITN)
adlb <- adlb %>%
  mutate(
    AVISIT = case_when(
      !is.na(VISIT) ~ str_to_title(VISIT),
      TRUE ~ NA_character_
    ),
    AVISITN = case_when(
      AVISIT == "Baseline" ~ 0,
      str_detect(str_to_upper(VISIT), "WEEK") ~
        as.integer(str_extract(VISIT, "\\d+")),
      TRUE ~ NA_integer_
    ),
    BASETYPE = "LAST"
  )

# Derive AVAL and AVALC
adlb <- adlb %>%
  mutate(
    LBSTRESN2 = case_when(
      PARAMN == 1 ~ round(LBSTRESN, 4),
      PARAMN == 2 ~ round(LBSTRESN, 1),
      PARAMN == 3 ~ round(LBSTRESN, 5),
      PARAMN == 4 ~ LBSTRESN,
      PARAMN == 5 ~ round(LBSTRESN, 3),
      TRUE ~ NA
    ),
    AVAL = LBSTRESN,
    # Only populate AVALC if the character value is non-redundant with AVAL,
    # following standard ADaM conventions.
    AVALC = if_else(
      is.na(AVAL) | as.character(signif(LBSTRESN2, 5)) != LBSTRESC,
      LBSTRESC,
      NA_character_
    ),
    ANRLO = LBSTNRLO,
    ANRHI = LBSTNRHI
  ) %>%
  select(!LBSTRESN2)
```

```{r echo=FALSE}
# Example display of derived data
dataset_vignette(
  arrange(adlb, USUBJID, ADY, PARAMN),
  display_vars = exprs(!!!get_admiral_option("subject_keys"), PARAMCD, PARAM, AVAL, ADY, AVISIT, AVISITN)
)
```

For deriving visits based on time-windows, see `{admiral}` [Visit and Period Variables](https://pharmaverse.github.io/admiral/cran-release/articles/visits_periods.html).

## Derive Log Transformation of Biomarkers {#neuro_params}

In addition to the core ADLB variables, log transformation of fluid biomarker values is essential for further analyses and graphing as these values are typically skewed.

```{r}
# Derive log-transformed AMYLB42 parameter for further analyses and plotting
adlb <- adlb %>%
  derive_param_computed(
    by_vars = exprs(
      !!!get_admiral_option("subject_keys"), AVISIT, AVISITN,
      ADT, ADY, !!!adsl_vars
    ),
    parameters = "AMYLB42",
    set_values_to = exprs(
      AVAL = log(AVAL.AMYLB42),
      PARAMCD = "LAMYLB42",
      PARAM = "Log-Transformed Lumipulse G Beta-Amyloid 1-42-N Plasma (pg/mL)",
      PARAMN = 6
    )
  )
```

```{r echo=FALSE}
# Example display of derived data
dataset_vignette(
  filter(adlb, PARAMCD == "LAMYLB42") %>%
    arrange(USUBJID, ADY, PARAMN),
  display_vars = exprs(!!!get_admiral_option("subject_keys"), PARAMCD, PARAM, AVAL, ADY, AVISIT, AVISITN)
)
```

## Remaining ADLB Set-up {#adlb_end}

The `{admiral}` [Creating a BDS Finding ADaM vignette](https://pharmaverse.github.io/admiral/cran-release/articles/bds_finding.html) describes the remaining standard ADLB derivations, including how to calculate baseline and change from baseline variables, add analysis flags (e.g., `ANL01FL`), handle reference ranges, categorizations, and other common ADLB requirements.

# Example Script {#example}

| ADaM | Sourcing Command                                            |
|------|-------------------------------------------------------------|
| `ADLB` | `admiral::use_ad_template("ADLB", package = "admiralneuro")` |
