In this vignette we show the general autoslider.core workflow, how you can create functions that produce study-specific outputs, and how you can integrate them into the autoslider.core framework.

Requirements

Of course, you need to have the autoslider.core package installed, and you need to have data available. In this example I use example data stored in the autoslider.core package.

The data needs to be stored in a named list where the names should correspond to ADaM data sets.

Workflow

The folder structure could look something like:

├── programs
│   ├── run_script.R
│   ├── R   
|   |   ├── helping_functions.R
|   |   ├── output_functions.R
├── outputs
├── specs.yml
├── filters.yml

The autoslideR workflow would be implemented in the run_script.R file. This workflow does not require the files in R/. However, if custom output-creating functions are implemented, R/ would be the place to put them.

The autoslideR workflow has four main aspects:

The specifications specs.yml

This file contains the specifications of all outputs you would like to create.

For each output we define specific information, namely the program name, the footnotes & titles, the paper (this indicates the orientation, P for portrait and L for landscape, the number indicates the font size), the suffix and args.

It could look something like that:

- program: t_ds_slide
  titles: Patient Disposition ({filter_titles("adsl")})
  footnotes: 't_ds footnotes'
  paper: L6
  suffix: ITT
- program: t_dm_slide
  titles: Patient Demographics and Baseline Characteristics
  footnotes: 't_dm_slide footnote'
  paper: L6
  suffix: ITT
  args:
    arm: "TRT01A"
    vars: ["SEX", "AGE", "RACE", "ETHNIC", "COUNTRY"]

The program name refers to a function that produces an output. This could be one of the _slide functions in autoslider.core or a custom function.

Titles and footnotes are added once the outputs are created. We refer to that as decorating the outputs.

The suffix specifies the name of the filters that are applied to the data, before the data is funneled into the function (program). The filters themselves are specified in the filters.yml file.

The filters filters.yml

In filters.yml we specify the names of the filters used across the outputs. Each filter has a name (e.g. FAS), a title (Full Analysis Set), and then the filtering condition on a target dataset. The filter title may be appended to the output title. For the t_ds_slides slide above all filter titles that target the adsl dataset would be included in the brackets. We would thus expect the title to read: “Patient Disposition (Full Analysis Set)”

[what is the type?]

As you can see, we don’t just have population filters, but also filters on serious adverse events. We can thus produce SAE tables by just supplying the serious adverse events to the AE table function. This concept generalizes also to PARAMCD values.

ITT:
  title: Intent to Treat Population
  condition: ITTFL =='Y'
  target: adsl
  type: slref
SAS:
  title: Secondary Analysis Set
  condition: SASFL == 'Y'
  target: adsl
  type: slref
SE:
  title: Safety Evaluable Population
  condition: SAFFL=='Y'
  target: adsl
  type: slref
SER:
  title: Serious Adverse Events
  condition: AESER == 'Y'
  target: adae
  type: anl

The functions

You can find an overview of all autoslider.core functions here. Note that all output-producing functions end with _slide while the prefix (i.e. t_, l_, g_) specify the type of output (i.e. table, listing, or graph respectively). Custom functions are needed if the autoslider.core functions do not cover the outputs you need. More on that further down.

The backend machinery

A typical workflow could look something like this:

# define path to the yml files
spec_file <- "spec.yml"
filters <- "filters.yml"
library("dplyr")
# load all filters
filters::load_filters(filters, overwrite = TRUE)
# read data
data <- list(
  "adsl" = eg_adsl %>%
    mutate(
      FASFL = SAFFL, # add FASFL for illustrative purpose for t_pop_slide
      # DISTRTFL is needed for t_ds_slide but is missing in example data
      DISTRTFL = sample(c("Y", "N"), size = length(TRT01A), replace = TRUE, prob = c(.1, .9))
    ) %>%
    preprocess_t_ds(), # this preproccessing is required by one of the autoslider.core functions
  "adae" = eg_adae,
  "adtte" = eg_adtte,
  "adrs" = eg_adrs,
  "adlb" = eg_adlb
)



# create outputs based on the specs and the functions
outputs <- spec_file %>%
  read_spec() %>%
  # we can also filter for specific programs, if we don't want to create them all
  filter_spec(., program %in% c(
    "t_ds_slide",
    "t_dm_slide"
  )) %>%
  # these filtered specs are now piped into the generate_outputs function.
  # this function also requires the data
  generate_outputs(datasets = data) %>%
  # now we decorate based on the specs, i.e. add footnotes and titles
  decorate_outputs(
    version_label = NULL
  )
#> ✔ 2/3 outputs matched the filter condition `program %in% c("t_ds_slide", "t_dm_slide")`.
#> ❯ Running program `t_ds_slide` with suffix 'ITT'.
#> Filter 'ITT' matched target ADSL.
#> 400/400 records matched the filter condition `ITTFL == 'Y'`.
#> ❯ Running program `t_dm_slide` with suffix 'ITT'.
#> Filter 'ITT' matched target ADSL.
#> 400/400 records matched the filter condition `ITTFL == 'Y'`.

We can have a look at one of the outputs stored in the outputs file:

outputs$t_dm_slide_ITT
#> An object of class "dVTableTree"
#> Slot "tbl":
#>  Patient Demographics and Baseline Characteristics, Intent to Treat Population
#> 
#> ———————————————————————————————————————————————————————————————————————————————————————————————————————