From 5ec7da9a4d691f64802f42d114cd69a0e7ee55c9 Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Tue, 31 Aug 2021 15:43:28 -0400 Subject: [PATCH 1/8] update license. fix #497 --- .Rbuildignore | 1 + DESCRIPTION | 5 ++--- LICENSE | 4 ++-- LICENSE.md | 21 +++++++++++++++++++++ 4 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 LICENSE.md diff --git a/.Rbuildignore b/.Rbuildignore index ab2f169e..893b8fef 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -14,3 +14,4 @@ ^CRAN-RELEASE$ ^customSettings$ ^\.github$ +^LICENSE\.md$ diff --git a/DESCRIPTION b/DESCRIPTION index 934c89c8..fa9a3712 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,13 +2,12 @@ Package: safetyGraphics Title: Create Interactive Graphics Related to Clinical Trial Safety Version: 2.0.0 Authors@R: c( - person("Jeremy", "Wildfire", email = "jeremy_wildfire@rhoworld.com", role = c("cre","aut")), + person("Jeremy", "Wildfire", email = "jwildfire@gmail.com", role = c("cre","aut")), person("Becca", "Krouse", role="aut"), person("Preston","Burns", role="aut"), person("Xiao","Ni", role = "aut"), person("James","Buchanan", role="aut"), - person("Susan","Duke", role="aut"), - person("Interactive Safety Graphics Working Group", role = "aut")) + person("Susan","Duke", role="aut") Maintainer: Jeremy Wildfire Description: A framework for evaluation of clinical trial safety. Users can interactively explore their data using the 'Shiny' application or create standalone 'htmlwidget' charts. Interactive charts are built using 'd3.js' and 'webcharts.js' 'JavaScript' libraries. URL: https://github.com/SafetyGraphics/safetyGraphics diff --git a/LICENSE b/LICENSE index f7b8a19e..f02ff01c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,2 +1,2 @@ -YEAR: 2018 -COPYRIGHT HOLDER: Rho Inc. +YEAR: 2021 +COPYRIGHT HOLDER: safetyGraphics authors diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..db5cbda1 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2021 safetyGraphics authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From c19370fb0f0acae4070eeba1485de3b78b7a232e Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Tue, 31 Aug 2021 16:08:38 -0400 Subject: [PATCH 2/8] update readme for v2. fix #545 --- README.md | 44 ++++++++------------------------------------ 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 171012f0..bcb77b4b 100644 --- a/README.md +++ b/README.md @@ -2,24 +2,15 @@ [![R build status](https://github.com/ASA-DIA-InteractiveSafetyGraphics/safetyGraphics/workflows/R-CMD-check/badge.svg)](https://github.com/ASA-DIA-InteractiveSafetyGraphics/safetyGraphics/actions) -# safetyGraphics: Clinical Trial Safety Graphics with R +# safetyGraphics: Clinical Trial Safety Monitoring with R -The **safetyGraphics** package provides a framework for evaluation of clinical trial safety in R. It includes several safety-focused visualizations to empower clinical data monitoring. Chief among these is the Hepatic Explorer, based on the [Evaluation of the Drug-Induced Serious Hepatotoxicity (eDish)](https://www.ncbi.nlm.nih.gov/pubmed/21332248) visualization. A demo of the Hepatic Explorer interactive graphic is available [here](https://safetygraphics.github.io/hep-explorer/test-page/example1/) and is shown below. - -This package is being built in conjunction with the [hep-explorer](https://github.com/SafetyGraphics/hep-explorer) javascript library. +The {safetyGraphics} package provides a framework for evaluating of clinical trial safety in R using a flexible data pipeline. The package includes a shiny application that allows users to explore safety data using a series of interactive graphics, including the hepatic safety explorer shown below. The package has been developed as part of the Interactive Safety Graphics (ISG) workstream of the ASA Biopharm-DIA Safety Working Group. ![edishgif](https://user-images.githubusercontent.com/3680095/45834450-02b3a000-bcbc-11e8-8172-324c2fe43521.gif) -## Usage - -Users can interactively explore their data with a shiny application or create standalone interactive charts. +## Using the app -### Shiny application - -The Shiny app provides a simple interface for: -- Loading data -- Customizing settings and data mappings -- Viewing and exporting the interactive graphics +A demo of the app using sample data is available [here](https://jwildfire.shinyapps.io/safetyGraphics/) or can be initialized as follows: ```r devtools::install_github("SafetyGraphics/safetyGraphics") @@ -27,29 +18,10 @@ library("safetyGraphics") safetyGraphicsApp() #open the shiny application ``` -### Standalone charts +The most common workflow is for a user to initialize the app with their data, adjust settings as needed, and view the interactive charts. Finally, the user can share any chart by exporting its source code or by generating a self-contained, fully reproducible report that can be shared with others. -Users can also initialize customized standalone charts with a few lines of code. +Instructions for loading study data are provided in the introductory vignette and more complex customizations are provided in the cookbook vignette. -```r -devtools::install_github("safetyGraphics/safetyGraphics") -library("safetyGraphics") - -settings <- list( - id_col = "USUBJID", - value_col = "AVAL", - measure_col = "PARAM", - visit_col = "VISIT", - visitn_col = "VISITNUM", - studyday_col = "ADY", - normal_col_low = "A1LO", - normal_col_high = "A1HI", - measure_values = list(ALT = "Alanine Aminotransferase (U/L)", - AST = "Aspartate Aminotransferase (U/L)", - TB = "Bilirubin (umol/L)", - ALP = "Alkaline Phosphatase (U/L)") - ) - -chartRenderer(data=adlbc, settings=settings, chart="hepexplorer") +# Charts +The app is built to support a wide variety of chart types including static plots (e.g. from {ggplot2}), shiny modules, {htmlwidgets} and even static outputs like RTFs. Several pre-configured charts are included in the companion {safetyCharts} R Package, and are available by default in the app. Other charts can be added using the process descibed in this vignette. -``` From b9d3b356d76ac2b22c38b59c874edf34cb3fcbd6 Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Tue, 31 Aug 2021 16:43:30 -0400 Subject: [PATCH 3/8] adding first v2 vignettes --- DESCRIPTION | 2 +- NAMESPACE | 2 - vignettes/chartConfiguration.Rmd | 319 +++++++++++++++++++++ vignettes/customWorkflows.Rmd | 461 ------------------------------- vignettes/intro.Rmd | 139 ++++++++++ vignettes/shinyUserGuide.Rmd | 237 ---------------- 6 files changed, 459 insertions(+), 701 deletions(-) create mode 100644 vignettes/chartConfiguration.Rmd delete mode 100644 vignettes/customWorkflows.Rmd create mode 100644 vignettes/intro.Rmd delete mode 100644 vignettes/shinyUserGuide.Rmd diff --git a/DESCRIPTION b/DESCRIPTION index fa9a3712..d15e10ff 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -7,7 +7,7 @@ Authors@R: c( person("Preston","Burns", role="aut"), person("Xiao","Ni", role = "aut"), person("James","Buchanan", role="aut"), - person("Susan","Duke", role="aut") + person("Susan","Duke", role="aut")) Maintainer: Jeremy Wildfire Description: A framework for evaluation of clinical trial safety. Users can interactively explore their data using the 'Shiny' application or create standalone 'htmlwidget' charts. Interactive charts are built using 'd3.js' and 'webcharts.js' 'JavaScript' libraries. URL: https://github.com/SafetyGraphics/safetyGraphics diff --git a/NAMESPACE b/NAMESPACE index 432ddc30..ba3befaa 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -84,5 +84,3 @@ importFrom(stringr,str_to_upper) importFrom(utils,hasName) importFrom(utils,zip) importFrom(yaml,as.yaml) -importFrom(yaml,write_yaml) - diff --git a/vignettes/chartConfiguration.Rmd b/vignettes/chartConfiguration.Rmd new file mode 100644 index 00000000..72aba17f --- /dev/null +++ b/vignettes/chartConfiguration.Rmd @@ -0,0 +1,319 @@ +--- +title: "Chart Configuration" +author: "Jeremy Wildfire" +date: "`r Sys.Date()`" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Chart Configuration} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +# Chart Configuration Vignette + +The {safetyGraphics} shiny app can be used to display a wide variety of charts. This vignette provides details about the charting process including step-by-step instructions for adding new charts and technical specifications, but first we need to talk about a 2nd package ... + +# Introducing {safetyCharts} + +While this is technically a vignette for {safetyGraphics}, the {safetyCharts} package is just as important here. The roles of the packages can be summarized in just a few words: + + **The {safetyGraphics} platform displays charts from {safetyCharts}.** + +This relationship is central to the technical framework for the safetyGraphics app. By itself, the `safetyGraphics` **platform** really doesn't do much! In fact, none of the content on the Charts tab is actually found in the `safetyGraphics` package; it's all imported from elsewhere! As you've probably guessed, the default charts live in the `safetyCharts` package. `safetyCharts` has over a dozen charts that are configured to work with {safetyGraphics}, but can also easily be used independently. + +While {safetyGraphics} and {safetyCharts} are designed to work seamlessly together, users can also add charts from other packages. In fact, several charts in {safetyCharts} are just wrappers that load charts from other packages for use in {safetyGraphics}. The rest of this vignette provides a series of step-by-step examples detailing how this process works for different types of charts. + +# {safetyGraphics} Chart Components + +To add a chart to safetyGraphics, two components are required: + +1. A Configuration Object +2. A Chart Function + +The configuration file captures metadata about the chart for use in the app and is typically saved as a YAML file. Several example configuration files are provided in the examples below, and YAML Configuration files for {safetyCharts} are saved [here](https://github.com/SafetyGraphics/safetyCharts/tree/dev/inst/config). + +The chart function typically takes a list of `settings` and a list of `data` as inputs and returns a chart object ready to be displayed in the app. Details of charting functions vary somewhat for different chart types, as explained in the examples below. + +A full technical specification of this chart configuration framework is provided in Appendix 1. + +# Example 1 - Hello World + +Once you've created the configuration and chart functions, the chart can be added to the app via the `charts` parameter in `safetyGraphicsApp()`. Consider this simple "Hello World" example: + +``` +# Chart Function +helloWorld <- function(data, settings){ + plot(-1:1, -1:1) + text(runif(20, -1,1),runif(20, -1,1),"Hello World") +} + +# Chart Configuration +helloworld_chart<-list( + env="safetyGraphics", + name="HelloWorld", + label="Hello World!", + type="plot", + domain="aes", + workflow=list( + main="helloWorld" + ) +) + +safetyGraphicsApp(charts=list(helloworld_chart)) +``` + +It's also easy to add a custom chart to the default charts provided in {safetyCharts} using the `makeChartConfig()` function: + +``` +charts <- makeChartConfig(packages="safetyCharts") # or just makeChartConfig() since safetyCharts is included by default +charts$helloworld<-helloworld_chart +safetyGraphicsApp(charts=charts) +``` + +Here's our Hello World the chart running in the app: + + + +# Example 2 - Static Outlier Explorer + +Now let's consider a more complex example that makes use of the `data` and `settings` provided in `safetyGraphics`. In this section, we use {ggplot2} to create a spaghetti plot for tracking outliers in lab data. First, consider the following code which creates a stand-alone plot for a single data set: + +``` +# Use sample clinical trial data sets from the {safetyData} package +library(safetyData) +library(ggplot2) +library(dplyr) + +# Define data mapping using a format similar to a reactive safetyGraphics mapping +settings <- list( + id_col="USUBJID", + value_col="LBSTRESN", + measure_col="LBTEST", + studyday_col="LBDY" +) + +# Define a plotting function that takes data and settings as inputs +spaghettiPlot <- function( data, settings ){ + # define plot aes - note use of standard evaluation! + plot_aes <- aes_( + x=as.name(settings$studyday_col), + y=as.name(settings$value_col), + group=as.name(settings$id_col) + ) + + #create the plot + p<-ggplot(data = data, plot_aes) + + geom_path(alpha=0.15) + + facet_wrap( + as.name(settings$measure_col), + scales="free_y" + ) + return(p) +} + +spaghettiPlot( + safetyData::sdtm_lb %>% + filter(LBTEST %in% c("Albumin","Bilirubin","Calcium","Chloride")), + settings +) +``` + +Running the code above should create a plot with 4 panels: + + + +With minor modifications, this chart can be added to the {safetyGraphics} shiny app, which allows us to create the chart with any mappings/data combination loaded in the app. The `spaghettiPlot()` function above is already written to work with safetyGraphics, so we just need to create the chart configuration object. This time we'll capture the configuration in a [YAML](https://yaml.org/) file. + +``` +env: safetyGraphics +label: Spaghetti Plot +type: plot +domain: + - labs +workflow: + main: spaghettiPlot +links: + safetyCharts: https://github.com/SafetyGraphics/safetycharts +``` + +With the charting function loaded in to our session and the configuration file saved in our working directory as `spaghetti.yaml`, we can add the chart to the app as follows: + +``` +library(yaml) +charts <- makeChartConfig() +charts$spaghetti<-prepareChart(read_yaml('spaghetti.yaml')) +safetyGraphicsApp(charts=charts) +``` +Under the charts tab, you'll see: + + + +If you look closely at the `spaghettiPlot()` code above, you'll noticed some details that make the chart work in the app: + + - The chart function is written as a function taking `data` and `settings` as inputs. This is the expected parameterization for most charts in {safetyGraphics}. +- The references to `settings` use parameters that are defined on the mapping tab. Behind the scenes, these are defined in the `safetyGraphics::meta`. +- The `spaghettiPlot` function is referenced in the `main` item the YAML `workflow`. This tells the app which function to use to draw the chart. + +These details allow users to dynamically define data attributes for any labs data set, allowing the chart to be reused across many different types of data. + +This example is inspired by `safetyCharts::safety_outlier_explorer` - the [charting function](https://github.com/SafetyGraphics/safetyCharts/blob/dev/R/safety_outlier_explorer.R) and [yaml configuration file](https://github.com/SafetyGraphics/safetyCharts/blob/dev/inst/config/safetyOutlierExplorerStatic.yaml) on are GitHub. + +# Example 3 - Shiny Module + +{safetyGraphics} also supports defining charts as Shiny Modules. Once you're [familiar](https://shiny.rstudio.com/articles/modules.html) [with](https://mastering-shiny.org/scaling-modules.html) [modules](https://emilyriederer.netlify.app/post/shiny-modules/), they are relatively straightforward to use with safetyGraphics. + +Let's take a look at a simple module that extends the functionality of the static chart from the example above. Once again, this example is based upon `safetyCharts`, and you can see the [code](https://github.com/SafetyGraphics/safetyCharts/blob/dev/R/mod_safetyOutlierExplorer.R) and [config](https://github.com/SafetyGraphics/safetyCharts/blob/dev/inst/config/safetyOutlierExplorerModule.yaml) on GitHub. + +The config object for a module differs from a static chart is that the workflow section of the YAML file must specify `ui` and `server` functions instead of a `main` charting function. This example defines a simple UI function that allows users to select which lab measurements should be included in the spaghetti plot from example 1: + +``` +safetyOutlierExplorer_ui <- function(id) { + ns <- NS(id) + sidebar<-sidebarPanel( + selectizeInput( + ns("measures"), + "Select Measures", + multiple=TRUE, + choices=c("") + ) + ) + main<-mainPanel(plotOutput(ns("outlierExplorer"))) + ui<-fluidPage( + sidebarLayout( + sidebar, + main, + position = c("right"), + fluid=TRUE + ) + ) + return(ui) +} +``` + +Next we define a server function that populates the control for selecting measurements and then draws the plot using [`safetyCharts::safety_outlier_explorer()`](https://github.com/SafetyGraphics/safetyCharts/blob/dev/R/safety_outlier_explorer.R) charting function - which is based on the `spaghetti()` function ! Note that the server function takes a single reactive `params` object containing the data (`params$data`) and settings (`param$settings`) as input. + +``` +safetyOutlierExplorer_server <- function(input, output, session, params) { + + ns <- session$ns + # Populate control with measures and select all by default + observe({ + measure_col <- params()$settings$measure_col + measures <- unique(params()$data[[measure_col]]) + updateSelectizeInput( + session, + "measures", + choices = measures, + selected = measures + ) + }) + + # customize selected measures based on input + settingsR <- reactive({ + settings <- params()$settings + settings$measure_values <- input$measures + return(settings) + }) + + #draw the chart + output$outlierExplorer <- renderPlot({safety_outlier_explorer(params()$data, settingsR())}) +} +``` + +Finally, the YAML configuration file looks like this - just the workflow and label changes from Example 1: + +``` +env: safetyGraphics +label: Outlier Explorer - Module +type: module +package: safetyCharts +domain: + - labs +workflow: + ui: safetyOutlierExplorer_ui + server: safetyOutlierExplorer_server +links: + safetyCharts: https://github.com/SafetyGraphics/safetycharts +``` + +Initializing the app as usual by adding it to the chart list: +`charts$outlierMod<-prepareChart(read_yaml('outlierMod.yaml'))` + +Unselecting a few measures gives the following display: + + +# Example 4 - htmlwidgets and init functions + +You can also add custom htmlwidgets to safetyGraphics. In fact, many of the [default charts](https://github.com/SafetyGraphics/safetyCharts/tree/dev/inst/htmlwidgets) imported from safetyCharts are javascript libraries that are imported as htmlwidgets. Like shiny modules, htmlwidgets are relatively simple to use once you are [familiar with the basics](https://www.htmlwidgets.org/). + +The biggest differences between widgets and other charts in safetyGraphics are: + +1. The widget must be contained in a package, which must be specified in the YAML file. +2. The widget expects a `widget` item giving the name of the widget in the YAML workflow. +3. By default, the data and settings for a widget are passed in a list (`list(data=data, settings=settings)`) to the `x` parameter in `htmlwidget::createWidget`. + +Items 1 and 2 above are simple enough, but #3 is likely to create problems unless the widget is designed specifically for usage with safetyGraphics. That is, if the widget isn't expecting `x$settings` to be a list that it uses to configure the chart, it probably isn't going to work as expected. + +Fortunately, there's a workaround built in to safetyGraphics in the form of `init` workflow functions. Init functions run before the chart is drawn, and can be used to create custom parameterizations. The init function should take `data` and `settings` as inputs and return `params` which should be a list which is then provided to the chart (see the appendix for more details). The [init function](https://github.com/SafetyGraphics/safetyCharts/blob/dev/R/init_aeExplorer.R) for the the interactive [AE Explorer](https://github.com/RhoInc/aeexplorer) is a good example. It starts by [merging demographics and adverse event data](https://github.com/SafetyGraphics/safetyCharts/blob/c37f3ac7883b15ab3d8a36e597dec85728657fd7/R/init_aeExplorer.R#L16-L18) and then proceeds to [create a customized settings object](https://github.com/SafetyGraphics/safetyCharts/blob/c37f3ac7883b15ab3d8a36e597dec85728657fd7/R/init_aeExplorer.R#L20-L43) to match [the configuration requirements](https://github.com/RhoInc/aeexplorer/wiki/Configuration) of the javascript chart renderer. This init function is then saved under `workflow$init` in the chart config object. + +The rest of the [chart configuration YAML](https://github.com/SafetyGraphics/safetyCharts/blob/dev/inst/config/aeExplorer.yaml) is similar to the examples above, and the chart is once again by passing the chart config object to `safetyGraphicsApp()` + +# Appendix #1 - Chart Framework Technical Specifications + +## Configuration Overview + + + +The diagram above summarizes the various components of the safetyGraphics charting framework: +- The `safetyGraphicsApp()` function allows users to specify which charts to include in the shiny app via the `charts` parameter, which expects a `list` of charts. +- Each item in `charts` is itself defined as a `list` that provides configuration details for a single chart. These configuration lists have several required parameters, which are described in the technical specification below. +- Configuration lists are typically saved as YAML files, but can be also be loaded directly as list objects as shown in the Hello World example above. +- Needed functions are bound to the chart object via the prepareChart() function. See the documentation for `chart$functions` below for full details. + +## Chart Specification + +Each item in the `charts` list should be a list() with the following parameters: +- `env`: Environment for the chart. Must be set to "safetyGraphics" or the chart is dropped. Type: *character*. **Required** +- `name`: Name of the chart. Type: *character*. **Required** +- `type:`: Type of chart. Valid options are: "plot","htmlwidget","html","table" and "module". Type: *character*. **Required** +- `label`: A short description of the chart. chart$name is used if not provided. Type: *character*. *Optional* +- `domain`: The data domain(s) used in the chart. Type: *character*. **Required** +- `package`: The package where the {htmlwidget} is saved. Type: *character*. **Required** when `chart$type` is "htmlwidget" +- `order`: Order in which to display the chart. If order is a negative number, the chart is dropped. Defaults to 999999. Type: *Integer*. *Optional* +- `links`: Named list of link names/urls to be shown in the chart header. Type: *list of character*. *Optional* +- `path`: Full path of the YAML file. Auto-generated by `makeChartConfig()` Type: *character* *optional* +- `workflow`: Names of functions used to create the chart. Should be loaded in global environment or included in `chart$package` before calling `prepareChart()`. Supported parameters are listed below. Type: *list of character*. **Required** + - `workflow$main`: name of the function to draw the chart. The function should take `data` and `settings` parameters unless the input parameters are customized by an `init` function. **Required**, unless `chart$type` is "htmlwidget" or "module") + - `workflow$init: name of initialization function that runs before chart is drawn via the `main` function. Should take `data` and `settings` as input and return a list of parameters accepted by the `main` function. *Optional* + - `workflow$widget`: name or widget saved in `chart$package` to be passed to `htmlwidgets::createWidget` **Required** when `chart$type` is "htmlwidget" + - `workflow$ui` and `workflow$server`: names of functions to render shiny ui and server. Automatically generated in `prepareChart()` unless `chart$type` is "module". **Required** when `chart$type` is 'module' +- `functions`: a list of functions used to create the chart. Typically generated at runtime by `prepareChart()` using information in `chart$workflow`, `chart$type` and `chart$package`. Not recommended to generate manually. Type: *list of functions*. **Required** + +## Default Technical workflow + +This appendix describe the technical process used to render a chart when safetyGraphicsApp() is called with the default parameters. + +1. `safetyGraphicsApp()` is called with `charts` and `chartSettingsPath` as NULL (the default). +2. `app_startup` is called, which then immediately calls `makeChartConfig()`. +3. `makeChartConfig()` looks for charts in the safetyCharts package (the default) since no path was specified. The function looks for the package in all current `.libPaths()` and then looks in the `inst/config` folder once the package is found. +4. `makeChartConfig` loads YAML configuration files in the specified directories and saves them to a list. `name` and `path` parameters are added. +5. `makeChartConfig` calls `prepareChart` for each chart configuration. `prepareChart` sets default values for `order`, `name` and `export`, and then binds relevant functions to a `chart$functions` list based on the chart's `type`, `workflow` and `package`. +6. That list of charts is then returned to `app_startup()` which runs a few actions on each chart: + - If `chart$functions` is missing, `prepareChart` is called (not relevant in the default workflow, but useful for adding custom charts) + - If `chart$order` is negative, the chart is dropped with a message. + - If `chart$env` is not "safetyGraphics", the chart is dropped with a message. + - If `chart$domains` has elements not found in the `dataDomains` passed to `app_startup(), the chart is dropped with a message. + - `charts` are re-ordered based on `chart$order` +7. `app_startup` returns the list of charts to `safetyGraphicsApp` which then then passes them along to `safetyGraphicsServer` as the `charts` parameter. +8. `safetyGraphicsServer` then creates modules for each chart. First, `UIs` are created via `chartsNav()` which then calls: + - `makeChartSummary` to create the chart header with links and metadata and ... + - `ChartsTabUI` which then calls `chart$functions$ui` to create the proper UI element based on `chart$type`. +8. Next, `safetyGraphicsServer` draws the charts using `chartsTab()` which: + - Creates a reactive `params` object containing mappings and data using `makeChartParams()` which: + - Subsets `domainData` based on `chart$domain` + - Calls `charts$functions$init` if provided + - Does custom formatting for `chart$type` of "htmlwidget" + - Chart is drawn using `chart$functions$server` and `chart$functions$main` + - Button to download R script is added to header. Script is created by `makeChartExport()` + - Button to download html report is added to header unless type="module". Report template is at "inst/reports/safetyGraphicsReport.Rmd" +9. Finally, `safetyGraphicsServer` passes the charts to `settingsTab`, which uses them to help populate the `charts` and `code` subtabs. diff --git a/vignettes/customWorkflows.Rmd b/vignettes/customWorkflows.Rmd deleted file mode 100644 index ef80cab8..00000000 --- a/vignettes/customWorkflows.Rmd +++ /dev/null @@ -1,461 +0,0 @@ ---- -title: "safetyGraphics Shiny App - Custom Workflows" -author: "Jeremy Wildfire" -date: "`r Sys.Date()`" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{safetyGraphics Shiny App - Custom Workflows} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r setup, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -``` -# Overview -The safetyGraphics package is designed to serve as a flexible and extensible platform for analyzing clinical trial safety. This vignette shows how users can configure the safetyGraphics shiny app with workflows using customized charts and data. - -Version 1.1 of the package allows users to preload their own charts and data sets for use in the safetyGraphics Shiny Application. Many types of clinical trial lab data are supported in conjunction with 4 types of charts - Static charts, Plotly charts, Shiny Modules and HTML widgets. As shown in the next section, loading data is simple, but adding custom charts is slightly more complex. Behind the scenes, all 4 chart types have two major technical components: **code** and **metadata**. As such, making a custom chart requires the user to create an R script that defines the chart's code and metadata. We provide several examples below that describe the step-by-step process for creating a chart. - -# Adding Custom Data - -Run `safetyGraphicsApp(loadData=TRUE)` to preload all data.frames from your current R session in a new instance of the safetyGraphics Shiny app. While users can still manually load additional `.csv` or `.sas7bdat` files in the app as needed, this programatic alternative allows for more flexibility for loading other data sources, and can help to automate situations where users want to load multiple files. For example, running the code below will preload several example data sets saved on our GitHub site. - -``` -#Load in data sets with different data standards -data_url <- 'https://raw.githubusercontent.com/SafetyGraphics/SafetyGraphics.github.io/master/pilot/' -SDTM<-read.csv(paste0(data_url,'SampleData_SDTM.csv')) -SDTM_Partial<-read.csv(paste0(data_url,'SampleData_PartialSDTM.csv')) -AdAM_Partial<-read.csv(paste0(data_url,'SampleData_PartialADaM.csv')) -NoStandard<-read.csv (paste0(data_url,'SampleData_NoStandard.csv')) -AdAM <- adlbc #loadData=TRUE overrides the default behavior where adlbc is automatically preloaded into the app - -#Initialize the app with data from the session -safetyGraphicsApp(loadData=TRUE) - -``` - -Clicking on the data tab shows the 5 pre-loaded data sets with their different data standards. - - - -This data load process can easily be combined with the chart workflow described below (including `customSettings.R` programs) to create easily reusable, custom workflows. - -# Steps to Create a Custom Chart - -There are 4 steps required to create a custom chart for use in `safetyGraphics`: - -1. Create custom chart code -2. Add new settings to the app (if needed) -3. Add the chart to the app -4. Initialize the app - -The remainder of this vignette is dedicated to 4 examples that describe the process for creating custom charts in more detail. Note that full code for all examples are available in Appendix 3 at the end of this vignette. - -# Example 1 - Hello World - -To create a trivially simple custom chart, make a file called `customSettings.R` with the following code: - -``` -# Step 1 - Write custom chart code -helloWorld <- function(data,settings){ - plot(-1:1, -1:1) - text(runif(20, -1,1),runif(20, -1,1),"Hello World") -} - -# Step 2 - Initialize Custom Settings -# Not Applicable! - -# Step 3 - Initialize the custom chart -addChart( - chart=”hello_world”, - main=”helloWorld", - label=”Hello World”, -) -``` - -Then initialize the app (Step 4) by running: - -``` -setwd('/path/to/the/file/above') -safetyGraphicsApp() -``` - -Once the app opens, click the charts tab to view the new custom "hello_world" chart. - - - -# Example 2 - Detailed Walkthrough - -Our second example goes through the chart creation process step-by-step for a more realistic example. An understanding of the underlying infrastructure for safetyGraphics will help here, so we recommend reviewing the first [introductory vignette](https://github.com/SafetyGraphics/safetyGraphics/wiki/Vignette:-Shiny-User-Guide) before diving in. - -## Step 1 - Create custom chart code - -The first, and most complicated, step is to write the code for the custom chart. It's easiest to break this process down in to 3 smaller steps. - -1. Create customSettings.R file -2. Make static code using sample data -3. Covert static chart code to Function - -### Step 1.1 - Create customSettings.R file - -First, create a file called customSettings.R and save it in a designated directory. All of the code in the following steps goes in this file. Note that when you run the app, custom medatadata files will be saved in the same directory as the customSettings.R file. - -### Step 1.2 - Make Static Code Using Sample Data - -Next, write code that creates your chart using a sample data set (the `adlbc` data set included with safetyGraphics is a good option). Note that all common charting packages are supported including `ggplot2`, `lattice` and base R graphics. Our example makes a histogram showing the distribution of lab values: - -``` -library(safetyGraphics) -library(ggplot2) -ggplot( - data = adlbc, - aes(x = PARAM, y = AVAL) -) + - geom_boxplot(fill =‘blue’) + - scale_y_log10() + - theme_bw() + - theme( - axis.text.x = element_text(angle = 25, hjust = 1), - axis.text = element_text(size = 12), - axis.title = element_text(size = 12) -) -``` - -As expected, running this code creates a simple box plot. - - - -### Step 1.3 - Convert Static Chart Code to a Function - -After the chart is working using the sample data, you need to update it to a function that will work with any data set that the user loads in the shiny app. Replace hard coded parameters with references to the settings defined in the safetyGraphics settings object as shown below. - - - -This is the hardest part of creating a custom chart, so we've provided some additional notes about this process below. There is also a technical appendix at the end of this document that provides more details about the metadata/settings objects used in this step. Finally, feel free to ask [ask us questions](https://github.com/SafetyGraphics/safetyGraphics/issues) if you run in to problems. - - - The code to create the chart must be wrapped in a function that takes 2 parameters as inputs: `data` and `settings` as shown in line 1 above. When the chart function is called by Shiny, these parameters are generated dynamically within the app; `data` represents the user selection in the Data module, and `settings` represents the selections in the Settings Module. - - The `data` parameter is saved as a `data.frame`, and a preview of the current data is conveniently available in the data tab. - - The `settings` parameter is saved as a `list` and is slightly more complex. Each setting shown on the settings page has a unique ID (called a `text_key` in the package) that gives its position in the settings `list`. In our example, the "Measure column" setting has the ID `measure_col` and is accessed in the charting function via `settings$measure_col`. Additional technical documentation about the `settings` list is provided in Appendix 1. -- Lines 2-7 above create a new data frame called `mapped_data`. This isn't required, but it simplifies the code somewhat and helps to avoid non-standard evaluation in the chart function. -- Note that we dynamically identify the `Value` and `Measure` columns in lines 4 and 5 by referencing the `settings` object. This code, as opposed to directly specifying a column name like `data$PARAM`, allows the chart to work with any data standard. -- Line 9 initializes the chart using `ggplot()` with the newly derived `mapped_data`. -- Line 13 introduces a custom setting - `settings[["boxcolor"]]` - so that the user can specify a color for the bars in the shiny app if desired. All custom settings must be initialized using the `addSetting()` function; this process is described in Step 2 below. -- Finally, note that the process for defining custom "htmlwidget" and "shiny module" charts is slightly different than the sample code above; example 3 provides basic example for a shiny module, and htmlwidgets are discussed in Appendix 2. - -## Step 2 - Add custom settings to the App - -Next, we'll add any new settings to the app by calling the `addSetting()` function in our `customSettings.R` function. - -First, we need to determine which settings are already defined. As noted above, our chart uses 3 settings: `value_col`, `measure_col` and `box_color`. In most cases you can just examine the `settingsMetadata` data frame, which contains all settings available in safetyGraphics, along with details about each. Either view it with view(settingsMetadata) or use code like this: - - - -In some complex cases, it might be easier to examine an example settings object directly (rather than the data frame representation). To do this, you can create a shell settings object and then check to see if the settings exist: - - - -As shown in the output above, our example uses 2 pre-loaded settings (`measure_col` and `value_col`) and one new setting (`boxcolor`). We add boxcolor to the metadata using the `addSetting()` function as shown below. - -``` -addSetting( - text_key="boxcolor", - label="Box Plot Color", - description="The color of the boxes", - setting_type="character", - setting_cat="appearance", - default="gray" -) -``` - -You could repeat as needed for multiple settings. For full details about each parameter see `?addSetting`, which matches up with the column names in `?settingsMetadata`. - -## Step 3 - Add the chart to the App - -Next, we need to add the chart itself to the app using `addChart()`. We'd add the example above as follows: - -``` -addChart( - chart="labdist", - main="labdist", - label="Lab Distribution - static", - requiredSettings=c("boxcolor","value_col","measure_col"), - type="static” - ) -``` - -For full details about each parameter see `?addChart`, which matches up with the column names in `?chartMetadata`. - -## Step 4 - Initialize the app - -Finally, make sure your working directory is set to the location of you customSettings.R and call safetyGraphicsApp(). The settings page for the new “Lab Distribution – Static” chart will look like this: - - - -And here is the chart: - - - -There are options that will let you save the custom code in other locations and/or automatically add a chart each time you run the app. See ?safetyGraphicsApp, ?addChart and ?addSettings for details. - -# Example 3 - Interactive Histogram - -We can expand on our static boxplot from Example 2 by adding some interactivity. Placing our boxplot in a Shiny module will allow the user to make chart-specific aesthetic adjustments on the fly. In this example, we've added the ability to add/remove individual data points, transform the y-axis scale, and show/hide outliers: - - - -This example expands on the static boxplot example in the following ways: -- Most of the underlying code for manipulating the dataset and creating the `ggplot2` figure is identical to the static boxplot example. However, we've added some conditional statements to modify the boxplot based on the user selections. -- Instead of a single chart function, we now have two: the module UI function, and the module server function. The UI function has the same name as the server function, with `_UI` appended. These functions should be specified (or sourced from an external file) within customSettings.R. -- `data` and `settings` are passed to the module server function as reactive objects. - -The full code for the custom script is saved in Appendix 3. - -# Example 4 - Custom htmlwidget (Coming soon!) - -Custom `htmlwidgets` are not currently supported via `addChart()` and addSetting()`, but we plan to add support in future release. - -For now, please contact the package development team or [file an issue on GitHub](https://github.com/SafetyGraphics/safetyGraphics/issues) if you would like to add a custom `htmlwidget` to safetyGraphics, and we can discuss technical details. - -# Appendix 1 - Technical Details - -This appendix provides a detailed technical description of the settings framework used in the application. As described in the [introductory vignette](https://github.com/SafetyGraphics/safetyGraphics/wiki/Vignette:-Shiny-User-Guide#update-settings), the settings Shiny module allows users to make a [wide](https://github.com/SafetyGraphics/safetyGraphics/wiki/Vignette:-Shiny-User-Guide#case-study-1---mapping-non-standard-data) [range](https://github.com/SafetyGraphics/safetyGraphics/wiki/Vignette:-Shiny-User-Guide#case-study-2---adding-customizations) of customizations to the charts for any given study. Understanding the underlying technical details of this settings customization process is perhaps the most complicated aspect of designing custom charts for `safetyGraphics`. This appendix is broken in to 2 sections, the first describes the structure of the settings themselves, the second describes the metadata used to generate the settings when the package is built. - -## Settings Structure - -Behind the scenes, the settings are stored as a `list`, which is updated in real time as the user makes changes in the Shiny settings module. A small chunk of a typical settings `list` is shown below. Note that this was generated using `generateSettings(standard="adam")`. More details on this and other functions related to settings is provided below. - - - -As described in the examples above, the current settings `list` is passed directly to the chart function whenever a user views a chart in the shiny app. Each control in the settings module is tied to a single component in the setting `list` using a unique key. That unique key defines the setting's position in the list. You can see the unique key for any setting by hovering over the title for the control in the shiny app. As an example, the "ID column" control has a unique key of "id_col", which is accessible in the settings `list` via `settings$id_col`, which would resolve to "USUBJID", the default value for the ADaM data standard, in our sample settings above. The settings framework also supports nested settings. A double dash "--" indicates a level of nesting in the `list`, so a setting ID of "measure_values--ALT" would be accessed as `settings[["measure_values"]][["ALT"]]`, which would resolve to "Alanine Aminotransferase (U/L)" in our sample settings. - -You can see additional details about pre-loaded settings by viewing the safetyGraphics::settingsMetadata data file that contains the default settings for the shiny app. ?settingsMetadata provides detailed data specifications for the metadata file, which also match the options available in the addSetting() function used in the examples above. - -The `safetyGraphics` package includes several functions specifically designed for use with settings objects. As mentioned above, you can generate a default settings list for a data standard using the `generateSettings()` function: - -``` -safetyGraphics::generateSettings() # no standard -safetyGraphics::generateSettings(standard="ADaM") # ADaM standard -``` - -Other functions for working with settings (all used liberally by the shiny app) include: `getRequiredSettings()`, `generateShell()`, `getSettingKeys()`, `getSettingValue()`, `getSettingsMetadata()`, `setSettingsValue()`, `trimSettings()` and `validateSettings()`. The R documentation for each of these functions provides technical details and examples for common use cases. Note also that all of the charts included with the application have detailed standalone documentation referenced in the `repo_url` and `settings_url` fields found in the `chartsMetadata` file; for example, the `hep-explorer`'s configuration page is [here](https://github.com/SafetyGraphics/hep-explorer/wiki/Configuration) and provides a lot of additional context about how each setting is used by the chart. - -Finally, note that for htmlwidgets the settings `list` is converted to a json object with the following code: - -``` -settings_list <- list(...) -jsonlite::toJSON( - settings_list, - auto_unbox = TRUE, - null = "null" - ) -``` - -## Metadata framework - -In general, there are 3 primary types of metadata used in the shiny app: chart metadata, setting metadata and data standard metadata. The metadata files that provide key information to the Shiny app and allow for the app to automatically be updated with new charts, settings, and standards. - -The underlying technical framework for the metadata is somewhat complex. In general, we follow the recommendations from the [Data chapter](http://r-pkgs.had.co.nz/data.html) in Hadley Wickham's R Packages book. Using that workflow, we combine 5 "raw" metadata files (saved in `data-raw\`) in to 3 data files that are available as part of the package (saved in `data\` with documentation in `R\`). An R script to convert the 5 "raw" files to the 3 files in the package is saved as `data-raw\csv-to-rda.R`, which is re-run whenever the metadata framework is updated. - -The `addChart()` and `addSetting()` functions (and their evil twins `removeCharts()` and `removeSettings()`) allow users to customize these metadata files without actually rebuilding the entire package. These functions simply edit, add or remove rows from the `settingsMetadata` and `chartsMetadata` files saved in `data\` and then save local copies of the files that are used in place of the default versions. This customization is likely enough for most users, but developers looking to make permanent changes to the apps default must go a level deeper and edit the files saved in `data-raw/`. More detail about those raw files is provided below, and step-by-step instructions for creating a new default chart are provided in Appendix 2. - -- **Charts Metadata (chartsMetadata.csv)**: This file informs the Shiny app about all of the chart modules that should be made available to the user. The structure of this file is 1 row per chart. Columns contain chart-specific details such as chart name, type, and size. - -- **Settings Metadata for Charts (settingsMetadataCharts.csv)**: This file helps the Shiny app understand which settings are needed for the different charts. This information is incorporated in the Settings configuration and Reporting modules. The structure of this file is 1 row per unique setting and 1 column per chart. `TRUE`/`FALSE` values are used to indicate whether the setting is relevant to a given chart. - -- **Settings Metadata (settingsMetadata.csv)**: This file informs the Shiny app about all of the possible settings across all of the charts. Specifically, the file helps to populate the Settings tab of the app, and it also ensures that settings are successfully handed off to the charts. The structure is 1 row per setting and the columns contain information such as a description of the setting, type of setting (e.g. data mapping), and whether the setting is optional or required. - -- **Settings Defaults (generateSettingsMetadataDefaults.R)**: Ths file contains information about the default values for the settings (specifically for non-data mapping settings). A `.R` file is used in place of a `.csv` to preserve the R value type (numeric, string, list, etc) of the defaults. While all settings are represented (structure of 1 row per setting), all data mapping defaults should be set to `NULL` and handled in the Standards metadata file. - -- **Standards Metadata (standardsMetadata.csv)**: This file contains information about the default values for the settings for each data standard (specifically for data mapping settings). The file helps the Shiny app automatically detect data standards in uploaded files and automate settings configuration if the data is in a standard format. The structure of the file is 1 row per setting and 1 column per data standard. While all settings are represented, all rows corresponding to non-data mapping settings should be left blank. - -# Appendix 2 - Step-by-Step Process for Contributing a New Default Chart to safetyGraphics Package - -1. Make a new branch of the safetyGraphics master [repository](https://github.com/SafetyGraphics/safetyGraphics). - -2. Create a new charting function using the guidelines in the examples above - -3. Drop the file containing the charting function in the `inst/custom` directory, under the subfolder that matches the chart type (static, plotly, or Shiny module). - -4. Update metadata - - Update metadata files: - - For all custom charts: - - Add a row for the new chart to `data-raw/chartsMetadata.csv` - - Add a column for the new chart to `data-raw/settingsMetadataCharts.csv`. - - For charts that contain new settings: - - Add rows for new settings to `data-raw/settingsMetadata.csv` - - Add defaults for new settings in `data-raw/generateSettingsMetadataDefaults.R` and re-run the file. - - Add rows for new settings in `data-raw/settingsMetadataCharts.csv`. - - Add rows for new settings in the data standard mappings in `data_raw/standardsMetaData.csv` - - Run `data-raw/csv_to_rda.R` to save the files to `data/`. - - Add chart to documentation file for settingsMetadata: `R/settingsMetadata.R`. Append `chart_` to the name of your chart function/file and add it as an item in the list. - -5. Update package dependencies. -If you've added a plotly chart: - - Add plotly to DESCRIPTION file Imports - - Add `library(plotly)` to top of `global.R` file under `inst/safetyGraphics_app` - -6. Update package documentation with `devtools::document()`. - -7. Rebuild the R package, test out the Shiny app, and make a PR to the safetyGraphics repo. - -# Appendix 3 - Full Custom Scripts for Examples - -## Full Code for Example 1 - Hello World - -``` -# Step 1 - Write custom chart code -helloWorld <- function(data,settings){ - plot(-1:1, -1:1) - text(runif(20, -1,1),runif(20, -1,1),"Hello World") -} - -# Step 2 - Initialize Custom Settings -# Not Applicable! - -# Step 3 - Initialize the custom chart -addChart( - chart=”hello_world”, - main=”helloWorld", - label=”Hello World”, -) -``` - -## Full Code for Example 2 - Static Histogram - -``` -custom_location<-"customBoxplot/" - -##################################################################### -# Step 1 - Write custom chart code -##################################################################### -labdist<-function(data,settings){ - mapped_data <- data %>% - select(Value = settings[["value_col"]], Measure = settings[["measure_col"]])%>% - filter(!is.na(Value)) - - ggplot(data = mapped_data, aes(x = Measure, y = Value)) + - geom_boxplot(fill = settings[["boxcolor"]]) + - scale_y_log10() + - theme_bw() + - theme(axis.text.x = element_text(angle = 25, hjust = 1), - axis.text = element_text(size = 12), - axis.title = element_text(size = 12)) -} - -##################################################################### -# Step 2 - Initialize Custom Settings -##################################################################### -addSetting( - text_key="boxcolor", - label="Box Plot Color", - description="The color of the boxes", - setting_type="character", - setting_cat="appearance", - default="gray", - settingsLocation=custom_location -) - - -##################################################################### -# Step 3 - Initialize the custom chart -##################################################################### -addChart( - chart="labdist", - main="labdist", - label="Lab Distribution - static", - settingsLocation = custom_location, - requiredSettings=c("boxcolor","value_col","measure_col"), - type="static" -) -``` - -## Full Code for Example 3 - Interactive Histogram - -``` -custom_location<-"customBoxplot/" - -##################################################################### -# Step 1 - Write custom chart module code -##################################################################### -labdist_module_UI <- function(id) { - ns <- NS(id) - tagList( - checkboxInput(ns("show_points"), "Show points?", value=FALSE), - checkboxInput(ns("show_outliers"), "Show outliers?", value=TRUE), - selectInput(ns("scale"), "Scale Transform", choices=c("Log-10","None")), - plotOutput(ns("labdist"), width = "1000px") - ) -} - -labdist_module <- function(input, output, session, data, settings) { - - ns <- session$ns - - mapped_data <- reactive({ - data() %>% - select(Value = settings()[["value_col"]], - Measure = settings()[["measure_col"]])%>% - filter(!is.na(Value)) - }) - - output$labdist <- renderPlot({ - - req(mapped_data()) - - # set up the plot - p <- ggplot(data = mapped_data(), aes(x = Measure, y = Value)) + - theme_bw() + - theme(axis.text.x = element_text(angle = 25, hjust = 1), - axis.text=element_text(size=12), - axis.title = element_text(size = 12)) - - # add/remove outliers - if (input$show_outliers){ - p <- p + geom_boxplot(fill = settings()[["boxcolor"]]) - } else { - p <- p + geom_boxplot(fill = settings()[["boxcolor"]], outlier.shape = NA) - } - - # log-transform scale - if (input$scale=="Log-10"){ - p <- p + scale_y_log10() - } - - # show individual data points - if (input$show_points){ - p <- p + geom_jitter(width = 0.2) - } - - p - }) -} - -##################################################################### -# Step 2 - Initialize Custom Settings -##################################################################### -addSetting( - text_key="boxcolor", - label="Box Plot Color", - description="The color of the boxes", - setting_type="character", - setting_cat="appearance", - default="gray", - settingsLocation=custom_location -) - -##################################################################### -# Step 3 - Initialize the custom chart -##################################################################### -addChart( - chart="labdist_module", - main="labdist_module", - label="Lab Distribution - shiny module", - settingsLocation = custom_location, - requiredSettings=c("boxcolor","value_col","measure_col"), - type="module" -) -``` \ No newline at end of file diff --git a/vignettes/intro.Rmd b/vignettes/intro.Rmd new file mode 100644 index 00000000..64d37a35 --- /dev/null +++ b/vignettes/intro.Rmd @@ -0,0 +1,139 @@ +--- +title: "safetyGraphics - Intro" +author: "Jeremy Wildfire" +date: "`r Sys.Date()`" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Intro} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +# Intro Vignette + +The `safetyGraphics` shiny app provides an easy-to-use shiny interface for creating shareable safety graphics for any study. This vignette provides an overview of the app's functionality, shows how to initialize the app with your own study data, and provides links to technical resources explaining how to customize the app. + +# safetyGraphics Demo + +A demo of shiny application using data from the [{safetyData} package](https://github.com/SafetyGraphics/safetyData) is hosted [here](https://jwildfire.shinyapps.io/safetyGraphics/). The app can also be initialized with the `safetyGraphicsApp()` function in the R console - see Appendix 1 for details. + +Let's take a quick look at the various pages in the app. + +## Home Tab + +A home page has a basic overview of the app. + + + +## Mapping Tab + +The Mapping tab is used to tell charts which data columns and fields to use for various chart components. + + + +This mapping process makes it easy to re-use charts across many different studies. You can see previews of the loaded data using the checkbox at the top of the page. The demo data has 3 data domains (labs, adverse events (aes) and demographics (dm)), but others can be added as well. The mapping tab is automatically filled in for common data standards, like the ADaM data shown here, but can also be filled in manually for non-standard data. + +## Filtering Tab + +The Filtering tab allows users to interactively select which participants to include in charts. + + + +This tab is created using the filter functionality included in the [{datamods} package](https://github.com/dreamRs/datamods#filter). Whenever data is filtered in this tab, those filtered data are used in all charts (across all data domains). Note that the number of participants selected is always shown in the upper right hand corner of the app. + +## Charts Tab + +Clicking the Charts tab opens a dropdown menu containing a series of charts related to clinical trial safety. Clicking the [Hepatic Safety Explorer](https://github.com/safetyGraphics/hep-explorer) opens this page: + + + +safetyGraphics supports many different kinds of charts including web-based interactive graphics using {htmlwidgets} (like the chart shown above), static plots, plotly plots and custom shiny modules. Each chart has a header that provides details about the chart, links to chart-specific resources and buttons that allow users to download a stand-alone html report or a .R file that reproduces the chart. See the [Chart Configuration Vignette](ChartConfiguration) for more detail about the safetyGraphics charting framework. + +## ⚙️ (Settings) Tab + +Finally, the Settings tab - shown as a gear icon ⚙️ - contains technical details that can be used to customize/troubleshoot the app. Clicking on the "Code" sub-tab (shown below) allows you to download a zip file that can be used to re-open the app with with any customizations that have been made during your current session. + + + +# Loading Study Data + +There are 2 primary ways to load your study data in to the safetyGraphics shiny app: + +1. Using `safetyGraphicsInit()` shiny interface +2. Passing data directly to `safetyGraphicsApp()` + +## Loading data with `safetyGraphicsInit()` + +The `safetyGraphicsInit()` function starts a simple app that allows users to select charts and then load the data required via a point-and-click interface as shown below: + + + +The app dynamically determines which data sets are required for the selected charts and updates the "Data Loader" UI when the charts selection changes. Below, we've selected 2 charts from the labs domain - so the other data domains are automatically hidden. + + + +Once you've picked charts, click the "Load" buttons in the "Data Loader" section to select data files for each domain. Data is loaded using the import functionality from the [`{datamods}` package](https://github.com/dreamRs/datamods#import) which allows you to select data loaded in your R session or load data files directly from your file system. `{datamods}` supports any file format that [{rio}](https://cran.r-project.org/web/packages/rio/index.html) can handle including text files, Excel, SAS and SPSS format. + +Once you've loaded files for all of the active data domains, the "Run App" button will become active. Click it to initialize the app. + +## Passing data to `safetyGraphicsApp()` + +You can also initialize the app with custom data directly from the R console. The basic workflow is as follows: + +1. Load your data in to the R session +2. Save your data as a named list. The name of each list item should correspond to a safetyGraphics data domain. +3. Run `safetyGraphicsApp()` using the `domainData` to pass the list of data frames. + +Here is a simple example that starts the app with SDTM data from the safetyData library: + +``` +library(safetyData) +sdtm <- list( + dm=safetyData::sdtm_dm, + aes=safetyData::sdtm_ae, + labs=safetyData::sdtm_lb +) + +safetyGraphics::safetyGraphicsApp(domainData=sdtm) +``` + +This example and other use cases are described in the `safetyGraphics Cookbook - Advanced Examples` Vignette. + +# Additional Resources + +Several additional vignettes are available for more advanced topics: +- [Chart Configuration Vignette](ChartConfiguration) - details about the charting process including technical specifications and step-by-step instructions +- [Cookbook Vignette](Cookbook) - a series of examples showing how to initialize the safetyGraphics Shiny app in different scenarios +- [Technical FAQ Vignette](TechnicalFAQ) Vignette - vignette discussing security, validation and other technical issues + +The {safetyGraphics} app is maintained by the Interactive Safety Graphics (ISG) subteam of the ASA Biopharm-DIA Safety Working Group. You can learn more about the team and find links to recent presentations and publications at our [home page](https://safetygraphics.github.io/). + +# Appendix 1 - Initialization code + +We suggest running the app in RStudio with R version 4.0 or higher. The following code installs the {safetyGraphics} package and initializes the app demo: + +``` +install.packages('safetyGraphics') +library(safetyGraphics) +safetyGraphicsApp() +``` + +Or to use the initialization workflow: + +``` +install.packages('safetyGraphics') +library(safetyGraphics) +safetyGraphicsInit() +``` + +Or you can install the most recent development version of {safetyGraphics} and the companion package {safetyCharts} directly from GitHub: + +``` +install.packages("devtools") +library(devtools) +devtools::install_github("safetyGraphics/safetyGraphics") +library(safetyGraphics) +devtools::install_github("safetyGraphics/safetyCharts") +library(safetyCharts) +safetyGraphicsApp() #or safetyGraphicsInit() +``` diff --git a/vignettes/shinyUserGuide.Rmd b/vignettes/shinyUserGuide.Rmd deleted file mode 100644 index 8efc3030..00000000 --- a/vignettes/shinyUserGuide.Rmd +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: "safetyGraphics Shiny App - User Guide" -author: "Jeremy Wildfire" -date: "`r Sys.Date()`" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{safetyGraphics Shiny App - User Guide} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r setup, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -``` - -# Overview - -The `safetyGraphics` Shiny app provides an easy-to-use point-and-click interface to create shareable safety graphics for any study. - -# Starting the Shiny App - -After opening RStudio and making sure you are running R version 3.5 or higher, the application can be started with just a few lines of code. In general, you'll want to load the latest stable release from CRAN: - -``` -install.packages("safetyGraphics") -library("safetyGraphics") -safetyGraphicsApp() -``` - -To load the latest development release from GitHub with `devtools`: - -``` -install.packages("devtools") -library("devtools") -devtools::install_github("SafetyGraphics/safetyGraphics") -library("safetyGraphics") -safetyGraphicsApp() -``` - -## Loading Large Files - -By default, Shiny only allows users to load files smaller than 5mb. If you want to load a larger file, use the maxFileSize setting when calling the app: - -``` -safetyGraphicsApp(maxFileSize = 100) -``` - -# Typical Workflow - -After opening the app, you will typically follow the workflow below. In short, you will load data (once), tweak settings and view charts (maybe more than once), and then export a snapshot of the charts for other users. - - - -This workflow lines up with the items in the toolbar for the App. - - - -More information about each step in the process is shown below. - -## Load Data - -When you open the app, you are taken to the Home Tab which contains some general information about the app and links to helpful documentation. Click on the Data Tab and you should see the "Data Upload" and "Data Preview" panels. The preview for the pre-loaded "Example data" dataset is shown by default. - - - -To load your own data, simply click the browse button and select a `.csv` or `.sas7bdat` data set. Once the file is loaded, select it in the list at the bottom of the "Data Upload Panel". Once selected, the "Data Preview" panel will update automatically (along with the Settings, Charts, and Reports tabs). - -The charts in the safetyGraphics app are specifically designed for clinical trial safety monitoring, and require laboratory datasets that contain one row per participant per time point per measure. Data mappings for two common [CDISC](https://www.cdisc.org/) data standards - [SDTM](https://www.cdisc.org/standards/foundational/sdtm) and [ADaM](https://www.cdisc.org/standards/foundational/adam) - are pre-loaded in the application. As described below, the app can automatically generate charts for data sets using these standards; other data sets require some user configuration. - -## Update Settings - -After loading your data, navigate to the Settings tab to customize the behavior of the charts. This tab includes a Charts panel for selecting the charts you want to visualize and other panels for different types of chart settings. For example, the "Data Mappings" panel (shown below for the "Example Data" ADaM data set) can be used to specify the column that contains the unique subject ID, and on the more general "Appearance Settings" panel, there is an option to specify a warning message to be displayed when the chart loads. You can hover the mouse over any setting label to get more details. The small numbers to the right of the settings labels indicate the number of charts that use the relevant setting. Mousing over them presents a list of these charts. - - - -When possible, items on the settings tab are pre-populated based on the data standard of the selected data set. If a SAS data set with labels is provided, the relevant column labels will appear within brackets [] next to their variable names. You can see this in the Data Mappings screenshot above. See the Case Studies below for more details regarding working with non-standard data and adding customizations to the charts. - -## View Chart - -Once the settings configuration is complete, click on the Charts tab to view a drop-down of the available charts. A green check will display by charts that are ready to be visualized and a red X will indicate that settings need to be changed in order to render the chart. Simply click one of the options to view it. The chart tab updates automatically when settings are changed or new data is loaded. -More details about chart functionality will be documented in separate vignettes. - - - -## Export Results - -Navigate to the Reports tab to choose reports for export and click the "Export Chart(s)" button at the bottom to create a standalone copy of the charts using the current configuration. The export functionality combines the data, code, and settings for the charts in to a single file. In addition to the charts themselves, the export includes a summary of the tool, and code to recreate the customized charts in R. - - - -# Case Study #1 - Mapping Non-Standard data - -## Overview - -When a new data file is loaded, the app will detect whether the dataset is formatted according to ADaM or SDTM data standards. If the uploaded dataset matches one of these standards, the settings tab will be pre-populated accordingly, and little or no custom user customization will be needed to generate a basic chart. However, no data standard is strictly required; the app also works with data in other formats. The specific data columns required varies between charts. For example, the only firm data requirements for the Hepatic Explorer chart are: - -- The data must have one record per participant per timepoint per lab test. That is, the data should be long, not wide. -- The data must have columns for: - - Unique Subject Identifier (ID Column) - - Name of Measure or Test (Measure Column) - - Numeric finding or result (Value Column) - - Numeric upper limit of normal for the test - - Numeric lower limit of normal for the test - - Numeric study day -- The following values must be present in the column corresponding to Measure or Test: - - Aminotransferase, alanine (ALT) - - Aminotransferase, aspartate (AST) - - Alkaline phosphatase (ALP) - - Total Bilirubin - -The app also supports data sets that partially match the pre-loaded data standards. The step-by-step instructions below outline how to create a chart for one such data set. - -## Step-by-step - -### 1. Open the App - -Paste the following code into RStudio: - -``` -#Code to initialize shiny application -install.packages("safetyGraphics") -library("safetyGraphics") -safetyGraphicsApp() -``` - -### 2. Load Data - -Use the "Browse.." button on the data upload section of the data tab to load a non-standard data set. We'll use the `.csv` saved [here](https://github.com/SafetyGraphics/safetyGraphics/tree/master/inst/safetyGraphics_app/tests/partialSDTM.csv), but the process is similar for other data sets. Notice that once the data is loaded, the app will detect whether the data matches one of those pre-loaded standards, and a note is added to indicate whether a match is found. Our sample data is a partial match for the SDTM standard. Once you select the newly loaded data set, the app should look like the screen capture below. Click on the Charts tab and note the red X's in the drop-down indicating that user customization is needed. - - - -### 3. Select Columns - -Next, click the "Settings" tab in the nav bar at the top of the page. The page should look something like this: - - - -Behind the scenes, a validation process is run to check if the selected settings match up with the selected data set to create a valid chart. Green (for valid) and red (for invalid) status messages are shown after each label in the Settings tab - you can hover the mouse over the status to get more details. - -As you can see, we've got several invalid settings with red status messages. We now need to go through and update each invalid setting and turn its status icon into a green check. Once all of the individual settings are valid, the red Xs in the Charts drop-down will turn to green checks, and the chart will be created. Let's hover over the red X by the Measure Column Setting to see the detailed description of the failed check: - - - -As you might've guessed from the empty select box, the check failed because no value is specified for the setting. Choosing the measure column is simple. Click the select box to see pre-populated options corresponding to the columns in the data. - - - -Now select ID for the ID column, LBTEST for the Measure Column, and LBDY for the Study Day Column option. Your setting page should look something like this: - - - -Now we need to fill in the 4 inputs beneath Measure Column. You may have noticed that there were no options available for these inputs when the page loaded. This is because these options are field level data that depend on the Measure Column option. Once you selected a Measure Column, the options for these inputs were populated using the unique values found in that data column. To fill them in, just type the first few letters of the lab measure in the text box. For example, type "Alan" for the Alanine Aminotransferase value input and select the correct option. - - - -Repeat the process for the other 3 "value" inputs and viola, the red X changes to a green check, and the Hepatic Explorer chart is ready. - - - -### 4. View Chart - -Now that we've got the data mapping complete, just select "Hepatic Explorer" from the Chart tab drop-down. - - - -The chart has lots of useful interactive features built in, but we'll cover those in a separate vignette. - -### 5. Export Chart - -To export the chart, click the Reports Tab, make sure that the Hepatic Explorer has a check by it, and click the "Export Chart(s)" button. Your chart, along with the other valid charts, will be saved in an `.html` file and downloaded to your machine. - -Open the downloaded file in a new tab in your browser and you'll see tabs for each of the charts and an "Info" tab. The Hepatic Explorer tab will be identical to the chart shown above, with all of your customizations intact. The "Info" tab, shown below, has a brief description of the safetyGraphics package and source code that you can use to recreate the charts in R. - - - -The html file contains all of the data and code for the charts and is easy to share. Just send the file to the person you're sharing with, and tell them to open it in their web browser (just double-click the file) - they don't even need R. - -## Summary - -This case study shows how to create a shareable chart created using custom settings in just a few clicks. Continue reading to find out how to add customizations to your chart. - -# Case Study #2 - Adding Customizations - -## Overview - -Only the most basic settings used by the `safetyGraphics` displays are populated by default, but users can also add a wide variety of additional customization. We'll walk through a few common customizations for the Hepatic Explorer chart in this case study including: - -- Adding grouping variables -- Adding filter variables -- Defining which rows should be included in the analyses using the Analysis Flag options -- Defining the baseline measurement using the Baseline options - -## Step-by-Step - -### 1. Open the App - -Just paste this code in to RStudio: - -``` -#Code to initialize shiny application -install.packages("safetyGraphics") -library("safetyGraphics") -safetyGraphicsApp() -``` - -We'll use the pre-loaded example data for this case study, so there is no need to load your own data file. - -### 2. Add Filters and Groups - -The `SafetyGraphics` Hepatic Explorer chart offers native support for data-driven groups and filtering. Any data column can be used to add filter and grouping controls to the chart. One common use case is to add grouping by treatment arm and filtering by site, race and sex. All of this can be done with just a few clicks. As you might have guessed, you just update the "Filter columns" and "Group columns" inputs as shown: - - - -Select "Hepatic Explorer" from the Charts drop-down tab to see the following chart (with orange boxes added around the newly created filters and groups for emphasis): - - - -A word of warning - both grouping and filtering work best using categorical variables with a relatively small number of groups (less than 10 or so). With that said, there is no official limit on the number of unique values to include in a group or filter, so if you followed the example above but chose "AGE" (with over a dozen unique integer values) instead of "AGEGR1" (with 3 categorical levels), you might not love the functionality in the chart. Fortunately, it's easy to go back and update the chart to use the categorized variable instead - just go back to the settings tab and update the corresponding setting. - -### 3. Flag Rows of Special Interest - -You can also use the settings page to identify important values in the data. For the Hepatic Explorer chart, you can flag baseline values (using the "Baseline column" and "Baseline values" inputs) and values included in the analysis population (using "Analysis Flag column" and "Analysis Flag values" inputs). In both cases, you need to choose the "column" first, and then choose 1 or more corresponding "values". Here are some suggested settings using our sample data: - - - -In the Hepatic Explorer chart, adding a baseline flag enables the users to view a baseline-adjusted version of the chart. Click the chart tab, and then change the "Display Type" control to "Baseline Adjusted (mDish)". - - - -We're following ADaM conventions and using "flag" columns ending in "FL" and "Y" values for the configuration here, but any column/value combination is allowed. For example, you could use study day 0 to define baseline by setting baseline column to "ADY" and baseline value to "0". - -### Summary - -This case study shows how to add some basic customizations to your Hepatic Explorer chart with a few clicks in the shiny application. Note that not all customizations are available in the shiny app. You can access more granular settings by looking at the documentation for the underlying [hep-explorer github repo](https://github.com/SafetyGraphics/hep-explorer) javascript library. From 8f130bef81cce7e7d48a60275b3af231ea3ed45a Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Wed, 1 Sep 2021 10:54:05 -0400 Subject: [PATCH 4/8] re-run pkgdown --- R/meta.R | 2 - R/mod_chartsNav.R | 2 +- R/mod_chartsTab.R | 10 +- R/mod_filterTab.R | 6 +- R/mod_filterTabChecks.R | 3 +- R/mod_homeTab.R | 6 +- R/mod_loadCharts.R | 13 +- R/mod_loadData.R | 6 +- R/mod_mappingColumn.R | 6 +- R/mod_mappingDomain.R | 6 +- R/mod_mappingSelect.R | 7 +- R/mod_mappingTab.R | 6 +- R/mod_safetyGraphicsServer.R | 2 +- R/mod_safetyGraphicsUI.R | 3 +- R/mod_settingsCharts.R | 6 +- R/mod_settingsCode.R | 8 +- R/mod_settingsData.R | 6 +- R/mod_settingsMapping.R | 8 +- R/mod_settingsTab.R | 2 +- R/safetyGraphicsApp.R | 2 +- R/safetyGraphicsInit.R | 2 +- README.md | 2 +- _pkgdown.yml | 87 +++- docs/404.html | 61 ++- docs/LICENSE-text.html | 65 ++- docs/LICENSE.html | 175 ++++++++ docs/articles/chartConfiguration.html | 411 ++++++++++++++++++ .../header-attrs-2.10/header-attrs.js | 12 + docs/articles/index.html | 65 +-- docs/articles/intro.html | 245 +++++++++++ .../header-attrs-2.10/header-attrs.js | 12 + docs/authors.html | 63 +-- docs/bootstrap-toc.css | 60 +++ docs/bootstrap-toc.js | 159 +++++++ docs/index.html | 120 ++--- docs/news/index.html | 88 ++-- docs/pkgdown.css | 125 +++++- docs/pkgdown.js | 5 - docs/pkgdown.yml | 9 +- docs/reference/Rplot001.png | Bin 0 -> 1011 bytes docs/reference/SafetyGraphics.html | 76 ++-- docs/reference/app_startup.html | 225 ++++++++++ docs/reference/chartsNav.html | 187 ++++++++ docs/reference/chartsTab.html | 203 +++++++++ docs/reference/chartsTabUI.html | 187 ++++++++ docs/reference/detectStandard.html | 314 ++++++++++--- docs/reference/evaluateStandard.html | 205 +++++---- docs/reference/filterTab.html | 223 ++++++++++ docs/reference/filterTabChecks.html | 194 +++++++++ docs/reference/filterTabUI.html | 183 ++++++++ docs/reference/generateMappingList.html | 191 ++++++++ docs/reference/hasColumn.html | 84 ++-- docs/reference/hasField.html | 95 ++-- docs/reference/homeTab.html | 191 ++++++++ docs/reference/homeTabUI.html | 183 ++++++++ docs/reference/index.html | 337 +++++++++++--- docs/reference/loadCharts.html | 195 +++++++++ docs/reference/loadChartsUI.html | 187 ++++++++ docs/reference/loadData.html | 195 +++++++++ docs/reference/loadDataUI.html | 187 ++++++++ docs/reference/makeChartConfig.html | 217 +++++++++ docs/reference/makeChartExport.html | 190 ++++++++ docs/reference/makeChartParams.html | 191 ++++++++ docs/reference/makeChartSummary.html | 191 ++++++++ docs/reference/makeMapping.html | 202 +++++++++ docs/reference/mappingColumn.html | 202 +++++++++ docs/reference/mappingColumnUI.html | 195 +++++++++ docs/reference/mappingDomain.html | 202 +++++++++ docs/reference/mappingDomainUI.html | 195 +++++++++ docs/reference/mappingSelect.html | 194 +++++++++ docs/reference/mappingSelectUI.html | 198 +++++++++ docs/reference/mappingTab.html | 202 +++++++++ docs/reference/mappingTabUI.html | 199 +++++++++ docs/reference/meta.html | 194 +++++++++ docs/reference/prepareChart.html | 186 ++++++++ docs/reference/safetyGraphicsApp.html | 120 ++--- docs/reference/safetyGraphicsInit.html | 195 +++++++++ docs/reference/safetyGraphicsServer.html | 220 ++++++++++ docs/reference/safetyGraphicsUI.html | 199 +++++++++ docs/reference/setMappingListValue.html | 208 +++++++++ docs/reference/settingsCharts.html | 195 +++++++++ docs/reference/settingsChartsUI.html | 183 ++++++++ docs/reference/settingsCode.html | 203 +++++++++ docs/reference/settingsCodeUI.html | 183 ++++++++ docs/reference/settingsData.html | 195 +++++++++ docs/reference/settingsDataUI.html | 183 ++++++++ docs/reference/settingsMapping.html | 199 +++++++++ docs/reference/settingsMappingUI.html | 183 ++++++++ docs/reference/settingsTab.html | 207 +++++++++ docs/reference/settingsTabUI.html | 183 ++++++++ docs/reference/textKeysToList.html | 86 ++-- docs/sitemap.xml | 118 +++-- man/chartsNav.Rd | 4 +- man/chartsTab.Rd | 6 +- man/chartsTabUI.Rd | 6 +- man/filterTab.Rd | 4 +- man/filterTabChecks.Rd | 4 +- man/filterTabUI.Rd | 4 +- man/homeTab.Rd | 4 +- man/homeTabUI.Rd | 4 +- man/loadCharts.Rd | 6 +- man/loadChartsUI.Rd | 6 +- man/loadData.Rd | 4 +- man/loadDataUI.Rd | 4 +- man/mappingColumn.Rd | 4 +- man/mappingColumnUI.Rd | 4 +- man/mappingDomain.Rd | 4 +- man/mappingDomainUI.Rd | 2 +- man/mappingSelect.Rd | 4 +- man/mappingSelectUI.Rd | 2 +- man/mappingTab.Rd | 4 +- man/mappingTabUI.Rd | 4 +- man/safetyGraphicsApp.Rd | 4 +- man/safetyGraphicsInit.Rd | 4 +- man/safetyGraphicsServer.Rd | 2 +- man/safetyGraphicsUI.Rd | 4 +- man/settingsCharts.Rd | 4 +- man/settingsChartsUI.Rd | 4 +- man/settingsCode.Rd | 4 +- man/settingsCodeUI.Rd | 4 +- man/settingsData.Rd | 4 +- man/settingsDataUI.Rd | 4 +- man/settingsMapping.Rd | 4 +- man/settingsMappingUI.Rd | 4 +- man/settingsTabUI.Rd | 4 +- vignettes/intro.Rmd | 4 +- 126 files changed, 11046 insertions(+), 828 deletions(-) create mode 100644 docs/LICENSE.html create mode 100644 docs/articles/chartConfiguration.html create mode 100644 docs/articles/chartConfiguration_files/header-attrs-2.10/header-attrs.js create mode 100644 docs/articles/intro.html create mode 100644 docs/articles/intro_files/header-attrs-2.10/header-attrs.js create mode 100644 docs/bootstrap-toc.css create mode 100644 docs/bootstrap-toc.js create mode 100644 docs/reference/Rplot001.png create mode 100644 docs/reference/app_startup.html create mode 100644 docs/reference/chartsNav.html create mode 100644 docs/reference/chartsTab.html create mode 100644 docs/reference/chartsTabUI.html create mode 100644 docs/reference/filterTab.html create mode 100644 docs/reference/filterTabChecks.html create mode 100644 docs/reference/filterTabUI.html create mode 100644 docs/reference/generateMappingList.html create mode 100644 docs/reference/homeTab.html create mode 100644 docs/reference/homeTabUI.html create mode 100644 docs/reference/loadCharts.html create mode 100644 docs/reference/loadChartsUI.html create mode 100644 docs/reference/loadData.html create mode 100644 docs/reference/loadDataUI.html create mode 100644 docs/reference/makeChartConfig.html create mode 100644 docs/reference/makeChartExport.html create mode 100644 docs/reference/makeChartParams.html create mode 100644 docs/reference/makeChartSummary.html create mode 100644 docs/reference/makeMapping.html create mode 100644 docs/reference/mappingColumn.html create mode 100644 docs/reference/mappingColumnUI.html create mode 100644 docs/reference/mappingDomain.html create mode 100644 docs/reference/mappingDomainUI.html create mode 100644 docs/reference/mappingSelect.html create mode 100644 docs/reference/mappingSelectUI.html create mode 100644 docs/reference/mappingTab.html create mode 100644 docs/reference/mappingTabUI.html create mode 100644 docs/reference/meta.html create mode 100644 docs/reference/prepareChart.html create mode 100644 docs/reference/safetyGraphicsInit.html create mode 100644 docs/reference/safetyGraphicsServer.html create mode 100644 docs/reference/safetyGraphicsUI.html create mode 100644 docs/reference/setMappingListValue.html create mode 100644 docs/reference/settingsCharts.html create mode 100644 docs/reference/settingsChartsUI.html create mode 100644 docs/reference/settingsCode.html create mode 100644 docs/reference/settingsCodeUI.html create mode 100644 docs/reference/settingsData.html create mode 100644 docs/reference/settingsDataUI.html create mode 100644 docs/reference/settingsMapping.html create mode 100644 docs/reference/settingsMappingUI.html create mode 100644 docs/reference/settingsTab.html create mode 100644 docs/reference/settingsTabUI.html diff --git a/R/meta.R b/R/meta.R index 503e52a4..8df6856a 100644 --- a/R/meta.R +++ b/R/meta.R @@ -1,5 +1,3 @@ -#' meta -#' #' Metadata data frame containing information about the data mapping used to configure safetyGraphics charts. One record per unique data mapping #' #' @format A data frame with 31 rows and 7 columns diff --git a/R/mod_chartsNav.R b/R/mod_chartsNav.R index 6a5762bb..6904a81e 100644 --- a/R/mod_chartsNav.R +++ b/R/mod_chartsNav.R @@ -1,4 +1,4 @@ -#' Add a navbar tab that initializes the Chart Module UI +#' Adds a navbar tab that initializes the Chart Module UI #' #' @param chart chart metadata #' @param ns namespace diff --git a/R/mod_chartsTab.R b/R/mod_chartsTab.R index 8883b315..7b274b5f 100644 --- a/R/mod_chartsTab.R +++ b/R/mod_chartsTab.R @@ -1,8 +1,7 @@ -#' @title Charts Tab -#' @description Charting module +#' @title UI for chart module, designed to be re-used for each chart generated. #' #' @param id module id -#' @param chart list containing chart specifications +#' @param chart list containing chart specifications like those returned by \link{makeChartConfig}. #' #' @importFrom stringr str_to_title #' @importFrom purrr map2 @@ -17,13 +16,12 @@ chartsTabUI <- function(id, chart){ return(list(header, chartWrap)) } -#' @title home tab - server -#' @description server for the display of the chart tab +#' @title Server for chart module, designed to be re-used for each chart generated. #' #' @param input Input objects from module namespace #' @param output Output objects from module namespace #' @param session An environment that can be used to access information and functionality relating to the session -#' @param chart list containing a safetyGraphics chart object. see custom chart vignette for details. +#' @param chart list containing a safetyGraphics chart object like those returned by \link{makeChartConfig}. #' @param data named list of current data sets (Reactive). #' @param mapping tibble capturing the current data mappings (Reactive). #' diff --git a/R/mod_filterTab.R b/R/mod_filterTab.R index dfd8cf43..aa31ad70 100644 --- a/R/mod_filterTab.R +++ b/R/mod_filterTab.R @@ -1,5 +1,4 @@ -#' @title filterTabUI -#' @description UI that facilitates the filtering data with datamods::filter_data_ui +#' @title UI for the filter module in datamods::filter_data_ui #' #' @param id module id #' @@ -39,8 +38,7 @@ filterTabUI <- function(id){ } -#' @title filter module server -#' @description server function that facilitates the data filtering with the datamods::filter_data_server module +#' @title Server for the filter module in datamods::filter_data_ui #' #' @param input Shiny input object #' @param output Shiny output object diff --git a/R/mod_filterTabChecks.R b/R/mod_filterTabChecks.R index 9da0dea3..5d93abbc 100644 --- a/R/mod_filterTabChecks.R +++ b/R/mod_filterTabChecks.R @@ -1,5 +1,4 @@ -#' @title filter module checks -#' @description function that checks whether the current data and settings are appropriate for the filter tab +#' @title Checks for whether the current data and settings support a filter tab #' #' @param domainData list of data files for each domain #' @param filterDomain domain to use for filtering (typically "dm") diff --git a/R/mod_homeTab.R b/R/mod_homeTab.R index edcdb9fa..cea29776 100644 --- a/R/mod_homeTab.R +++ b/R/mod_homeTab.R @@ -1,5 +1,4 @@ -#' @title Home Tab -#' @description Home Tab - sub-module showing details for the data loaded in the app - UI +#' @title UI for the home module #' #' @param id module id #' @@ -13,8 +12,7 @@ homeTabUI <- function(id){ ) } -#' @title home tab - server -#' @description server for the display of the home tab +#' @title Server for the filter module in datamods::filter_data_ui #' #' @param input mod input #' @param output mod output diff --git a/R/mod_loadCharts.R b/R/mod_loadCharts.R index 7de657c5..858095a0 100644 --- a/R/mod_loadCharts.R +++ b/R/mod_loadCharts.R @@ -1,8 +1,7 @@ -#' @title loadChartsUI -#' @description UI that helps users pick charts +#' @title UI for the chart loading module used in safetyGraphicsInit() #' #' @param id module id -#' @param charts list of charts +#' @param charts list containing chart specifications like those returned by \link{makeChartConfig}. #' #' @importFrom purrr keep #' @importFrom sortable bucket_list add_rank_list @@ -21,15 +20,15 @@ loadChartsUI <- function(id, charts=makeChartConfig()){ ) } -#' @title loadCharts -#' @description server that facilitates selection of charts for safetyGraphicsApp +#' @title Server for the chart loading module used in safetyGraphicsInit() #' #' @param input Shiny input object #' @param output Shiny output object #' @param session Shiny session object -#' @param charts Initial list of charts - +#' @param charts list containing chart specifications like those returned by \link{makeChartConfig}. +#' #' @export + loadCharts <- function(input, output, session, charts=makeChartConfig()) { ns<-session$ns labels<-charts%>%map(~makeChartSummary(.x,showLinks=FALSE,class="chart-sortable")) diff --git a/R/mod_loadData.R b/R/mod_loadData.R index 8f76429e..9673952e 100644 --- a/R/mod_loadData.R +++ b/R/mod_loadData.R @@ -1,5 +1,4 @@ -#' @title loadDataUI -#' @description UI that facilitates the mapping of a column data domain +#' @title UI for the data loading module used in safetyGraphicsInit() #' #' @param id module id #' @param domain character vector with domains to be loaded @@ -19,8 +18,7 @@ loadDataUI <- function(id, domain=NULL){ ) } -#' @title loadDataServer -#' @description UI that facilitates the mapping of a column data domain +#' @title Server for the data loading module used in safetyGraphicsInit() #' #' @param domain data domain to be loaded #' @param input Shiny input object diff --git a/R/mod_mappingColumn.R b/R/mod_mappingColumn.R index a991d446..a08d2f29 100644 --- a/R/mod_mappingColumn.R +++ b/R/mod_mappingColumn.R @@ -1,5 +1,4 @@ -#' @title mappingColumnUI -#' @description UI that facilitates the mapping of a column data domain +#' @title UI that facilitates the mapping of a column data (and any associated fields) #' #' @param id module id #' @param meta metadata for the column (and related fields) @@ -66,8 +65,7 @@ mappingColumnUI <- function(id, meta, data, mapping=NULL){ col_ui } -#' @title mappingColumn -#' @description server function that facilitates the mapping of a single data element (column of field) with a simple select UI +#' @title Server that facilitates the mapping of a column data (and any associated fields) #' #' @param input Shiny input object #' @param output Shiny output object diff --git a/R/mod_mappingDomain.R b/R/mod_mappingDomain.R index be814e27..38871694 100644 --- a/R/mod_mappingDomain.R +++ b/R/mod_mappingDomain.R @@ -1,5 +1,4 @@ -#' @title mappingDomainUI -#' @description UI that facilitates the mapping of a full data domain +#' @title UI that facilitates the mapping of a full data domain #' #' @param id module id #' @param meta metadata for the domain @@ -37,8 +36,7 @@ mappingDomainUI <- function(id, meta, data, mapping=NULL){ } -#' @title mappingDomain -#' @description server function that facilitates the mapping of a single data domain +#' @title Server that facilitates the mapping of a full data domain #' #' @param input Shiny input object #' @param output Shiny output object diff --git a/R/mod_mappingSelect.R b/R/mod_mappingSelect.R index 43c3d7ba..38eb1ef4 100644 --- a/R/mod_mappingSelect.R +++ b/R/mod_mappingSelect.R @@ -1,7 +1,5 @@ -#' Mapping Select UI +#' @title UI that facilitates the mapping of a single data element (column or field) with a simple select UI #' -#' UI that facilitates the mapping of a single data element (column or field) with a simple select UI -#' #' @param id unique id for the UI #' @param label label associated with the control #' @param choices a list of options for the control @@ -33,8 +31,7 @@ mappingSelectUI <- function(id, label, choices=NULL, default=NULL){ ) } -#' @title mappingSelect -#' @description server function that facilitates the mapping of a single data element (column of field) with a simple select UI +#' @title Server that facilitates the mapping of a single data element (column or field) with a simple select UI #' #' @param input Shiny input object #' @param output Shiny output object diff --git a/R/mod_mappingTab.R b/R/mod_mappingTab.R index 21e7bc35..d41bdf52 100644 --- a/R/mod_mappingTab.R +++ b/R/mod_mappingTab.R @@ -1,5 +1,4 @@ -#' @title mappingTabUI -#' @description UI that facilitates the mapping of all data domain +#' @title UI for mapping tab covering of all data domains #' #' @param id module id #' @param meta metadata for all domains @@ -68,8 +67,7 @@ mappingTabUI <- function(id, meta, domainData, mappings=NULL, standards=NULL){ } -#' @title mapping module server -#' @description server function that facilitates the mapping of a single data domain +#' @title Server for mapping tab covering of all data domains #' #' @param input Shiny input object #' @param output Shiny output object diff --git a/R/mod_safetyGraphicsServer.R b/R/mod_safetyGraphicsServer.R index cfa78086..89126bde 100644 --- a/R/mod_safetyGraphicsServer.R +++ b/R/mod_safetyGraphicsServer.R @@ -1,4 +1,4 @@ -#' Server for the default safetyGraphics shiny app +#' Server for core safetyGraphics app including Home, Mapping, Filter, Charts and Settings modules. #' #' This function returns a server function suitable for use in shiny::runApp() #' diff --git a/R/mod_safetyGraphicsUI.R b/R/mod_safetyGraphicsUI.R index 62be772a..db044db5 100644 --- a/R/mod_safetyGraphicsUI.R +++ b/R/mod_safetyGraphicsUI.R @@ -1,4 +1,5 @@ -#' UI for the default safetyGraphics shiny app +#' UI for the core safetyGraphics app including Home, Mapping, Filter, Charts and Settings modules. +#' #' #' @param id module ID #' @param meta data frame containing the metadata for use in the app. See the preloaded file (\code{?safetyGraphics::meta}) for more data specifications and details. Defaults to \code{safetyGraphics::meta}. diff --git a/R/mod_settingsCharts.R b/R/mod_settingsCharts.R index 25ad6e32..2d69976d 100644 --- a/R/mod_settingsCharts.R +++ b/R/mod_settingsCharts.R @@ -1,5 +1,4 @@ -#' @title Settings Module - chart details -#' @description Settings Module - sub-module showing details for the charts loaded in the app - UI +#' @title UI for settings tab showing details for the charts loaded in the app #' #' @param id module id #' @@ -23,8 +22,7 @@ settingsChartsUI <- function(id){ ) } -#' @title Settings Module - charts details - server -#' @description server for the display of the charts +#' @title Server for settings tab showing details for the charts loaded in the app #' #' @param input Shiny input object #' @param output Shiny output object diff --git a/R/mod_settingsCode.R b/R/mod_settingsCode.R index a55c14a4..a778bfc0 100644 --- a/R/mod_settingsCode.R +++ b/R/mod_settingsCode.R @@ -1,5 +1,5 @@ -#' UI for the settings page -#' +#' @title UI for settings tab providing code to re-start the app with current data/settings +#' #' @param id module ID #' #' @export @@ -92,8 +92,8 @@ settingsCodeUI <- function(id){ } -#' @title Server for the setting code page -#' +#' @title Server for settings tab providing code to re-start the app with current data/settings +#' #' @param input Shiny input object #' @param output Shiny output object #' @param session Shiny session object diff --git a/R/mod_settingsData.R b/R/mod_settingsData.R index 45e85175..8d15aae3 100644 --- a/R/mod_settingsData.R +++ b/R/mod_settingsData.R @@ -1,5 +1,4 @@ -#' @title Settings Module - data details -#' @description Settings Module - sub-module showing details for the data loaded in the app - UI +#' @title UI for settings tab showing current data #' #' @param id module id #' @@ -20,8 +19,7 @@ settingsDataUI <- function(id){ ) } -#' @title Settings Module - data details - server -#' @description server for the display of the loaded data +#' @title Server for settings tab showing current data #' #' @param input Shiny input object #' @param output Shiny output object diff --git a/R/mod_settingsMapping.R b/R/mod_settingsMapping.R index d114fe30..9b1b353e 100644 --- a/R/mod_settingsMapping.R +++ b/R/mod_settingsMapping.R @@ -1,6 +1,5 @@ -#' @title Settings view of Metadata/Mapping - UI -#' @description UI that displays the data mapping metadata. -#' +#' @title UI for settings tab showing current mapping +#' #' @param id module id #' #' @import rclipboard @@ -19,8 +18,7 @@ settingsMappingUI <- function(id){ ) } -#' @title Settings view of Metadata/Mapping - server -#' @description server for the display of the data mapping metadata. +#' @title Server for settings tab showing current mapping #' #' @param input Shiny input object #' @param output Shiny output object diff --git a/R/mod_settingsTab.R b/R/mod_settingsTab.R index b16ecf0a..bfb72ffe 100644 --- a/R/mod_settingsTab.R +++ b/R/mod_settingsTab.R @@ -1,4 +1,4 @@ -#' UI for the settings page +#' @title UI for the settings tab #' #' @param id module ID #' diff --git a/R/safetyGraphicsApp.R b/R/safetyGraphicsApp.R index 8902c97a..1b90206c 100644 --- a/R/safetyGraphicsApp.R +++ b/R/safetyGraphicsApp.R @@ -1,4 +1,4 @@ -#' Run the interactive safety graphics app +#' Run the core safetyGraphics App #' #' @param domainData named list of data.frames to be loaded in to the app. Sample AdAM data from the safetyData package used by default #' @param meta data frame containing the metadata for use in the app. See the preloaded file (\code{?safetyGraphics::meta}) for more data specifications and details. Defaults to \code{safetyGraphics::meta}. diff --git a/R/safetyGraphicsInit.R b/R/safetyGraphicsInit.R index 81bde317..7c136424 100644 --- a/R/safetyGraphicsInit.R +++ b/R/safetyGraphicsInit.R @@ -1,4 +1,4 @@ -#' Run the interactive safety graphics app +#' App to select charts, load data and then initialize the core safetyGraphics app #' #' @param charts chart object #' @param delayTime time (in ms) between drawing app UI and starting server. Default set to 1000 (1 second), but could need to be higher on slow machine. diff --git a/README.md b/README.md index bcb77b4b..923fa06e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![R build status](https://github.com/ASA-DIA-InteractiveSafetyGraphics/safetyGraphics/workflows/R-CMD-check/badge.svg)](https://github.com/ASA-DIA-InteractiveSafetyGraphics/safetyGraphics/actions) -# safetyGraphics: Clinical Trial Safety Monitoring with R +# safetyGraphics: Clinical Trial Monitoring with R The {safetyGraphics} package provides a framework for evaluating of clinical trial safety in R using a flexible data pipeline. The package includes a shiny application that allows users to explore safety data using a series of interactive graphics, including the hepatic safety explorer shown below. The package has been developed as part of the Interactive Safety Graphics (ISG) workstream of the ASA Biopharm-DIA Safety Working Group. diff --git a/_pkgdown.yml b/_pkgdown.yml index fce6b351..7539e8eb 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -5,6 +5,24 @@ template: bootswatch: cerulean navbar: + title: safetyGraphics + left: + - icon: fa-home fa-lg + href: index.html + - text: Vignettes + menu: + - text: Intro to Shiny App + href: articles/intro.html + - text: Chart Configuration + href: articles/chartConfiguration.html + - text: Examples Cookbook + href: articles/cookbook.html + - text: Technical FAQ + href: articles/technicalFAQ.html + - text: Functions + href: reference/index.html + - text: News + href: news/index.html right: - icon: fa-github href: https://github.com/SafetyGraphics/safetyGraphics @@ -12,27 +30,60 @@ navbar: development: mode: release - reference: - - title: Main Functions + - title: Main Shiny App Functions contents: - safetyGraphicsApp + - safetyGraphicsInit + - title: Shiny Modules + desc: Reusable Shiny Modules + contents: + - safetyGraphicsServer + - safetyGraphicsUI + - chartsTab + - chartsTabUI + - filterTab + - filterTabUI + - homeTab + - homeTabUI + - loadCharts + - loadChartsUI + - loadData + - loadDataUI + - mappingTab + - mappingTabUI + - mappingDomain + - mappingDomainUI + - mappingColumn + - mappingColumnUI + - mappingSelect + - mappingSelectUI + - settingsTab + - settingsTabUI + - settingsCharts + - settingsChartsUI + - settingsData + - settingsDataUI + - settingsMapping + - settingsMappingUI + - settingsCode + - settingsCodeUI + - title: Data + desc: Data sets used in the apps + contents: + - meta - title: Helper Functions - desc: these functions are used by the main app + desc: Utility functions used in the apps contents: - - addChart - - addSetting - - adlbc - - chartRenderer-shiny - - chartRenderer - - chartsMetadata + - app_startup + - chartsNav - detectStandard - - generateSettings - - getRequiredSettings - - getSettingsMetadata - - removeCharts - - removeSettings - - settingsMetadata - - standardsMetadata - - trimSettings - - validateSettings + - evaluateStandard + - filterTabChecks + - generateMappingList + - makeChartConfig + - makeChartExport + - makeChartParams + - makeChartSummary + - makeMapping + - prepareChart diff --git a/docs/404.html b/docs/404.html index 0eaf4b23..1013dc52 100644 --- a/docs/404.html +++ b/docs/404.html @@ -8,23 +8,29 @@ Page not found (404) • safetyGraphics + - + - + + - + + + + + - - + + - + - - + + @@ -32,10 +38,12 @@ + + @@ -49,7 +57,7 @@ - + + + diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index 83016c8b..b5b04273 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -8,23 +8,29 @@ License • safetyGraphics + - + - + + - + + + + + - - + + - + - - + + @@ -32,10 +38,12 @@ + + @@ -49,7 +57,7 @@ - + -
YEAR: 2018
-COPYRIGHT HOLDER: Rho Inc.
+
YEAR: 2021
+COPYRIGHT HOLDER: safetyGraphics authors
 
+ +
diff --git a/docs/LICENSE.html b/docs/LICENSE.html new file mode 100644 index 00000000..96f3686c --- /dev/null +++ b/docs/LICENSE.html @@ -0,0 +1,175 @@ + + + + + + + + +MIT License • safetyGraphics + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+
+ + +
+ +

Copyright (c) 2021 safetyGraphics authors

+

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

+

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+
+ +
+ + + +
+ + + +
+ + +
+

Site built with pkgdown 1.6.1.

+
+ +
+
+ + + + + + + + diff --git a/docs/articles/chartConfiguration.html b/docs/articles/chartConfiguration.html new file mode 100644 index 00000000..b7013ee9 --- /dev/null +++ b/docs/articles/chartConfiguration.html @@ -0,0 +1,411 @@ + + + + + + + +Chart Configuration • safetyGraphics + + + + + + + + + + +
+
+ + + + +
+
+ + + + +
+

+Chart Configuration Vignette

+

The {safetyGraphics} shiny app can be used to display a wide variety of charts. This vignette provides details about the charting process including step-by-step instructions for adding new charts and technical specifications, but first we need to talk about a 2nd package …

+
+
+

+Introducing {safetyCharts}

+

While this is technically a vignette for {safetyGraphics}, the {safetyCharts} package is just as important here. The roles of the packages can be summarized in just a few words:

+

The {safetyGraphics} platform displays charts from {safetyCharts}.

+

This relationship is central to the technical framework for the safetyGraphics app. By itself, the safetyGraphics platform really doesn’t do much! In fact, none of the content on the Charts tab is actually found in the safetyGraphics package; it’s all imported from elsewhere! As you’ve probably guessed, the default charts live in the safetyCharts package. safetyCharts has over a dozen charts that are configured to work with {safetyGraphics}, but can also easily be used independently.

+

While {safetyGraphics} and {safetyCharts} are designed to work seamlessly together, users can also add charts from other packages. In fact, several charts in {safetyCharts} are just wrappers that load charts from other packages for use in {safetyGraphics}. The rest of this vignette provides a series of step-by-step examples detailing how this process works for different types of charts.

+
+
+

+{safetyGraphics} Chart Components

+

To add a chart to safetyGraphics, two components are required:

+
    +
  1. A Configuration Object
  2. +
  3. A Chart Function
  4. +
+

The configuration file captures metadata about the chart for use in the app and is typically saved as a YAML file. Several example configuration files are provided in the examples below, and YAML Configuration files for {safetyCharts} are saved here.

+

The chart function typically takes a list of settings and a list of data as inputs and returns a chart object ready to be displayed in the app. Details of charting functions vary somewhat for different chart types, as explained in the examples below.

+

A full technical specification of this chart configuration framework is provided in Appendix 1.

+
+
+

+Example 1 - Hello World

+

Once you’ve created the configuration and chart functions, the chart can be added to the app via the charts parameter in safetyGraphicsApp(). Consider this simple “Hello World” example:

+
# Chart Function
+helloWorld <- function(data, settings){
+    plot(-1:1, -1:1)
+    text(runif(20, -1,1),runif(20, -1,1),"Hello World")
+}
+
+# Chart Configuration
+helloworld_chart<-list(
+    env="safetyGraphics",
+    name="HelloWorld",
+    label="Hello World!",
+    type="plot",
+    domain="aes",
+    workflow=list(
+        main="helloWorld"
+    )
+)
+
+safetyGraphicsApp(charts=list(helloworld_chart))
+

It’s also easy to add a custom chart to the default charts provided in {safetyCharts} using the makeChartConfig() function:

+
charts <- makeChartConfig(packages="safetyCharts") # or just makeChartConfig() since safetyCharts is included by default
+charts$helloworld<-helloworld_chart
+safetyGraphicsApp(charts=charts)
+

Here’s our Hello World the chart running in the app:

+

+
+
+

+Example 2 - Static Outlier Explorer

+

Now let’s consider a more complex example that makes use of the data and settings provided in safetyGraphics. In this section, we use {ggplot2} to create a spaghetti plot for tracking outliers in lab data. First, consider the following code which creates a stand-alone plot for a single data set:

+
# Use sample clinical trial data sets from the {safetyData} package
+library(safetyData) 
+library(ggplot2)
+library(dplyr)
+
+# Define data mapping using a format similar to a reactive safetyGraphics mapping 
+settings <- list(
+    id_col="USUBJID",
+    value_col="LBSTRESN",
+    measure_col="LBTEST",
+    studyday_col="LBDY"
+)
+
+# Define a plotting function that takes data and settings as inputs 
+spaghettiPlot <- function( data, settings ){
+    # define plot aes - note use of standard evaluation! 
+    plot_aes <- aes_(
+        x=as.name(settings$studyday_col), 
+        y=as.name(settings$value_col), 
+        group=as.name(settings$id_col)
+    )
+
+    #create the plot
+    p<-ggplot(data = data, plot_aes) +
+        geom_path(alpha=0.15) + 
+        facet_wrap(
+            as.name(settings$measure_col),
+            scales="free_y"
+        )
+    return(p)
+}
+
+spaghettiPlot(
+    safetyData::sdtm_lb %>% 
+        filter(LBTEST %in% c("Albumin","Bilirubin","Calcium","Chloride")), 
+    settings
+)
+

Running the code above should create a plot with 4 panels:

+

+

With minor modifications, this chart can be added to the {safetyGraphics} shiny app, which allows us to create the chart with any mappings/data combination loaded in the app. The spaghettiPlot() function above is already written to work with safetyGraphics, so we just need to create the chart configuration object. This time we’ll capture the configuration in a YAML file.

+
env: safetyGraphics
+label: Spaghetti Plot
+type: plot
+domain: 
+  - labs
+workflow:
+  main: spaghettiPlot
+links:
+  safetyCharts: https://github.com/SafetyGraphics/safetycharts
+

With the charting function loaded in to our session and the configuration file saved in our working directory as spaghetti.yaml, we can add the chart to the app as follows:

+
library(yaml)
+charts <- makeChartConfig()
+charts$spaghetti<-prepareChart(read_yaml('spaghetti.yaml'))
+safetyGraphicsApp(charts=charts)
+

Under the charts tab, you’ll see:

+

+

If you look closely at the spaghettiPlot() code above, you’ll noticed some details that make the chart work in the app:

+
    +
  • The chart function is written as a function taking data and settings as inputs. This is the expected parameterization for most charts in {safetyGraphics}.
  • +
  • The references to settings use parameters that are defined on the mapping tab. Behind the scenes, these are defined in the safetyGraphics::meta.
  • +
  • The spaghettiPlot function is referenced in the main item the YAML workflow. This tells the app which function to use to draw the chart.
  • +
+

These details allow users to dynamically define data attributes for any labs data set, allowing the chart to be reused across many different types of data.

+

This example is inspired by safetyCharts::safety_outlier_explorer - the charting function and yaml configuration file on are GitHub.

+
+
+

+Example 3 - Shiny Module

+

{safetyGraphics} also supports defining charts as Shiny Modules. Once you’re familiar with modules, they are relatively straightforward to use with safetyGraphics.

+

Let’s take a look at a simple module that extends the functionality of the static chart from the example above. Once again, this example is based upon safetyCharts, and you can see the code and config on GitHub.

+

The config object for a module differs from a static chart is that the workflow section of the YAML file must specify ui and server functions instead of a main charting function. This example defines a simple UI function that allows users to select which lab measurements should be included in the spaghetti plot from example 1:

+
safetyOutlierExplorer_ui <- function(id) {
+    ns <- NS(id) 
+    sidebar<-sidebarPanel(
+        selectizeInput(
+            ns("measures"), 
+            "Select Measures", 
+            multiple=TRUE, 
+            choices=c("")
+        )
+    )
+    main<-mainPanel(plotOutput(ns("outlierExplorer")))
+    ui<-fluidPage(
+        sidebarLayout(
+            sidebar,
+            main,
+            position = c("right"),
+            fluid=TRUE
+        )
+    )
+    return(ui)
+}
+

Next we define a server function that populates the control for selecting measurements and then draws the plot using safetyCharts::safety_outlier_explorer() charting function - which is based on the spaghetti() function ! Note that the server function takes a single reactive params object containing the data (params$data) and settings (param$settings) as input.

+
safetyOutlierExplorer_server <- function(input, output, session, params) {
+
+    ns <- session$ns
+    # Populate control with measures and select all by default
+    observe({
+        measure_col <- params()$settings$measure_col
+        measures <- unique(params()$data[[measure_col]])
+        updateSelectizeInput(
+            session, 
+            "measures",
+            choices = measures,
+            selected = measures
+        )
+    })
+
+    # customize selected measures based on input
+    settingsR <- reactive({
+        settings <- params()$settings
+        settings$measure_values <- input$measures
+        return(settings)
+    })
+
+    #draw the chart
+    output$outlierExplorer <- renderPlot({safety_outlier_explorer(params()$data, settingsR())})
+}
+

Finally, the YAML configuration file looks like this - just the workflow and label changes from Example 1:

+
env: safetyGraphics
+label: Outlier Explorer - Module
+type: module
+package: safetyCharts
+domain: 
+  - labs
+workflow:
+  ui: safetyOutlierExplorer_ui
+  server: safetyOutlierExplorer_server
+links:
+  safetyCharts: https://github.com/SafetyGraphics/safetycharts
+

Initializing the app as usual by adding it to the chart list: charts$outlierMod<-prepareChart(read_yaml('outlierMod.yaml'))

+

Unselecting a few measures gives the following display:

+
+
+

+Example 4 - htmlwidgets and init functions

+

You can also add custom htmlwidgets to safetyGraphics. In fact, many of the default charts imported from safetyCharts are javascript libraries that are imported as htmlwidgets. Like shiny modules, htmlwidgets are relatively simple to use once you are familiar with the basics.

+

The biggest differences between widgets and other charts in safetyGraphics are:

+
    +
  1. The widget must be contained in a package, which must be specified in the YAML file.
  2. +
  3. The widget expects a widget item giving the name of the widget in the YAML workflow.
  4. +
  5. By default, the data and settings for a widget are passed in a list (list(data=data, settings=settings)) to the x parameter in htmlwidget::createWidget.
  6. +
+

Items 1 and 2 above are simple enough, but #3 is likely to create problems unless the widget is designed specifically for usage with safetyGraphics. That is, if the widget isn’t expecting x$settings to be a list that it uses to configure the chart, it probably isn’t going to work as expected.

+

Fortunately, there’s a workaround built in to safetyGraphics in the form of init workflow functions. Init functions run before the chart is drawn, and can be used to create custom parameterizations. The init function should take data and settings as inputs and return params which should be a list which is then provided to the chart (see the appendix for more details). The init function for the the interactive AE Explorer is a good example. It starts by merging demographics and adverse event data and then proceeds to create a customized settings object to match the configuration requirements of the javascript chart renderer. This init function is then saved under workflow$init in the chart config object.

+

The rest of the chart configuration YAML is similar to the examples above, and the chart is once again by passing the chart config object to safetyGraphicsApp()

+
+
+

+Appendix #1 - Chart Framework Technical Specifications

+
+

+Configuration Overview

+

+

The diagram above summarizes the various components of the safetyGraphics charting framework: - The safetyGraphicsApp() function allows users to specify which charts to include in the shiny app via the charts parameter, which expects a list of charts. - Each item in charts is itself defined as a list that provides configuration details for a single chart. These configuration lists have several required parameters, which are described in the technical specification below. - Configuration lists are typically saved as YAML files, but can be also be loaded directly as list objects as shown in the Hello World example above. - Needed functions are bound to the chart object via the prepareChart() function. See the documentation for chart$functions below for full details.

+
+
+

+Chart Specification

+

Each item in the charts list should be a list() with the following parameters: - env: Environment for the chart. Must be set to “safetyGraphics” or the chart is dropped. Type: character. Required - name: Name of the chart. Type: character. Required - type:: Type of chart. Valid options are: “plot”,“htmlwidget”,“html”,“table” and “module”. Type: character. Required - label: A short description of the chart. chart\(name is used if not provided. Type: *character*. *Optional* - `domain`: The data domain(s) used in the chart. Type: *character*. **Required** - `package`: The package where the {htmlwidget} is saved. Type: *character*. **Required** when `chart\)typeis "htmlwidget" -order: Order in which to display the chart. If order is a negative number, the chart is dropped. Defaults to 999999. Type: *Integer*. *Optional* -links: Named list of link names/urls to be shown in the chart header. Type: *list of character*. *Optional* -path: Full path of the YAML file. Auto-generated bymakeChartConfig()Type: *character* *optional* -workflow: Names of functions used to create the chart. Should be loaded in global environment or included inchart\(package` before calling `prepareChart()`. Supported parameters are listed below. Type: *list of character*. **Required** - `workflow\)main: name of the function to draw the chart. The function should takedataandsettingsparameters unless the input parameters are customized by aninitfunction. **Required**, unlesschart\(type` is "htmlwidget" or "module") - `workflow\)init: name of initialization function that runs before chart is drawn via the main function. Should take data and settings as input and return a list of parameters accepted by the main function. Optional - workflow$widget: name or widget saved in chart$package to be passed to htmlwidgets::createWidget Required when chart$type is “htmlwidget” - workflow$ui and workflow$server: names of functions to render shiny ui and server. Automatically generated in prepareChart() unless chart$type is “module”. Required when chart$type is ‘module’ - functions: a list of functions used to create the chart. Typically generated at runtime by prepareChart() using information in chart$workflow, chart$type and chart$package. Not recommended to generate manually. Type: list of functions. Required

+
+
+

+Default Technical workflow

+

This appendix describe the technical process used to render a chart when safetyGraphicsApp() is called with the default parameters.

+
    +
  1. +safetyGraphicsApp() is called with charts and chartSettingsPath as NULL (the default).
  2. +
  3. +app_startup is called, which then immediately calls makeChartConfig().
  4. +
  5. +makeChartConfig() looks for charts in the safetyCharts package (the default) since no path was specified. The function looks for the package in all current .libPaths() and then looks in the inst/config folder once the package is found.
  6. +
  7. +makeChartConfig loads YAML configuration files in the specified directories and saves them to a list. name and path parameters are added.
  8. +
  9. +makeChartConfig calls prepareChart for each chart configuration. prepareChart sets default values for order, name and export, and then binds relevant functions to a chart$functions list based on the chart’s type, workflow and package.
  10. +
  11. That list of charts is then returned to app_startup() which runs a few actions on each chart: +
      +
    • If chart$functions is missing, prepareChart is called (not relevant in the default workflow, but useful for adding custom charts)
    • +
    • If chart$order is negative, the chart is dropped with a message.
    • +
    • If chart$env is not “safetyGraphics”, the chart is dropped with a message.
    • +
    • If chart$domains has elements not found in the dataDomains passed to `app_startup(), the chart is dropped with a message.
    • +
    • +charts are re-ordered based on chart$order +
    • +
    +
  12. +
  13. +app_startup returns the list of charts to safetyGraphicsApp which then then passes them along to safetyGraphicsServer as the charts parameter.
  14. +
  15. +safetyGraphicsServer then creates modules for each chart. First, UIs are created via chartsNav() which then calls: +
      +
    • +makeChartSummary to create the chart header with links and metadata and …
    • +
    • +ChartsTabUI which then calls chart$functions$ui to create the proper UI element based on chart$type.
    • +
    +
  16. +
  17. Next, safetyGraphicsServer draws the charts using chartsTab() which: +
      +
    • Creates a reactive params object containing mappings and data using makeChartParams() which: +
        +
      • Subsets domainData based on chart$domain +
      • +
      • Calls charts$functions$init if provided
      • +
      • Does custom formatting for chart$type of “htmlwidget”
      • +
      +
    • +
    • Chart is drawn using chart$functions$server and chart$functions$main +
    • +
    • Button to download R script is added to header. Script is created by makeChartExport() +
    • +
    • Button to download html report is added to header unless type=“module”. Report template is at “inst/reports/safetyGraphicsReport.Rmd”
    • +
    +
  18. +
  19. Finally, safetyGraphicsServer passes the charts to settingsTab, which uses them to help populate the charts and code subtabs.
  20. +
+
+
+
+ + + +
+ + + +
+ +
+

Site built with pkgdown 1.6.1.

+
+ +
+
+ + + + + + diff --git a/docs/articles/chartConfiguration_files/header-attrs-2.10/header-attrs.js b/docs/articles/chartConfiguration_files/header-attrs-2.10/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/articles/chartConfiguration_files/header-attrs-2.10/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/articles/index.html b/docs/articles/index.html index 2adb935d..ccf3ae6f 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -8,23 +8,29 @@ Articles • safetyGraphics + - + - + + - + + + + + - - + + - + - - + + @@ -32,10 +38,12 @@ + + @@ -49,7 +57,7 @@ - +
@@ -71,33 +79,38 @@ -
@@ -136,11 +151,11 @@

All vignettes

-

Site built with pkgdown 1.4.1.

+

Site built with pkgdown 1.6.1.

diff --git a/docs/articles/intro.html b/docs/articles/intro.html new file mode 100644 index 00000000..8033f03f --- /dev/null +++ b/docs/articles/intro.html @@ -0,0 +1,245 @@ + + + + + + + +Intro to Shiny App • safetyGraphics + + + + + + + + + + +
+
+ + + + +
+
+ + + + +
+

+Intro Vignette

+

The safetyGraphics shiny app provides an easy-to-use shiny interface for creating shareable safety graphics for any study. This vignette provides an overview of the app’s functionality, shows how to initialize the app with your own study data, and provides links to technical resources explaining how to customize the app.

+
+
+

+safetyGraphics Demo

+

A demo of shiny application using data from the {safetyData} package is hosted here. The app can also be initialized with the safetyGraphicsApp() function in the R console - see Appendix 1 for details.

+

Let’s take a quick look at the various pages in the app.

+
+

+Home Tab

+

A home page has a basic overview of the app.

+

+
+
+

+Mapping Tab

+

The Mapping tab is used to tell charts which data columns and fields to use for various chart components.

+

+

This mapping process makes it easy to re-use charts across many different studies. You can see previews of the loaded data using the checkbox at the top of the page. The demo data has 3 data domains (labs, adverse events (aes) and demographics (dm)), but others can be added as well. The mapping tab is automatically filled in for common data standards, like the ADaM data shown here, but can also be filled in manually for non-standard data.

+
+
+

+Filtering Tab

+

The Filtering tab allows users to interactively select which participants to include in charts.

+

+

This tab is created using the filter functionality included in the {datamods} package. Whenever data is filtered in this tab, those filtered data are used in all charts (across all data domains). Note that the number of participants selected is always shown in the upper right hand corner of the app.

+
+
+

+Charts Tab

+

Clicking the Charts tab opens a dropdown menu containing a series of charts related to clinical trial safety. Clicking the Hepatic Safety Explorer opens this page:

+

+

safetyGraphics supports many different kinds of charts including web-based interactive graphics using {htmlwidgets} (like the chart shown above), static plots, plotly plots and custom shiny modules. Each chart has a header that provides details about the chart, links to chart-specific resources and buttons that allow users to download a stand-alone html report or a .R file that reproduces the chart. See the Chart Configuration Vignette for more detail about the safetyGraphics charting framework.

+
+
+

+⚙️ (Settings) Tab

+

Finally, the Settings tab - shown as a gear icon ⚙️ - contains technical details that can be used to customize/troubleshoot the app. Clicking on the “Code” sub-tab (shown below) allows you to download a zip file that can be used to re-open the app with with any customizations that have been made during your current session.

+

+
+
+
+

+Loading Study Data

+

There are 2 primary ways to load your study data in to the safetyGraphics shiny app:

+
    +
  1. Using safetyGraphicsInit() shiny interface
  2. +
  3. Passing data directly to safetyGraphicsApp() +
  4. +
+
+

+Loading data with safetyGraphicsInit() +

+

The safetyGraphicsInit() function starts a simple app that allows users to select charts and then load the data required via a point-and-click interface as shown below:

+

+

The app dynamically determines which data sets are required for the selected charts and updates the “Data Loader” UI when the charts selection changes. Below, we’ve selected 2 charts from the labs domain - so the other data domains are automatically hidden.

+

+

Once you’ve picked charts, click the “Load” buttons in the “Data Loader” section to select data files for each domain. Data is loaded using the import functionality from the {datamods} package which allows you to select data loaded in your R session or load data files directly from your file system. datamods supports any file format that {rio} can handle including text files, Excel, SAS and SPSS format.

+

Once you’ve loaded files for all of the active data domains, the “Run App” button will become active. Click it to initialize the app.

+
+
+

+Passing data to safetyGraphicsApp() +

+

You can also initialize the app with custom data directly from the R console. The basic workflow is as follows:

+
    +
  1. Load your data in to the R session
  2. +
  3. Save your data as a named list. The name of each list item should correspond to a safetyGraphics data domain.
  4. +
  5. Run safetyGraphicsApp() using the domainData to pass the list of data frames.
  6. +
+

Here is a simple example that starts the app with SDTM data from the safetyData library:

+
library(safetyData)
+sdtm <- list(
+    dm=safetyData::sdtm_dm,
+    aes=safetyData::sdtm_ae,
+    labs=safetyData::sdtm_lb
+)
+
+safetyGraphics::safetyGraphicsApp(domainData=sdtm)
+

This example and other use cases are described in the safetyGraphics Cookbook - Advanced Examples Vignette.

+
+
+
+

+Additional Resources

+

Several additional vignettes are available for more advanced topics: - Chart Configuration Vignette - details about the charting process including technical specifications and step-by-step instructions - Cookbook Vignette - a series of examples showing how to initialize the safetyGraphics Shiny app in different scenarios - Technical FAQ Vignette Vignette - vignette discussing security, validation and other technical issues

+

The {safetyGraphics} app is maintained by the Interactive Safety Graphics (ISG) subteam of the ASA Biopharm-DIA Safety Working Group. You can learn more about the team and find links to recent presentations and publications at our home page.

+
+
+

+Appendix 1 - Initialization code

+

We suggest running the app in RStudio with R version 4.0 or higher. The following code installs the {safetyGraphics} package and initializes the app demo:

+
install.packages('safetyGraphics')
+library(safetyGraphics)
+safetyGraphicsApp() 
+

Or to use the initialization workflow:

+
install.packages('safetyGraphics')
+library(safetyGraphics)
+safetyGraphicsInit() 
+

Or you can install the most recent development version of {safetyGraphics} and the companion package {safetyCharts} directly from GitHub:

+
install.packages("devtools")
+library(devtools)
+devtools::install_github("safetyGraphics/safetyGraphics") 
+library(safetyGraphics)
+devtools::install_github("safetyGraphics/safetyCharts") 
+library(safetyCharts)
+safetyGraphicsApp() #or safetyGraphicsInit()
+
+
+ + + +
+ + + +
+ +
+

Site built with pkgdown 1.6.1.

+
+ +
+
+ + + + + + diff --git a/docs/articles/intro_files/header-attrs-2.10/header-attrs.js b/docs/articles/intro_files/header-attrs-2.10/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/articles/intro_files/header-attrs-2.10/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/authors.html b/docs/authors.html index 231c124c..06c9745f 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -8,23 +8,29 @@ Authors • safetyGraphics + - + - + + + + - + + + - - + + - + - - + + @@ -32,10 +38,12 @@ + + @@ -49,7 +57,7 @@ - + @@ -164,11 +169,11 @@

Authors

diff --git a/docs/bootstrap-toc.css b/docs/bootstrap-toc.css new file mode 100644 index 00000000..5a859415 --- /dev/null +++ b/docs/bootstrap-toc.css @@ -0,0 +1,60 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ + +/* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ + +/* All levels of nav */ +nav[data-toggle='toc'] .nav > li > a { + display: block; + padding: 4px 20px; + font-size: 13px; + font-weight: 500; + color: #767676; +} +nav[data-toggle='toc'] .nav > li > a:hover, +nav[data-toggle='toc'] .nav > li > a:focus { + padding-left: 19px; + color: #563d7c; + text-decoration: none; + background-color: transparent; + border-left: 1px solid #563d7c; +} +nav[data-toggle='toc'] .nav > .active > a, +nav[data-toggle='toc'] .nav > .active:hover > a, +nav[data-toggle='toc'] .nav > .active:focus > a { + padding-left: 18px; + font-weight: bold; + color: #563d7c; + background-color: transparent; + border-left: 2px solid #563d7c; +} + +/* Nav: second level (shown on .active) */ +nav[data-toggle='toc'] .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} +nav[data-toggle='toc'] .nav .nav > li > a { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 30px; + font-size: 12px; + font-weight: normal; +} +nav[data-toggle='toc'] .nav .nav > li > a:hover, +nav[data-toggle='toc'] .nav .nav > li > a:focus { + padding-left: 29px; +} +nav[data-toggle='toc'] .nav .nav > .active > a, +nav[data-toggle='toc'] .nav .nav > .active:hover > a, +nav[data-toggle='toc'] .nav .nav > .active:focus > a { + padding-left: 28px; + font-weight: 500; +} + +/* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ +nav[data-toggle='toc'] .nav > .active > ul { + display: block; +} diff --git a/docs/bootstrap-toc.js b/docs/bootstrap-toc.js new file mode 100644 index 00000000..1cdd573b --- /dev/null +++ b/docs/bootstrap-toc.js @@ -0,0 +1,159 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ +(function() { + 'use strict'; + + window.Toc = { + helpers: { + // return all matching elements in the set, or their descendants + findOrFilter: function($el, selector) { + // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ + // http://stackoverflow.com/a/12731439/358804 + var $descendants = $el.find(selector); + return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); + }, + + generateUniqueIdBase: function(el) { + var text = $(el).text(); + var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); + return anchor || el.tagName.toLowerCase(); + }, + + generateUniqueId: function(el) { + var anchorBase = this.generateUniqueIdBase(el); + for (var i = 0; ; i++) { + var anchor = anchorBase; + if (i > 0) { + // add suffix + anchor += '-' + i; + } + // check if ID already exists + if (!document.getElementById(anchor)) { + return anchor; + } + } + }, + + generateAnchor: function(el) { + if (el.id) { + return el.id; + } else { + var anchor = this.generateUniqueId(el); + el.id = anchor; + return anchor; + } + }, + + createNavList: function() { + return $(''); + }, + + createChildNavList: function($parent) { + var $childList = this.createNavList(); + $parent.append($childList); + return $childList; + }, + + generateNavEl: function(anchor, text) { + var $a = $(''); + $a.attr('href', '#' + anchor); + $a.text(text); + var $li = $('
  • '); + $li.append($a); + return $li; + }, + + generateNavItem: function(headingEl) { + var anchor = this.generateAnchor(headingEl); + var $heading = $(headingEl); + var text = $heading.data('toc-text') || $heading.text(); + return this.generateNavEl(anchor, text); + }, + + // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). + getTopLevel: function($scope) { + for (var i = 1; i <= 6; i++) { + var $headings = this.findOrFilter($scope, 'h' + i); + if ($headings.length > 1) { + return i; + } + } + + return 1; + }, + + // returns the elements for the top level, and the next below it + getHeadings: function($scope, topLevel) { + var topSelector = 'h' + topLevel; + + var secondaryLevel = topLevel + 1; + var secondarySelector = 'h' + secondaryLevel; + + return this.findOrFilter($scope, topSelector + ',' + secondarySelector); + }, + + getNavLevel: function(el) { + return parseInt(el.tagName.charAt(1), 10); + }, + + populateNav: function($topContext, topLevel, $headings) { + var $context = $topContext; + var $prevNav; + + var helpers = this; + $headings.each(function(i, el) { + var $newNav = helpers.generateNavItem(el); + var navLevel = helpers.getNavLevel(el); + + // determine the proper $context + if (navLevel === topLevel) { + // use top level + $context = $topContext; + } else if ($prevNav && $context === $topContext) { + // create a new level of the tree and switch to it + $context = helpers.createChildNavList($prevNav); + } // else use the current $context + + $context.append($newNav); + + $prevNav = $newNav; + }); + }, + + parseOps: function(arg) { + var opts; + if (arg.jquery) { + opts = { + $nav: arg + }; + } else { + opts = arg; + } + opts.$scope = opts.$scope || $(document.body); + return opts; + } + }, + + // accepts a jQuery object, or an options object + init: function(opts) { + opts = this.helpers.parseOps(opts); + + // ensure that the data attribute is in place for styling + opts.$nav.attr('data-toggle', 'toc'); + + var $topContext = this.helpers.createChildNavList(opts.$nav); + var topLevel = this.helpers.getTopLevel(opts.$scope); + var $headings = this.helpers.getHeadings(opts.$scope, topLevel); + this.helpers.populateNav($topContext, topLevel, $headings); + } + }; + + $(function() { + $('nav[data-toggle="toc"]').each(function(i, el) { + var $nav = $(el); + Toc.init($nav); + }); + }); +})(); diff --git a/docs/index.html b/docs/index.html index 763ab389..6f45a499 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6,19 +6,19 @@ Create Interactive Graphics Related to Clinical Trial Safety • safetyGraphics - - - - + + + + + - - +
    - -
    +

    R build status

    +
    -

    The safetyGraphics package provides a framework for evaluation of clinical trial safety in R. It includes several safety-focused visualizations to empower clinical data monitoring. Chief among these is the Hepatic Explorer, based on the Evaluation of the Drug-Induced Serious Hepatotoxicity (eDish) visualization. A demo of the Hepatic Explorer interactive graphic is available here and is shown below.

    -

    This package is being built in conjunction with the hep-explorer javascript library.

    +

    The {safetyGraphics} package provides a framework for evaluating of clinical trial safety in R using a flexible data pipeline. The package includes a shiny application that allows users to explore safety data using a series of interactive graphics, including the hepatic safety explorer shown below. The package has been developed as part of the Interactive Safety Graphics (ISG) workstream of the ASA Biopharm-DIA Safety Working Group.

    edishgif

    -
    +

    -Usage

    -

    Users can interactively explore their data with a shiny application or create standalone interactive charts.

    -
    -

    -Shiny application

    -

    The Shiny app provides a simple interface for:

    -
      -
    • Loading data
    • -
    • Customizing settings and data mappings
    • -
    • Viewing and exporting the interactive graphics
    • -
    -
    devtools::install_github("SafetyGraphics/safetyGraphics")
    -library("safetyGraphics")
    -safetyGraphicsApp() #open the shiny application
    -
    -
    -

    -Standalone charts

    -

    Users can also initialize customized standalone charts with a few lines of code.

    -
    devtools::install_github("safetyGraphics/safetyGraphics")
    -library("safetyGraphics")
    -
    -settings <- list(
    -  id_col = "USUBJID",
    -  value_col = "AVAL",
    -  measure_col = "PARAM",
    -  visit_col = "VISIT",
    -  visitn_col = "VISITNUM",
    -  studyday_col = "ADY",
    -  normal_col_low = "A1LO",
    -  normal_col_high = "A1HI",
    -  measure_values = list(ALT = "Alanine Aminotransferase (U/L)",
    -                        AST = "Aspartate Aminotransferase (U/L)",
    -                        TB = "Bilirubin (umol/L)",
    -                        ALP = "Alkaline Phosphatase (U/L)")
    -  )
    -
    -chartRenderer(data=adlbc, settings=settings, chart="hepexplorer")
    +Using the app

    +

    A demo of the app using sample data is available here or can be initialized as follows:

    +
    +devtools::install_github("SafetyGraphics/safetyGraphics")
    +library("safetyGraphics")
    +safetyGraphicsApp() #open the shiny application
    +

    The most common workflow is for a user to initialize the app with their data, adjust settings as needed, and view the interactive charts. Finally, the user can share any chart by exporting its source code or by generating a self-contained, fully reproducible report that can be shared with others.

    +

    Instructions for loading study data are provided in the introductory vignette and more complex customizations are provided in the cookbook vignette.

    +
    +

    +Charts

    +

    The app is built to support a wide variety of chart types including static plots (e.g. from {ggplot2}), shiny modules, {htmlwidgets} and even static outputs like RTFs. Several pre-configured charts are included in the companion {safetyCharts} R Package, and are available by default in the app. Other charts can be added using the process descibed in this vignette.

    -
    -

    Site built with pkgdown 1.4.1.

    +

    Site built with pkgdown 1.6.1.

    diff --git a/docs/news/index.html b/docs/news/index.html index ce95a77e..5868715f 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -8,23 +8,29 @@ Changelog • safetyGraphics + - + - + + - + + + + + - - + + - + - - + + @@ -32,10 +38,12 @@ + + @@ -49,7 +57,7 @@ - +
    @@ -71,33 +79,38 @@ -
    diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index f176e82c..a081efc2 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -2,9 +2,11 @@ pandoc: 2.11.4 pkgdown: 1.6.1 pkgdown_sha: ~ articles: - chartConfiguration: chartConfiguration.html - intro: intro.html -last_built: 2021-09-01T14:52Z + ChartConfiguration: ChartConfiguration.html + Cookbook: Cookbook.html + Intro: Intro.html + TechnicalFAQ: TechnicalFAQ.html +last_built: 2021-09-02T17:22Z urls: reference: https://pages.github.com/SafetyGraphics/safetyGraphics/reference article: https://pages.github.com/SafetyGraphics/safetyGraphics/articles diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 2e923e3b..b81e6b3e 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -154,9 +154,15 @@ https://pages.github.com/SafetyGraphics/safetyGraphics/reference/textKeysToList.html - https://pages.github.com/SafetyGraphics/safetyGraphics/articles/chartConfiguration.html + https://pages.github.com/SafetyGraphics/safetyGraphics/articles/ChartConfiguration.html - https://pages.github.com/SafetyGraphics/safetyGraphics/articles/intro.html + https://pages.github.com/SafetyGraphics/safetyGraphics/articles/Cookbook.html + + + https://pages.github.com/SafetyGraphics/safetyGraphics/articles/Intro.html + + + https://pages.github.com/SafetyGraphics/safetyGraphics/articles/TechnicalFAQ.html diff --git a/vignettes/Cookbook.Rmd b/vignettes/Cookbook.Rmd new file mode 100644 index 00000000..287db308 --- /dev/null +++ b/vignettes/Cookbook.Rmd @@ -0,0 +1,145 @@ +--- +title: "Cookbook" +author: "Jeremy Wildfire" +date: "`r Sys.Date()`" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Cookbook} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +# Cookbook Vignette + +This vignette contains a series of examples showing how to initialize the safetyGraphics Shiny app in different scenarios. For a general overview of the app see [this vignette](). For more details about adding custom charts, see [this vignette](). + +## Setup and installation + +safetyGraphics requires R v4 or higher. These examples have been tested using RStudio v1.4, but should work on other platforms with proper configuration. + +You can install `{safetyGraphics}` from CRAN like any other R package: + +``` +install.packages("safetyGraphics") +library("safetyGraphics") +``` + +Or to use the most recent development version from GitHub, call: + +``` +devtools::install_github("safetyGraphics/safetyCharts", ref="dev") +library(safetyCharts) +devtools::install_github("safetyGraphics/safetyGraphics", ref="dev") +library(safetyGraphics) +safetyGraphics::safetyGraphicsApp() +``` + +## Example 1 - Default App + +To run the app with no customizations using sample AdAM data from the {safetyData} package, install the package and run: + +``` +safetyGraphics::safetyGraphicsApp() +``` + +## Example 2 - SDTM Data + +The data passed in to the safetyGraphics app can be customized using the `data` parameter in `safetyGraphicsApp()`. For example, to run the app with SDTM data saved in `{safetyData}`, call: + +``` +sdtm <- list( + dm=safetyData::sdtm_dm, + aes=safetyData::sdtm_ae, + labs=safetyData::sdtm_lb +) + +safetyGraphics::safetyGraphicsApp(domainData=sdtm) +``` + +## Example 3 - Single Data Domain + +Running the app for a single data domain, is similar: + +``` +justLabs <- list(labs=safetyData::adam_adlbc) +safetyGraphics::safetyGraphicsApp(domainData=justLabs) +``` + +Note that charts with missing data are automatically dropped and the filtering tab is not present since it requires demographics data by default. + +## Example 4 - Drop Unwanted Charts + +Users can also generate a list of charts and then drop charts that they don't want to include. For example, if you wanted to drop charts with `type` of "htmlwidgets" you could run this code. + +``` +library(purrr) +charts <- makeChartConfig() #gets charts from safetyCharts pacakge by default +notWidgets <- charts %>% purrr::keep(~.x$type != "htmlwidget") +safetyGraphicsApp(charts=notWidgets) +``` + +## Example 6 - Add a chart + +The code below adds a new simple chart showing participants' age distribution by sex. + +``` +ageDist <- function(data, settings){ + p<-ggplot(data = data, aes_(x=as.name(settings$age_col))) + + geom_histogram() + + facet_wrap(as.name(settings$sex_col)) + return(p) +} +ageDist_chart<-list( + env="safetyGraphics", + name="ageDist", + label="Age Distribution", + type="plot", + domain="dm", + workflow=list( + main="ageDist" + ) +) +charts <- makeChartConfig() +charts$ageDist<-ageDist_chart +safetyGraphicsApp(charts=charts) +``` + +For extensive details on adding and customizing different types of charts, see this [vignette](chartConfiguration). + +## Example 7 - Non-standard data + +Next, let's initialize the the app with non-standard data. {safetyGraphics} automatically detects AdAM and SDTM data when possible, but for non-standard data, the user must provide a data mapping. This can be done in the app using the data/mapping tab, or can be done when the app is initialized by passing a `mapping` list to `safetyGraphicsApp()`. For example: + +``` +notAdAM <- list(labs=safetyData::adam_adlbc %>% rename(id = USUBJID)) +idMapping<- list(labs=list(id_col="id")) +safetyGraphicsApp(domainData=notAdAM, mapping=idMapping) +``` + +## Example 8 - Non-standard data #2 + +For a more realistic example, consider [this labs data set (csv)](https://raw.githubusercontent.com/SafetyGraphics/SafetyGraphics.github.io/master/pilot/SampleData_NoStandard.csv). The data can be loaded in to safetyGraphics with the code below, but several items in the mapping page need to be filled in: + +``` +labs <- read.csv("https://raw.githubusercontent.com/SafetyGraphics/SafetyGraphics.github.io/master/pilot/SampleData_NoStandard.csv") +safetyGraphics::safetyGraphicsApp(domainData=list(labs=labs)) +``` + +drawing + +Fortunately there is no need to re-enter this mapping information in every time you re-start the app. After filling in these values once, you can export code to restart the app *with the specified settings pre-populated*. First, click on the setting icon in the header and then on "code" to see this page: + + + +The YAML code provided here captures the updates you've made on the mapping page. To re-start the app with those settings, just save these YAML code in a new file called `customSettings.yaml` in your working directory, and then call: + +``` +labs <- read.csv("https://raw.githubusercontent.com/SafetyGraphics/SafetyGraphics.github.io/master/pilot/SampleData_NoStandard.csv") +customMapping <- read_yaml("customSettings.yaml") +safetyGraphics::safetyGraphicsApp( + domainData=list(labs=labs), + mapping=customMapping +) +``` + +Note, that for more complex customizations, the setting page also provides a `.zip` file with a fully re-usable version of the app. diff --git a/vignettes/TechnicalFAQ.Rmd b/vignettes/TechnicalFAQ.Rmd new file mode 100644 index 00000000..e60f0b73 --- /dev/null +++ b/vignettes/TechnicalFAQ.Rmd @@ -0,0 +1,114 @@ +--- +title: "Cookbook" +author: "Jeremy Wildfire" +date: "`r Sys.Date()`" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Cookbook} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +# Technical FAQ Vignette + +This vignette answers frequently asked technical questions about {safetyGraphics}. It addressees questions on a variety of technical topics including Qualification and Validation status, Common Data Pipelines and Security. + +Whenever new questions come in, we'll update the version of [this FAQ in our wiki](https://github.com/SafetyGraphics/safetyGraphics/wiki/TechnicalFAQ/) - so check there first if you have a question. We'll update the vignette on CRAN whenever a new version of the package is released. + +# Validation, Quality Control and Testing + +## Q: Is the safetyGraphics package validated? +**A**: As of the version 2 release, the safetyGraphics package is intended for exploratory use only and is not validated or qualified per [21 CFR Part 11](https://www.fda.gov/regulatory-information/search-fda-guidance-documents/part-11-electronic-records-electronic-signatures-scope-and-application). No warranty or guarantees are included as part of the package. Further, any formal validation should be fit for purpose and follow your organization's procedures. That said, extensive quality checks are built in to the package (see the question below for details) and in to many of charts that are included by default. We follow the work of [R Validation hub](https://www.pharmar.org/) closely, and may release validation guidance based on the approach described in their [white paper](https://www.pharmar.org/white-paper/) at a future date. + +## Q: Can I validate charts created by safetyGraphics? +**A**: Study-specific instances of most safetyGraphics charts can be exported either as an R script or as a standalone html report. It may be possible to treat those outputs as standard TLFs (Tables, Listings and Figures) and conduct QC/Validation on them using standard statistical SOPs. Consult with your companies procedures to confirm. + +## Q: What testing/QC process for safetyGraphics? +**A**: Several layers of quality control are included in our standard development workflow including: +- Over 200 automated unit tests with `{testthat}` that run automatically via Continuous integration with GitHub actions. +- Automated unit tests for shiny modules run via a headless browser using `{shinytest}`. +- Pass all standard R checks in `R cmd check` +- Full code review of all new functionality documented in GitHub PR. +- Issue tracking in GitHub +- Formal Alpha/Beta user testing before major releases +- Basic user tests conducted before minor release + +# Use Cases, Data Sources and Deployment +## Q: What are some common use cases for safetyGraphics? + +**A**: safetyGraphics graphics has been used in a variety of ways. Some of the most common use cases thus far are: +- Analysts exploring safety data +- Clinicians monitoring ongoing studies +- Analysts and Clinicians evaluating safety signals in completed studies + +As an open source tool with a flexible data pipeline, many other use cases have been discussed: +- Data review by Data Safety Monitoring Boards ([link](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7833551/pdf/main.pdf)) +- Submissions to FDA ([link](https://phuse.s3.eu-central-1.amazonaws.com/Advance/Data+Visualisation+and+Open+Source+Technology/Interactive+Data+Visualizations+for+Decision+Making+in+Submissions+%E2%80%93%C2%A0PHUSE+Webinar.pdf)) +- Visualizing Analysis results data ([link](https://github.com/phuse-org/aesummaries)) +- Risk based monitoring + +## Q: Do I have to use a certain data standard with safetyGraphics? + +**A**: No. Any standard (or non-standard) data can be loaded as long as it meets the [minimum data requirements](Intro#appendix-2---minimum-data-requirements) for the selected data domain. Metadata capturing default CDISC standards are included with the app (see `?safetyGraphics::meta`) so that data mappings can be automatically populated when AdAM and SDTM data are loaded. Other data standards require the user to manually complete the data mapping in the mapping tab - see the [cookbook vignette](cookbook) for examples. + +## Q: What data sources does safetyGraphics support? How do I load custom data? + +**A**: This topic is covered in detail in the [Loading data section of the Introductory vignette](Intro#loading-study-data)`safetyGraphics` is designed to support a flexible data pipeline that supports many data types. In short, data can be loaded using the the `dataDomains` parameter in the `safetyGraphicsApp()` function or via the `safetyGraphicsInit()` graphical user interface. + +`safetyGraphicsApp()` - custom data can be loaded via the `dataDomains` parameter, which should be a list containing `dataframes` or `tibbles` for each clinical domain; that list can be populated by importing data from any number of sources including databases, sas files or [any number of other sources](https://r4ds.had.co.nz/data-import.html). See the [cookbook vignette](cookbook) for some basic examples of loading custom data. + +`safetyGraphicsInit()` - allows users to load tabular data from a variety of sources using the point-and-click interface provided in the {datamods} package. + +More detail is provided in the [Loading data section of the Introductory vignette](Intro#loading-study-data) + +## Q: How can the safetyGraphics app be shared? + +**A**: The safetyGraphics app can be shared using [standard shiny methodology](https://shiny.rstudio.com/tutorial/written-tutorial/lesson7/). More details for a specific use cases are given in the next few questions. Charts created by safetyGraphics can also be exported and re-used. Charts created with [htmlwidgets](https://www.htmlwidgets.org/) are especially flexible and can be used in many contexts - including in web applications outside of R. + +## Q: Can I deploy `safetyGraphics` to shinyapps.io to explore trial data from my organization? + +**A**: No, we advise against loading non-authorized, private, or non-deidentified patient data outside of your organization's firewall. Consult with your IT and QA first. There is huge risk associated with confidentiality, IP, and patient privacy. Also refer to [ShinyApps.io Chapter 8 Security and Compliance](https://docs.rstudio.com/shinyapps.io/security-and-compliance.html). + +## **Q**: Can I deploy `safetyGraphics` to an internal [rsconnect](https://www.rstudio.com/products/connect/) server? + +**A**: Yes - the easiest way to do this is likely to deploy a customized app using shiny modules. In general, you'll want to use wrap `safetyGraphicsServer()`, `safetyGraphicsUI()` and `app_startup()` in the context of `shiny_app` and then call rsconnect::deployApp(). The script below shows the code for the app deployed at [https://jwildfire.shinyapps.io/safetyGraphics/](https://jwildfire.shinyapps.io/safetyGraphics/) using demo data. + +``` +library(safetyGraphics) +library(shiny) + +domainData<-list( + labs=safetyData::adam_adlbc, + aes=safetyData::adam_adae, + dm=safetyData::adam_adsl +) + +config <- app_startup( + domainData=domainData, + meta=safetyGraphics::meta, + autoMapping = TRUE, + filterDomain="dm" +) + +shinyApp( + ui = safetyGraphicsUI("sg",config$meta, config$domainData, config$mapping, config$standards), + server = function(input,output,session){ + callModule( + safetyGraphicsServer, + "sg", + config$meta, + config$mapping, + config$domainData, + config$charts, + config$filterDomain + ) + } +) + +``` + +# Misc. + +## Q: How do I avoid R not choking on the huge volume of lab data? (from @AlbrechtDurer) +**A**: This is a very good question @AlbrechtDurer, and in my experience the answer is complex and varies for different use cases. Focusing on specific toxicities helps, but probably isn't enough in really big studies. In those cases, I think the most important thing is to design a good data pipeline that includes both a database backend (as opposed to loading all of your study data each time you initialize the app) and visualizations that summarize the data in a reasonable way (as opposed to just plotting every single data point in a scatter plot no matter what). Fortunately this is all doable in R, and improvements in this area are our radar for safetyGraphics after v2 goes live. + From 70ba060c697d36dfe2a0923946dce2fc6cc2ef65 Mon Sep 17 00:00:00 2001 From: jwildfire Date: Thu, 2 Sep 2021 16:09:37 -0400 Subject: [PATCH 6/8] Update README.md Co-authored-by: Eli Miller --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 923fa06e..a62df0da 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # safetyGraphics: Clinical Trial Monitoring with R -The {safetyGraphics} package provides a framework for evaluating of clinical trial safety in R using a flexible data pipeline. The package includes a shiny application that allows users to explore safety data using a series of interactive graphics, including the hepatic safety explorer shown below. The package has been developed as part of the Interactive Safety Graphics (ISG) workstream of the ASA Biopharm-DIA Safety Working Group. +The {safetyGraphics} package provides a framework for the evaluation of clinical trial safety data in R using a flexible data pipeline. The package includes a shiny application that allows users to explore safety data using a series of interactive graphics, including the hepatic safety explorer shown below. The package has been developed as part of the Interactive Safety Graphics (ISG) workstream of the ASA Biopharm-DIA Safety Working Group. ![edishgif](https://user-images.githubusercontent.com/3680095/45834450-02b3a000-bcbc-11e8-8172-324c2fe43521.gif) From 59e6603d282c732a9fbde8f8144761a496549531 Mon Sep 17 00:00:00 2001 From: jwildfire Date: Thu, 2 Sep 2021 16:11:50 -0400 Subject: [PATCH 7/8] Update vignettes/Cookbook.Rmd --- vignettes/Cookbook.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/Cookbook.Rmd b/vignettes/Cookbook.Rmd index 287db308..bd7a8116 100644 --- a/vignettes/Cookbook.Rmd +++ b/vignettes/Cookbook.Rmd @@ -11,7 +11,7 @@ vignette: > # Cookbook Vignette -This vignette contains a series of examples showing how to initialize the safetyGraphics Shiny app in different scenarios. For a general overview of the app see [this vignette](). For more details about adding custom charts, see [this vignette](). +This vignette contains a series of examples showing how to initialize the safetyGraphics Shiny app in different scenarios. For a general overview of the app see [this vignette](Intro). For more details about adding custom charts, see [this vignette](chartConfiguration). ## Setup and installation From c277e574aeaa64d8b1c2411e44131af621756383 Mon Sep 17 00:00:00 2001 From: jwildfire Date: Thu, 2 Sep 2021 21:22:26 -0400 Subject: [PATCH 8/8] fix vignette title. rebuild pkgdown --- docs/articles/Cookbook.html | 4 ++-- .../Cookbook_files/header-attrs-2.9/header-attrs.js | 12 ++++++++++++ docs/articles/TechnicalFAQ.html | 8 ++++---- .../header-attrs-2.9/header-attrs.js | 12 ++++++++++++ docs/articles/chartConfiguration.html | 6 +++--- .../header-attrs-2.9/header-attrs.js | 12 ++++++++++++ docs/articles/index.html | 8 ++++---- docs/articles/intro.html | 6 +++--- .../intro_files/header-attrs-2.9/header-attrs.js | 12 ++++++++++++ docs/index.html | 2 +- docs/pkgdown.yml | 8 ++++---- docs/reference/index.html | 2 +- docs/reference/meta.html | 6 +++--- docs/sitemap.xml | 8 ++++---- man/meta.Rd | 2 +- vignettes/TechnicalFAQ.Rmd | 4 ++-- 16 files changed, 80 insertions(+), 32 deletions(-) create mode 100644 docs/articles/Cookbook_files/header-attrs-2.9/header-attrs.js create mode 100644 docs/articles/TechnicalFAQ_files/header-attrs-2.9/header-attrs.js create mode 100644 docs/articles/chartConfiguration_files/header-attrs-2.9/header-attrs.js create mode 100644 docs/articles/intro_files/header-attrs-2.9/header-attrs.js diff --git a/docs/articles/Cookbook.html b/docs/articles/Cookbook.html index dcdf60d6..24121fd4 100644 --- a/docs/articles/Cookbook.html +++ b/docs/articles/Cookbook.html @@ -88,7 +88,7 @@ -
    +