diff --git a/DESCRIPTION b/DESCRIPTION
index ad5fc0d9..476adb11 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -27,6 +27,7 @@ Suggests:
plotly
Imports:
dplyr,
+ esquisse,
htmlwidgets,
purrr,
stringr,
@@ -44,3 +45,4 @@ Imports:
tidyr,
shinybusy
VignetteBuilder: knitr
+Roxygen: list(markdown = TRUE)
diff --git a/NAMESPACE b/NAMESPACE
index ef59e71f..9c9fb165 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,7 +1,10 @@
# Generated by roxygen2: do not edit by hand
+export(app_server)
export(app_ui)
export(chartsNav)
+export(chartsRenderModule)
+export(chartsRenderModuleUI)
export(chartsRenderStatic)
export(chartsRenderStaticUI)
export(chartsRenderWidget)
@@ -13,9 +16,9 @@ export(evaluateStandard)
export(filterTab)
export(filterTabUI)
export(generateMappingList)
-export(getChartFunctions)
export(homeTab)
export(homeTabUI)
+export(makeChartConfig)
export(mappingColumn)
export(mappingColumnUI)
export(mappingDomain)
@@ -31,12 +34,15 @@ export(settingsData)
export(settingsDataUI)
export(settingsMapping)
export(settingsMappingUI)
+import(clisymbols)
import(dplyr)
+import(esquisse)
+import(magrittr)
import(shiny)
+import(tools)
+import(yaml)
importFrom(DT,DTOutput)
importFrom(DT,renderDT)
-importFrom(esquisse,filterDF)
-importFrom(esquisse,filterDF_UI)
importFrom(haven,read_sas)
importFrom(magrittr,"%>%")
importFrom(purrr,keep)
diff --git a/R/app_server.R b/R/app_server.R
new file mode 100644
index 00000000..c41630a2
--- /dev/null
+++ b/R/app_server.R
@@ -0,0 +1,65 @@
+#' Server for the default safetyGraphics shiny app
+#'
+#' This function returns a server function suitable for use in shiny::runApp()
+#'
+#' @param input app input
+#' @param output app output
+#' @param session app session
+#' @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}.
+#' @param domainData named list of data.frames to be loaded in to the app.
+#' @param chartsList list of charts to include in the app
+#'
+#' @export
+app_server <- function(input, output, session, meta, mapping, domainData, charts){
+ server <- function(input, output, session) {
+ #Initialize modules
+
+
+ #TODO: add mapping to function call.
+ current_mapping<-callModule(mappingTab, "mapping", meta, domainData)
+
+ id_col <- reactive({
+ dm<-current_mapping()%>%filter(domain=="dm")
+ id<-dm %>%filter(text_key=="id_col")%>%pull(current)
+ return(id)
+ })
+
+ filtered_data<-callModule(
+ filterTab,
+ "filter",
+ domainData=domainData,
+ filterDomain="dm",
+ id_col=id_col
+ )
+
+ callModule(settingsData, "dataSettings", domains = domainData, filtered=filtered_data)
+ callModule(settingsMapping, "metaSettings", metaIn=meta, mapping=current_mapping)
+ callModule(settingsCharts, "chartSettings",charts = charts)
+ callModule(homeTab, "home")
+
+ #Initialize Chart UI - Adds subtabs to chart menu - this initializes initializes chart UIs
+ charts %>% map(chartsNav)
+
+ #Initialize Chart Servers
+ validDomains <- tolower(names(mapping))
+ charts %>% map(
+ ~callModule(
+ module=chartsTab,
+ id=.x$name,
+ chart=.x,
+ data=filtered_data,
+ mapping=current_mapping
+ )
+ )
+
+ #participant count in header
+ shinyjs::html("header-count", paste(dim(domainData[["dm"]])[1]))
+ shinyjs::html("header-total", paste(dim(domainData[["dm"]])[1]))
+ observe({
+ req(filtered_data)
+ shinyjs::html("header-count", paste0(dim(filtered_data()[["dm"]])[1]))
+ })
+ }
+ return(server)
+}
+
diff --git a/R/app_startup.R b/R/app_startup.R
new file mode 100644
index 00000000..51a6ef9c
--- /dev/null
+++ b/R/app_startup.R
@@ -0,0 +1,50 @@
+#' Startup code for shiny app
+#'
+#' Prepare inputs for safetyGraphics app - run before app is initialized. See ?safetyGraphicsApp for parameter definitions
+#'
+#' @return List of elements for used to initialize the shiny app with the following parameters
+#' \itemize{
+#' \item{"meta"}{ List of configuration metadata }
+#' \item{"charts"}{ List of charts }
+#' \item{"domainData"}{ List of domain level data sets }
+#' \item{"mapping"}{ Initial Data Mapping }
+#' \item{"standards"}{ List of domain level data standards }
+#' }
+#'
+app_startup<-function(domainData=NULL, meta=NULL, charts=NULL, mapping=NULL, chartSettingsPaths=NULL){
+ # Process charts metadata
+ if(is.null(charts)){
+ if(is.null(chartSettingsPaths)){
+ charts <- makeChartConfig()
+ }else{
+ charts <- makeChartConfig(chartSettingsPaths)
+ }
+ }
+
+ # get the data standards
+ standards <- names(domainData) %>% lapply(function(domain){
+ return(detectStandard(domain=domain, data = domainData[[domain]], meta=meta))
+ })
+ names(standards)<-names(domainData)
+
+ # attempt to generate a mapping if none is provided by the user
+ if(is.null(mapping)){
+ mapping_list <- standards %>% lapply(function(standard){
+ return(standard[["mapping"]])
+ })
+ mapping<-bind_rows(mapping_list, .id = "domain")
+ }
+
+ config<-list(
+ meta=meta,
+ charts=charts,
+ domainData=domainData,
+ mapping=mapping,
+ standards=standards
+ )
+
+ # Check config
+ # TODO write some checks to make sure the config is valid.
+
+ return(config)
+}
\ No newline at end of file
diff --git a/R/app_ui.R b/R/app_ui.R
index 3d44908e..67d7c768 100644
--- a/R/app_ui.R
+++ b/R/app_ui.R
@@ -8,39 +8,45 @@
#' @export
app_ui <- function(meta, domainData, mapping, standards){
- ui<-tagList(
- useShinyjs(),
- #add_busy_spinner(spin = "fading-circle", position = "bottom-left", timeout=3000),
- tags$head(
- tags$style(HTML(readLines( paste(.libPaths(),'safetygraphics','safetyGraphics_app', 'www','index.css', sep="/")))),
- tags$link(
- rel = "stylesheet",
- type = "text/css",
- href = "https://use.fontawesome.com/releases/v5.8.1/css/all.css"
- )
- ),
- navbarPage(
- "safetyGraphics",
- id="nav_id",
- tabPanel("Home", icon=icon("home"),homeTabUI("home")),
- navbarMenu('Data',icon=icon("database"),
- tabPanel("Preview", icon=icon("table"), settingsDataUI("dataSettings", domains=domainData)),
- tabPanel("Mapping", icon=icon("map"), mappingTabUI("mapping", meta, domainData, mapping, standards)),
- tabPanel("Filtering", icon=icon("filter"), filterTabUI("filter","dm"))
- ),
- navbarMenu('Charts', icon=icon("chart-bar")),
- tabPanel("Reports", icon=icon("file-alt")),
- navbarMenu('',icon=icon("cog"),
- tabPanel(title = "Metadata", settingsMappingUI("metaSettings")),
- tabPanel(title = "Charts", settingsChartsUI("chartSettings"))
- ),
- tags$script(
- HTML(
+ #read css from pacakge
+ app_css <- HTML(readLines( paste(.libPaths(),'safetyGraphics','safetyGraphics_app', 'www','index.css', sep="/")))
+
+ #script to append population badge nav bar
+ participant_badge<-tags$script(
+ HTML(
"var header = $('.navbar> .container-fluid');
header.append('
');"
- )
- )
- )
+ )
+ )
+
+ #app UI using calls to modules
+ ui<-tagList(
+ useShinyjs(),
+ tags$head(
+ tags$style(app_css),
+ tags$link(
+ rel = "stylesheet",
+ type = "text/css",
+ href = "https://use.fontawesome.com/releases/v5.8.1/css/all.css"
+ )
+ ),
+ navbarPage(
+ "safetyGraphics",
+ id="safetyGraphicsApp",
+ tabPanel("Home", icon=icon("home"),homeTabUI("home")),
+ navbarMenu('Data',icon=icon("database"),
+ tabPanel("Preview", icon=icon("table"), settingsDataUI("dataSettings")),
+ tabPanel("Mapping", icon=icon("map"), mappingTabUI("mapping", meta, domainData, mapping, standards)),
+ tabPanel("Filtering", icon=icon("filter"), filterTabUI("filter","dm"))
+ ),
+ navbarMenu('Charts', icon=icon("chart-bar")),
+ tabPanel("Reports", icon=icon("file-alt")),
+ navbarMenu('',icon=icon("cog"),
+ tabPanel(title = "Metadata", settingsMappingUI("metaSettings")),
+ tabPanel(title = "Charts", settingsChartsUI("chartSettings"))
+ ),
+ participant_badge
+ )
)
return(ui)
}
diff --git a/R/getChartFunctions.R b/R/getChartFunctions.R
deleted file mode 100644
index c09f5fe9..00000000
--- a/R/getChartFunctions.R
+++ /dev/null
@@ -1,44 +0,0 @@
-#' @title Get Chart Functions
-#' @description Function to get functions associated with charts
-#'
-#' @param chartsList List of charts and thier parameters
-#' @param chartSettingsPath path for custom files.
-#'
-#' @return an updated chartsList object with initFunction and chartFunction parameters added as appropriate
-#'
-#' @export
-#'
-getChartFunctions <- function(chartsList, chartSettingsPaths){
- #source all R files in specified settings paths
- for(path in chartSettingsPaths){
- chartSettingsSources <- list.files(path, pattern = "\\.R$", ignore.case=TRUE, full.names=TRUE)
- sapply(chartSettingsSources, source)
- }
-
- for(chartID in names(chartsList)){
- #set default until function is found
- chartsList[[chartID]][["initFunction"]]<-function(data,settings){
- return(list(data=data,settings=settings))
- }
-
- # add init function
- if(exists(paste0(chartID,"_init"))){
- chartsList[[chartID]][["initFunction"]] <- match.fun(paste0(chartID,"_init"))
- }
-
- # add chart function (type == static only)
- chartsList[[chartID]][["chartFunction"]]<-function(data,settings){
- plot(-1:1, -1:1)
- text(0,0,"Charting Function Not Found")
- text(runif(20, -1,1),runif(20, -1,1),":(")
- }
-
- if(exists(chartID)){
- chartsList[[chartID]][["chartFunction"]] <- match.fun(paste0(chartID))
- }else if(exists(paste0(chartID,"_chart"))){
- chartsList[[chartID]][["chartFunction"]] <- match.fun(paste0(chartID,"_chart"))
- }
- #TODO: Add some checks to make sure matches are in fact functions
- }
- return(chartsList)
-}
diff --git a/R/makeChartConfig.R b/R/makeChartConfig.R
new file mode 100644
index 00000000..d5c118d3
--- /dev/null
+++ b/R/makeChartConfig.R
@@ -0,0 +1,97 @@
+#' Make Chart Config
+#'
+#' Converts YAML chart configuration files to an R list and binds workflow functions. See the vignette about creating custom charts for more details.
+#'
+#' @param dirs path to one or more directories containing yaml files (relative to working directory)
+#' @param sourceFiles boolean indicating whether to source all R files found in dirs.
+#'
+#' @import magrittr
+#' @import tools
+#' @import yaml
+#' @import clisymbols
+#'
+#' @return returns a named list of charts derived from YAML files. Each element of the list contains information about a single chart, and has the following parameters:
+#' \itemize{
+#' \item{"name"}{ Name of the chart. Also the name of the element in the list - e.g. charts$aeExplorer$name is "aeExplorer"}
+#' \item{"label"}{ short description of the chart }
+#' \item{"type"}{ type of chart; options are: 'htmlwidget', 'module', 'plot', 'table', 'html' or 'plotly'.}
+#' \item{"domain"}{ data domain. Should correspond to a domain in `meta` or be set to "multiple" }
+#' \item{"package"}{ primary package (if any). Other packages can be loaded directly in workflow functions. }
+#' \item{"path"}{ Path to YAML file}
+#' \item{"workflow"}{ List of functions names used to render chart. See vignette for details. }
+#' \item{"functions"}{ List of functions for use in chart renderering. These functions must be located in the global environment or `package` field of the YAML config. Function names must include either the `name` or `workflow` fields of the YAML config. }
+#' }
+#' @export
+
+makeChartConfig <- function(dirs, sourceFiles=TRUE){
+ # Use the charts settings saved in safetycharts if no path is provided.
+ if(missing(dirs) || is.null(dirs)){
+ #dirs<-paste(.libPaths(),'safetycharts','chartSettings', sep="/")
+ dirs<-paste(.libPaths(),'safetycharts','config', sep="/")
+ }
+
+ if(sourceFiles){
+ r_files<-list.files(
+ dirs,
+ pattern = "\\.R$",
+ ignore.case=TRUE,
+ full.names=TRUE,
+ recursive=TRUE
+ )
+ sapply(r_files, source)
+ }
+
+ yaml_files<-list.files(
+ dirs,
+ pattern = "yaml",
+ recursive = TRUE,
+ full.names = TRUE
+ )
+
+ charts<-lapply(yaml_files, function(path){
+ chart <- read_yaml(path)
+ chart$path <- path
+ chart$name <- path %>% file_path_sans_ext %>% basename
+ return(chart)
+ })
+
+ names(charts) <- yaml_files %>% file_path_sans_ext %>% basename
+
+ message("Found ", length(yaml_files), " config files: ",paste(names(charts),collapse=", "))
+
+ # Bind workflow functions to chart object
+ all_functions <- as.character(lsf.str(".GlobalEnv"))
+ message("Global Functions: ",all_functions)
+ charts <- lapply(charts,
+ function(chart){
+ if(hasName(chart, "package")){
+ package_functions <- as.character(lsf.str(paste0("package:",chart$package)))
+ all_functions<-c(all_functions,package_functions)
+ }
+
+ #search functions that include the charts name or the workflow function names
+ chart_function_names <- c()
+ for(query in c(chart$name, unlist(chart$workflow)) ){
+ matches<-all_functions[str_detect(query, all_functions)]
+ chart_function_names <- c(chart_function_names, matches)
+ }
+
+ chart$functions <- lapply(chart_function_names, match.fun)
+ names(chart$functions) <- chart_function_names
+
+ # check that functions exist for specified workflows
+ workflow_found <- sum(unlist(chart$workflow) %in% chart_function_names)
+ workflow_total <- length(unlist(chart$workflow)[names(unlist(chart$workflow))!="widget"])
+ message<-paste0(chart$name,": Found ", workflow_found, " of ",workflow_total, " workflow functions, and ", length(chart$functions)-workflow_found ," other functions.")
+ if(workflow_found == workflow_total){
+ message(symbol$tick," ",message)
+ }else{
+ message(symbol$cross," ", message)
+ }
+
+ return(chart)
+ }
+ )
+
+ return(charts)
+}
diff --git a/R/mod_chartsNav.R b/R/mod_chartsNav.R
index fd9fe4ee..600a360c 100644
--- a/R/mod_chartsNav.R
+++ b/R/mod_chartsNav.R
@@ -5,21 +5,16 @@
#' @export
#'
-chartsNav <- function(chart, label, package, type){
- #chart$chartFunction <- NULL
- #chart$initFunction <- NULL
+chartsNav <- function(chart){
appendTab(
- inputId = "nav_id",
+ inputId = "safetyGraphicsApp",
menuName = "Charts",
tab = tabPanel(
- title = label,
- value = chart,
+ title = chart$label,
+ value = chart$name,
chartsTabUI(
- chart,
- chart=chart,
- package=package,
- label=label,
- type=type
+ id=chart$name,
+ chart=chart
)
)
)
diff --git a/R/mod_chartsRenderModule.R b/R/mod_chartsRenderModule.R
new file mode 100644
index 00000000..57b2f955
--- /dev/null
+++ b/R/mod_chartsRenderModule.R
@@ -0,0 +1,25 @@
+#' @title Charts Module - render module chart UI
+#' @description Charts Module - sub module for rendering a static chart
+#'
+#' @export
+
+chartsRenderModuleUI <- function(id, customModUI){
+ ns <- NS(id)
+ customModUI(ns("customModUI"))
+}
+
+#' @title Charts Module - render static chart server
+#' @description server for the display of the loaded data
+#'
+#' @param input Shiny input object
+#' @param output Shiny output object
+#' @param session Shiny session object
+#' @param chartFunction function to generate the chart.
+#' @param params parameters to be passed to the widget [REACTIVE]
+#'
+#' @export
+
+chartsRenderModule <- function(input, output, session, serverFunction, params){
+ ns <- session$ns
+ callModule(serverFunction, "customModUI", params)
+}
diff --git a/R/mod_chartsRenderStatic.R b/R/mod_chartsRenderStatic.R
index 1b634a8c..2db49718 100644
--- a/R/mod_chartsRenderStatic.R
+++ b/R/mod_chartsRenderStatic.R
@@ -1,8 +1,6 @@
#' @title Charts Module - render static chart UI
#' @description Charts Module - sub module for rendering a static chart
#'
-#' @import DT
-#'
#' @export
chartsRenderStaticUI <- function(id, type){
diff --git a/R/mod_chartsRenderWidget.R b/R/mod_chartsRenderWidget.R
index 1ecdab31..eaa02cd2 100644
--- a/R/mod_chartsRenderWidget.R
+++ b/R/mod_chartsRenderWidget.R
@@ -8,8 +8,7 @@
#' @export
chartsRenderWidgetUI <- function(id, chart, package){
-
- # shiny output binding for a widget named 'foo'
+ # shiny output binding for a widget
widgetOutput <- function(outputId, width = "100%", height = "400px") {
htmlwidgets::shinyWidgetOutput(outputId, chart, width, height, package=package)
}
@@ -40,8 +39,7 @@ chartsRenderWidget <- function(
settingsToJSON=TRUE
){
ns <- session$ns
-
-
+ message("chartRenderWidget() starting for ", chart)
# shiny output binding
widgetOutput <- function(outputId, width = "100%", height = "400px") {
htmlwidgets::shinyWidgetOutput(outputId, chart, width, height, package=package)
@@ -54,6 +52,7 @@ chartsRenderWidget <- function(
}
widgetParams <- reactive({
+ print("Getting widget params")
widgetParams<-params()
if(settingsToJSON){
widgetParams$settings <- jsonlite::toJSON(
@@ -68,11 +67,12 @@ chartsRenderWidget <- function(
# shiny render function for the widget
output[["widgetChart"]] <- renderWidget({
+ message("Rendering Widget")
htmlwidgets::createWidget(
name = chart,
widgetParams(),
package = package,
sizingPolicy = htmlwidgets::sizingPolicy(viewer.suppress=TRUE, browser.external = TRUE),
- )
+ )
})
}
diff --git a/R/mod_chartsTab.R b/R/mod_chartsTab.R
index cc0d7333..b31f7f87 100644
--- a/R/mod_chartsTab.R
+++ b/R/mod_chartsTab.R
@@ -3,20 +3,19 @@
#'
#' @export
-chartsTabUI <- function(id, chart, package, label=chart, type){
- ns <- NS(id)
- chartID <- ifelse(missing(package), chart, paste0(package,"-",chart))
- h2(paste("Chart:",label))
- if(tolower(type=="module")){
- #render the module UI
- #call the module server
- }else if(tolower(type=="htmlwidget")){
- #render the widget
- chartsRenderWidgetUI(id=ns(chartID),chart=chart,package=package)
- }else{
- #create the static or plotly chart
- chartsRenderStaticUI(id=ns(chartID), type=type)
- }
+chartsTabUI <- function(id, chart){
+ ns <- NS(id)
+ h2(paste("Chart:",chart$label))
+ if(tolower(chart$type=="module")){
+ #render the module UI
+ chartsRenderModuleUI(id=ns("wrap"), chart$functions[[chart$workflow$ui]])
+ }else if(tolower(chart$type=="htmlwidget")){
+ #render the widget
+ chartsRenderWidgetUI(id=ns("wrap"),chart=chart$name, package=chart$package)
+ }else{
+ #create the static or plotly chart
+ chartsRenderStaticUI(id=ns("wrap"), type=chart$type)
+ }
}
#' @title home tab - server
@@ -25,58 +24,71 @@ chartsTabUI <- function(id, chart, package, label=chart, type){
#' @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 type type of chart. Must be 'htmlwidget', 'module', 'plot', 'table', 'html' or 'plotly'. See ?mod_chartRenderer* functions for more details about each chart type.
-#' @param package package containing the widget.
-#' @param chart chart name. Should generally match the name of the function/widget/module to be intiated. See specific renderer modules for more details.
-#' @param chartFunction function to generate static chart.
-#' @param initFunction function called before the chart is generated. The function should take `data` and `settings` as inputs and return `params` which should be a list which is then provided to the widget. If domain is specified, only domain-level information is passed to the init function, otherwise named lists containing information for all domains is provided. The mapping is parsed as a list using `generateMappingList()` before being passed to the init function. By default, init returns an unmodified list of data and settings - possibly subset to the specified domain (e.g. list(data=data, settings=settings))
-#' @param domain data domain. Should correspond to a domain in `meta` or be set to "multiple", in which case, named lists for `data` and `mappings` containing all domain data are used.
+#' @param chart list containing a safetyGraphics chart object. see custom chart vignette for details.
#' @param data named list of current data sets [reactive].
#' @param mapping tibble capturing the current data mappings [reactive].
#'
#' @export
-chartsTab <- function(input, output, session, chart, type, package, chartFunction, initFunction, domain, data, mapping){
- ns <- session$ns
- chartID <- ifelse(missing(package), chart, paste0(package,"-",chart))
-
+#chartsTab <- function(input, output, session, chart, type, package, chartFunction, initFunction, domain, data, mapping){
+chartsTab <- function(input, output, session, chart, data, mapping){
+
+ ns <- session$ns
+ message("chartsTab() starting for ",chart$name)
+
params <- reactive({
-
#convert settings from data frame to list and subset to specified domain (if any)
- settingsList <- safetyGraphics::generateMappingList(mapping(), domain=domain)
-
+ settingsList <- safetyGraphics::generateMappingList(mapping(), domain=chart$domain)
+
#subset data to specific domain (if specified)
- if(domain=="multiple"){
+ if(chart$domain=="multiple"){
domainData <- data()
}else{
- domainData<- data()[[domain]]
+ domainData<- data()[[chart$domain]]
}
+ params <- list(data=domainData, settings=settingsList)
#customize initial the parameters if desired - otherwise pass through domain level data and mapping)
- params <- initFunction(data=domainData, settings=settingsList)
-
+ if(hasName(chart,"functions")){
+ if(hasName(chart$workflow,"init")){
+ message(chart$name, " has an init.")
+ print(chart$functions[chart$workflow$init])
+ params <- do.call(chart$functions[[chart$workflow$init]], params)
+ print(params)
+ }
+ }
return(params)
})
-
- if(tolower(type=="module")){
- #render the module UI
- #call the module server
- }else if(tolower(type=="htmlwidget")){
- callModule(
- chartsRenderWidget,
- chartID,
- chart=chart,
- package=package,
- params=params
- )
- }else{
- #create the static or plotly chart
- callModule(
- chartsRenderStatic,
- chartID,
- chartFunction=chartFunction,
- params=params,
- type=type
- )
- }
+
+ if(tolower(chart$type=="module")){
+ #render the module UI
+ message("chartsTab() is initializing a module at ", ns("wrap"))
+ serverFunction <- chart$functions[[chart$workflow$server]]
+ callModule(
+ module=chartsRenderModule,
+ id="wrap",
+ serverFunction=serverFunction,
+ params=params
+ )
+ }else if(tolower(chart$type=="htmlwidget")){
+ message("chartsTab() is initializing a widget at ", ns("wrap"))
+ message("chart is ", chart$name, "; package is ", chart$package)
+ callModule(
+ module=chartsRenderWidget,
+ id="wrap",
+ chart=chart$name,
+ package=chart$package,
+ params=params
+ )
+ }else{
+ #create the static or plotly chart
+ chartFunction <- chart$functions[[chart$workflow$main]]
+ callModule(
+ module=chartsRenderStatic,
+ id="wrap",
+ chartFunction=chartFunction,
+ params=params,
+ type=chart$type
+ )
+ }
}
\ No newline at end of file
diff --git a/R/mod_filterTab.R b/R/mod_filterTab.R
index d6d40a2e..5c316396 100644
--- a/R/mod_filterTab.R
+++ b/R/mod_filterTab.R
@@ -3,7 +3,7 @@
#'
#' @param filterDomain data set for the domain
#'
-#' @importFrom esquisse filterDF_UI
+#' @import esquisse
#' @importFrom shiny dataTableOutput
#'
#' @export
@@ -50,7 +50,7 @@ filterTabUI <- function(id, filterDomain = "dm"){
#'
#' @return filtered data set
#'
-#' @importFrom esquisse filterDF
+#' @import esquisse
#' @importFrom shinyWidgets progressBar updateProgressBar
#' @importFrom shiny renderDataTable
#'
@@ -71,7 +71,7 @@ filterTab <- function(input, output, session, domainData, filterDomain, id_col){
})
)
- observeEvent(res_filter$data_filtered(), {
+ observeEvent(res_filter$data_filtered(), {
updateProgressBar(
session = session, id = "pbar",
value = nrow(res_filter$data_filtered()), total = nrow(raw)
diff --git a/R/mod_settingsData.R b/R/mod_settingsData.R
index 57eb249f..c5cbaffa 100644
--- a/R/mod_settingsData.R
+++ b/R/mod_settingsData.R
@@ -7,17 +7,12 @@
#' @export
-settingsDataUI <- function(id, domains){
+settingsDataUI <- function(id){
ns <- NS(id)
- names(domains) %>% map(function(domain){
- return(
- list(
- h1(paste0("Domain: ", domain)),
- DTOutput(ns(domain))
- )
- )
-
- })
+ div(
+ h2("Data Domain Previews"),
+ uiOutput(ns('previews'))
+ )
}
#' @title Settings Module - data details - server
@@ -27,12 +22,26 @@ settingsDataUI <- function(id, domains){
#' @param output Shiny output object
#' @param session Shiny session object
#' @param domains named list of the data.frames for each domain
-#' #'
+#'
#' @export
settingsData <- function(input, output, session, domains, filtered){
ns <- session$ns
- for(domain in names(domains)){
+ #Set up tabs
+ output$previews <- renderUI({
+ tabs <- lapply(names(domains),function(domain){
+ tabPanel(domain,
+ div(
+ #h3(paste0("Note: Showing filtered data. X of X rows displayed for the X selected participants.")),
+ DTOutput(ns(domain))
+ )
+ )
+ })
+ do.call(tabsetPanel, tabs)
+ })
+
+ # Draw the tables
+ lapply(names(domains), function(domain){
output[[domain]] <- renderDT({
DT::datatable(
domains[[domain]],
@@ -41,10 +50,5 @@ settingsData <- function(input, output, session, domains, filtered){
class="compact"
)
})
- }
-
- #NOTE: There is no real need for this to be reactive right now, but in this is just a bit of future proofing for when data is more dynamic.
-
- return(reactive({domains}))
-
+ })
}
\ No newline at end of file
diff --git a/R/safetyGraphicsApp.R b/R/safetyGraphicsApp.R
index 99246706..b9481ace 100644
--- a/R/safetyGraphicsApp.R
+++ b/R/safetyGraphicsApp.R
@@ -1,11 +1,10 @@
#' Run the interactive safety graphics app
#'
-#' @param maxFileSize maximum file size in MB allowed for file upload
#' @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}.
#' @param domainData named list of data.frames to be loaded in to the app.
#' @param charts data.frame of charts to be used in the app
#' @param mapping data.frame specifying the initial values for each data mapping. If no mapping is provided, the app will attempt to generate one via \code{detectStandard()}
-#' @param settingsPath path where customization functions are saved relative to your working directory. All charts can have itialization (e.g. [chart]Init.R) and static charts can have charting functions (e.g. [chart]Chart.R). All R files in this folder are sourced and files with the correct naming convention are linked to the chart. See the Custom Charts vignette for more details.
+#' @param chartSettingsPaths path(s) where customization functions are saved relative to your working directory. All charts can have itialization (e.g. [chart]Init.R) and static charts can have charting functions (e.g. [chart]Chart.R). All R files in this folder are sourced and files with the correct naming convention are linked to the chart. See the Custom Charts vignette for more details.
#'
#' @import shiny
#' @importFrom shinyjs useShinyjs html
@@ -19,102 +18,22 @@
#' @export
safetyGraphicsApp <- function(
- maxFileSize = NULL,
- meta = safetyGraphics::meta,
domainData=list(
labs=safetyGraphics::labs,
aes=safetyGraphics::aes,
dm=safetyGraphics::dm
),
- charts=safetyGraphics::charts,
+ meta = safetyGraphics::meta,
+ charts=NULL,
mapping=NULL,
chartSettingsPaths = NULL
){
- #increase maximum file upload limit
- if(!is.null(maxFileSize)){
- options(shiny.maxRequestSize=(maxFileSize*1024^2))
- }
-
- # load files from default location in the package (for default charts)
- defaultPath <- paste(.libPaths(),'safetygraphics','chartSettings', sep="/")
- if(!is.null(chartSettingsPaths)){
- chartSettingsPaths <- paste(getwd(),chartSettingsPaths,sep="/")
- }
- chartSettingPaths <- c(defaultPath, chartSettingsPaths)
-
- # get the data standards
- standards <- names(domainData) %>% lapply(function(domain){
- return(detectStandard(domain=domain, data = domainData[[domain]], meta=meta))
- })
- names(standards)<-names(domainData)
-
- # attempt to generate a mapping if none is provided by the user
- if(is.null(mapping)){
- mapping_list <- standards %>% lapply(function(standard){
- return(standard[["mapping"]])
- })
- mapping<-bind_rows(mapping_list, .id = "domain")
- }
+ config <- app_startup(domainData, meta, charts, mapping, chartSettingsPaths)
- #convert charts data frame to a list and bind functions
- chartsList <- setNames(transpose(charts), charts$chart)
- chartsList <- getChartFunctions(chartsList, chartSettingPaths)
-
app <- shinyApp(
- ui = app_ui(meta, domainData, mapping, standards),
- server = function(input, output) {
- #Initialize modules
- current_mapping<-callModule(mappingTab, "mapping", meta, domainData)
-
- id_col <- reactive({
- dm<-current_mapping()%>%filter(domain=="dm")
- id<-dm %>%filter(text_key=="id_col")%>%pull(current)
- return(id)
- })
-
-
- filtered_data<-callModule(
- filterTab,
- "filter",
- domainData=domainData,
- filterDomain="dm",
- id_col=id_col
- )
-
- callModule(settingsData, "dataSettings", domains = domainData, filtered=filtered_data)
- callModule(settingsMapping, "metaSettings", metaIn=meta, mapping=current_mapping)
- callModule(settingsCharts, "chartSettings",charts = chartsList)
- callModule(homeTab, "home")
-
- #Initialize Chart UI - Adds subtabs to chart menu and initializes chart UIs
- chartsList %>% map(~chartsNav(chart=.x$chart, label=.x$label, type=.x$type, package=.x$package))
-
- #Initialize Chart Servers
- validDomains <- tolower(names(mapping))
- chartsList %>% map(
- ~callModule(
- chartsTab,
- .x$chart,
- chart=.x$chart,
- chartFunction=.x$chartFunction,
- initFunction=.x$initFunction,
- type=.x$type,
- package=.x$package,
- domain=.x$domain,
- data=filtered_data,
- mapping=current_mapping
- )
- )
-
- #participant count in header
- shinyjs::html("header-count", paste(dim(domainData[["dm"]])[1]))
- shinyjs::html("header-total", paste(dim(domainData[["dm"]])[1]))
- observe({
- req(filtered_data)
- shinyjs::html("header-count", paste0(dim(filtered_data()[["dm"]])[1]))
- })
- }
+ ui = app_ui(config$meta, config$domainData, config$mapping, config$standards),
+ server = app_server(input, output, session, config$meta, config$mapping, config$domainData, config$charts)
)
runApp(app, launch.browser = TRUE)
}
diff --git a/inst/chartSettings/aeExplorer_init.R b/inst/chartSettings/aeExplorer_init.R
deleted file mode 100644
index c14c4249..00000000
--- a/inst/chartSettings/aeExplorer_init.R
+++ /dev/null
@@ -1,37 +0,0 @@
-library(dplyr)
-
-aeExplorer_init<- function(data, settings){
- print(data)
- print(settings)
- dm_sub <- data$dm %>% select(settings[["dm"]][["id_col"]], settings[["dm"]][["treatment_col"]])
- anly <- dm_sub %>% left_join(data$aes)
-
- print(head(anly))
-
- settings<-c(settings$aes, settings$labs)
-
- settings$variables<-list(
- major=settings[["bodsys_col"]],
- minor=settings[["term_col"]],
- group=settings[["trt_col"]],
- id=paste0(settings[["id_col"]]),
- filters=list(),
- details=list()
- )
-
- settings$variableOptions<-list(
- group=c(
- settings[["treatment_values--group1"]],
- settings[["treatment_values--group2"]]
- )
- )
-
- settings$defaults = list(
- placeholderFlag = list(
- valueCol = settings[["bodsys_col"]],
- values = c("", NA, NULL)
- )
- )
- View(settings)
- return(list(data=anly,settings=settings))
-}
\ No newline at end of file
diff --git a/inst/config/mappings/aes.yaml b/inst/config/mappings/aes.yaml
new file mode 100644
index 00000000..9a5ac690
--- /dev/null
+++ b/inst/config/mappings/aes.yaml
@@ -0,0 +1 @@
+- text_key: id_col\n col_key: id_col\n field_key: .na.character\n type: column\n label: ID column\n description: Unique subject identifier variable name.\n multiple: no\n standard_adam: USUBJID\n standard_sdtm: USUBJID\n- text_key: seq_col\n col_key: seq_col\n field_key: .na.character\n type: column\n label: Sequence column\n description: Event sequence number variable name\n multiple: no\n standard_adam: ASEQ\n standard_sdtm: AESEQ\n- text_key: stdy_col\n col_key: stdy_col\n field_key: .na.character\n type: column\n label: AE Start day column\n description: Event start day variable name\n multiple: no\n standard_adam: ASTDY\n standard_sdtm: AESTDY\n- text_key: endy_col\n col_key: endy_col\n field_key: .na.character\n type: column\n label: AE End day column\n description: Event end day variable name\n multiple: no\n standard_adam: AENDY\n standard_sdtm: AEENDY\n- text_key: term_col\n col_key: term_col\n field_key: .na.character\n type: column\n label: Preferred Term Column\n description: verbatim adverse event text variable name\n multiple: no\n standard_adam: AETERM\n standard_sdtm: AETERM\n- text_key: bodsys_col\n col_key: bodsys_col\n field_key: .na.character\n type: column\n label: AE Body System\n description: AE Body System\n multiple: no\n standard_adam: AEBODSYS\n standard_sdtm: AEBODSYS\n- text_key: detail_col\n col_key: detail_col\n field_key: .na.character\n type: column\n label: Details\n description: Details\n multiple: yes\n standard_adam: .na.character\n standard_sdtm: .na.character\n- text_key: filter_cols\n col_key: filter_cols\n field_key: .na.character\n type: column\n label: Filters\n description: Filters\n multiple: yes\n standard_adam: .na.character\n standard_sdtm: .na.character\n
\ No newline at end of file
diff --git a/inst/safetyGraphics_app/www/index.css b/inst/safetyGraphics_app/www/index.css
index 17769bf3..1971b618 100644
--- a/inst/safetyGraphics_app/www/index.css
+++ b/inst/safetyGraphics_app/www/index.css
@@ -44,7 +44,6 @@
border-color:green;
}
-
table.dataTable tr > td:last-of-type, table.dataTable tr > th:last-of-type {
border-left:2px solid black;
background:#d0d1e6;
@@ -54,3 +53,7 @@ table.dataTable tr > td:last-of-type, table.dataTable tr > th:last-of-type {
float:right;
margin-top:1em;
}
+
+#dataSettings-previews .nav-tabs{
+ margin-bottom: 1em;
+}
\ No newline at end of file
diff --git a/man/aes.Rd b/man/aes.Rd
index 702a48ed..c289dbd6 100644
--- a/man/aes.Rd
+++ b/man/aes.Rd
@@ -7,9 +7,9 @@
\format{
A data frame with 10288 rows and 46 variables.
\describe{
- \item{STUDYID}{Study Identifier}
- \item{SUBJID}{Subject Identifier for the Study}
- \item{USUBJID}{Unique Subject Identifier}
+\item{STUDYID}{Study Identifier}
+\item{SUBJID}{Subject Identifier for the Study}
+\item{USUBJID}{Unique Subject Identifier}
}
}
\source{
diff --git a/man/app_server.Rd b/man/app_server.Rd
new file mode 100644
index 00000000..d8952393
--- /dev/null
+++ b/man/app_server.Rd
@@ -0,0 +1,24 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/app_server.R
+\name{app_server}
+\alias{app_server}
+\title{Server for the default safetyGraphics shiny app}
+\usage{
+app_server(input, output, session, meta, mapping, domainData, charts)
+}
+\arguments{
+\item{input}{app input}
+
+\item{output}{app output}
+
+\item{session}{app session}
+
+\item{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}.}
+
+\item{domainData}{named list of data.frames to be loaded in to the app.}
+
+\item{chartsList}{list of charts to include in the app}
+}
+\description{
+This function returns a server function suitable for use in shiny::runApp()
+}
diff --git a/man/app_startup.Rd b/man/app_startup.Rd
new file mode 100644
index 00000000..d6a45b9c
--- /dev/null
+++ b/man/app_startup.Rd
@@ -0,0 +1,27 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/app_startup.R
+\name{app_startup}
+\alias{app_startup}
+\title{Startup code for shiny app}
+\usage{
+app_startup(
+ domainData = NULL,
+ meta = NULL,
+ charts = NULL,
+ mapping = NULL,
+ chartSettingsPaths = NULL
+)
+}
+\value{
+List of elements for used to initialize the shiny app with the following parameters
+\itemize{
+\item{"meta"}{ List of configuration metadata }
+\item{"charts"}{ List of charts }
+\item{"domainData"}{ List of domain level data sets }
+\item{"mapping"}{ Initial Data Mapping }
+\item{"standards"}{ List of domain level data standards }
+}
+}
+\description{
+Prepare inputs for safetyGraphics app - run before app is initialized. See ?safetyGraphicsApp for parameter definitions
+}
diff --git a/man/chartsNav.Rd b/man/chartsNav.Rd
index 9d11b303..bad6a978 100644
--- a/man/chartsNav.Rd
+++ b/man/chartsNav.Rd
@@ -4,7 +4,7 @@
\alias{chartsNav}
\title{Add a navbar tab that initializes the Chart Module UI}
\usage{
-chartsNav(chart, label, package, type)
+chartsNav(chart)
}
\arguments{
\item{chart}{chart metadata}
diff --git a/man/chartsRenderModule.Rd b/man/chartsRenderModule.Rd
new file mode 100644
index 00000000..0c35557b
--- /dev/null
+++ b/man/chartsRenderModule.Rd
@@ -0,0 +1,22 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mod_chartsRenderModule.R
+\name{chartsRenderModule}
+\alias{chartsRenderModule}
+\title{Charts Module - render static chart server}
+\usage{
+chartsRenderModule(input, output, session, serverFunction, params)
+}
+\arguments{
+\item{input}{Shiny input object}
+
+\item{output}{Shiny output object}
+
+\item{session}{Shiny session object}
+
+\item{params}{parameters to be passed to the widget \link{REACTIVE}}
+
+\item{chartFunction}{function to generate the chart.}
+}
+\description{
+server for the display of the loaded data
+}
diff --git a/man/chartsRenderModuleUI.Rd b/man/chartsRenderModuleUI.Rd
new file mode 100644
index 00000000..7ab6b300
--- /dev/null
+++ b/man/chartsRenderModuleUI.Rd
@@ -0,0 +1,11 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mod_chartsRenderModule.R
+\name{chartsRenderModuleUI}
+\alias{chartsRenderModuleUI}
+\title{Charts Module - render module chart UI}
+\usage{
+chartsRenderModuleUI(id, customModUI)
+}
+\description{
+Charts Module - sub module for rendering a static chart
+}
diff --git a/man/chartsRenderStatic.Rd b/man/chartsRenderStatic.Rd
index 2c15ffc2..0222b97e 100644
--- a/man/chartsRenderStatic.Rd
+++ b/man/chartsRenderStatic.Rd
@@ -4,7 +4,7 @@
\alias{chartsRenderStatic}
\title{Charts Module - render static chart server}
\usage{
-chartsRenderStatic(input, output, session, chartFunction, params)
+chartsRenderStatic(input, output, session, chartFunction, params, type)
}
\arguments{
\item{input}{Shiny input object}
@@ -15,7 +15,7 @@ chartsRenderStatic(input, output, session, chartFunction, params)
\item{chartFunction}{function to generate the chart.}
-\item{params}{parameters to be passed to the widget [REACTIVE]}
+\item{params}{parameters to be passed to the widget \link{REACTIVE}}
}
\description{
server for the display of the loaded data
diff --git a/man/chartsRenderStaticUI.Rd b/man/chartsRenderStaticUI.Rd
index d35bc513..3f383eef 100644
--- a/man/chartsRenderStaticUI.Rd
+++ b/man/chartsRenderStaticUI.Rd
@@ -4,7 +4,7 @@
\alias{chartsRenderStaticUI}
\title{Charts Module - render static chart UI}
\usage{
-chartsRenderStaticUI(id)
+chartsRenderStaticUI(id, type)
}
\description{
Charts Module - sub module for rendering a static chart
diff --git a/man/chartsRenderWidget.Rd b/man/chartsRenderWidget.Rd
index 149b3fe9..43d21b96 100644
--- a/man/chartsRenderWidget.Rd
+++ b/man/chartsRenderWidget.Rd
@@ -25,7 +25,7 @@ chartsRenderWidget(
\item{package}{package containing the widget. Note that package name is required for htmlwidgets.}
-\item{params}{parameters to be passed to the widget [REACTIVE]}
+\item{params}{parameters to be passed to the widget \link{REACTIVE}}
\item{settingsToJSON}{convert param$settings to json? Default = TRUE}
}
diff --git a/man/chartsTab.Rd b/man/chartsTab.Rd
index 7e266ea9..f63b4993 100644
--- a/man/chartsTab.Rd
+++ b/man/chartsTab.Rd
@@ -4,19 +4,7 @@
\alias{chartsTab}
\title{home tab - server}
\usage{
-chartsTab(
- input,
- output,
- session,
- chart,
- type,
- package,
- chartFunction,
- initFunction,
- domain,
- data,
- mapping
-)
+chartsTab(input, output, session, chart, data, mapping)
}
\arguments{
\item{input}{Input objects from module namespace}
@@ -25,21 +13,11 @@ chartsTab(
\item{session}{An environment that can be used to access information and functionality relating to the session}
-\item{chart}{chart name. Should generally match the name of the function/widget/module to be intiated. See specific renderer modules for more details.}
+\item{chart}{list containing a safetyGraphics chart object. see custom chart vignette for details.}
-\item{type}{type of chart. Must be 'htmlwidget', 'module', 'static' or 'plotly'. See ?mod_chartRenderer{{type}} for more details about each chart type}
+\item{data}{named list of current data sets \link{reactive}.}
-\item{package}{package containing the widget.}
-
-\item{chartFunction}{function to generate static chart.}
-
-\item{initFunction}{function called before the chart is generated. The function should take `data` and `settings` as inputs and return `params` which should be a list which is then provided to the widget. If domain is specified, only domain-level information is passed to the init function, otherwise named lists containing information for all domains is provided. The mapping is parsed as a list using `generateMappingList()` before being passed to the init function. By default, init returns an unmodified list of data and settings - possibly subset to the specified domain (e.g. list(data=data, settings=settings))}
-
-\item{domain}{data domain. Should correspond to a domain in `meta` or be set to "multiple" to named lists for data and mappings containing domains.}
-
-\item{data}{named list of current data sets [reactive].}
-
-\item{mapping}{named list of the current data mappings [reactive].}
+\item{mapping}{tibble capturing the current data mappings \link{reactive}.}
}
\description{
server for the display of the chart tab
diff --git a/man/chartsTabUI.Rd b/man/chartsTabUI.Rd
index 6b6663ec..6b26142f 100644
--- a/man/chartsTabUI.Rd
+++ b/man/chartsTabUI.Rd
@@ -4,7 +4,7 @@
\alias{chartsTabUI}
\title{Charts Tab}
\usage{
-chartsTabUI(id, chart, package, label = chart, type)
+chartsTabUI(id, chart)
}
\description{
Charting module
diff --git a/man/detectStandard.Rd b/man/detectStandard.Rd
index 439314df..6f5fe95f 100644
--- a/man/detectStandard.Rd
+++ b/man/detectStandard.Rd
@@ -20,7 +20,7 @@ A data frame describing the detected standard for each \code{"text_key"} in the
This function attempts to detect the clinical data standard used in a given R data frame.
}
\details{
-This function compares the columns in the provided \code{"data"} with the required columns for a given data standard/domain combination. The function is designed to work with the SDTM and ADaM CDISC() standards for clinical trial data by default. Additional standards can be added by modifying the \code{"meta"} data set included as part of this package.
+This function compares the columns in the provided \code{"data"} with the required columns for a given data standard/domain combination. The function is designed to work with the SDTM and ADaM CDISC(\url{https://www.cdisc.org/}) standards for clinical trial data by default. Additional standards can be added by modifying the \code{"meta"} data set included as part of this package.
}
\examples{
detectStandard(data=safetyGraphics::aes) #aes domain evaluated by default
diff --git a/man/dm.Rd b/man/dm.Rd
index 9f100d05..9f95453d 100644
--- a/man/dm.Rd
+++ b/man/dm.Rd
@@ -7,9 +7,9 @@
\format{
A data frame with 306 rows and 25 variables.
\describe{
- \item{STUDYID}{Study Identifier}
- \item{SUBJID}{Subject Identifier for the Study}
- \item{USUBJID}{Unique Subject Identifier}
+\item{STUDYID}{Study Identifier}
+\item{SUBJID}{Subject Identifier for the Study}
+\item{USUBJID}{Unique Subject Identifier}
}
}
\source{
diff --git a/man/generateMappingList.Rd b/man/generateMappingList.Rd
index 58d9e4c1..604406a6 100644
--- a/man/generateMappingList.Rd
+++ b/man/generateMappingList.Rd
@@ -4,10 +4,10 @@
\alias{generateMappingList}
\title{Convert mapping data.frame to a list}
\usage{
-generateMappingList(settingsDF, domain)
+generateMappingList(settingsDF, domain, pull = FALSE)
}
\arguments{
-\item{domain}{mapping domain to return (returns all domains as a named list by default)}
+\item{domain}{call pull() the value for each parameter - needed for testing only. default: FALSE}
\item{mappingDF}{data frame containing current mapping}
}
diff --git a/man/getChartFunctions.Rd b/man/getChartFunctions.Rd
deleted file mode 100644
index d485fe59..00000000
--- a/man/getChartFunctions.Rd
+++ /dev/null
@@ -1,19 +0,0 @@
-% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/getChartFunctions.R
-\name{getChartFunctions}
-\alias{getChartFunctions}
-\title{Get Chart Functions}
-\usage{
-getChartFunctions(chartsList, chartSettingsPaths)
-}
-\arguments{
-\item{chartsList}{List of charts and thier parameters}
-
-\item{chartSettingsPath}{path for custom files.}
-}
-\value{
-an updated chartsList object with initFunction and chartFunction parameters added as appropriate
-}
-\description{
-Function to get functions associated with charts
-}
diff --git a/man/labs.Rd b/man/labs.Rd
index 3e869278..1068f25c 100644
--- a/man/labs.Rd
+++ b/man/labs.Rd
@@ -7,52 +7,52 @@
\format{
A data frame with 10288 rows and 46 variables.
\describe{
- \item{STUDYID}{Study Identifier}
- \item{SUBJID}{Subject Identifier for the Study}
- \item{USUBJID}{Unique Subject Identifier}
- \item{TRTP}{Planned Treatment}
- \item{TRTPN}{Planned Treatment (N)}
- \item{TRTA}{Actual Treatment}
- \item{TRTAN}{Actual Treatment (N)}
- \item{TRTSDT}{Date of First Exposure to Treatment}
- \item{TRTEDT}{Date of Last Exposure to Treatment}
- \item{AGE}{Age}
- \item{AGEGR1}{Age Group}
- \item{AGEGR1N}{Age Group (N)}
- \item{RACE}{Race}
- \item{RACEN}{Race (N)}
- \item{SEX}{Sex}
- \item{COMP24FL}{Completers Flag}
- \item{DSRAEFL}{Discontinued due to AE?}
- \item{SAFFL}{Safety Population Flag}
- \item{AVISIT}{Analysis Visit}
- \item{AVISITN}{Analysis Visit (N)}
- \item{ADY}{Analysis Relative Day}
- \item{ADT}{Analysis Relative Date}
- \item{VISIT}{Visit}
- \item{VISITNUM}{Visit (N)}
- \item{PARAM}{Parameter}
- \item{PARAMCD}{Parameter Code}
- \item{PARAMN}{Parameter (N)}
- \item{PARCAT1}{Parameter Category}
- \item{AVAL}{Analysis Value}
- \item{BASE}{Baseline Value}
- \item{CHG}{Change from Baseline}
- \item{A1LO}{Analysis Normal Range Lower Limit}
- \item{A1HI}{Analysis Normal Range Upper Limit}
- \item{R2A1LO}{Ratio to Low limit of Analysis Range}
- \item{R2A1HI}{Ratio to High limit of Analysis Range}
- \item{BR2A1LO}{Base Ratio to Analysis Range 1 Lower Lim}
- \item{BR2A1HI}{Base Ratio to Analysis Range 1 Upper Lim}
- \item{ANL01FL}{Analysis Population Flag}
- \item{ALBTRVAL}{Amount Threshold Range}
- \item{ANRIND}{Analysis Reference Range Indicator}
- \item{BNRIND}{Baseline Reference Range Indicator}
- \item{ABLFL}{Baseline Record Flag}
- \item{AENTMTFL}{Analysis End Date Flag}
- \item{LBSEQ}{Lab Sequence Number }
- \item{LBNRIND}{Reference Range Indicator}
- \item{LBSTRESN}{Numeric Result/Finding in Std Units}
+\item{STUDYID}{Study Identifier}
+\item{SUBJID}{Subject Identifier for the Study}
+\item{USUBJID}{Unique Subject Identifier}
+\item{TRTP}{Planned Treatment}
+\item{TRTPN}{Planned Treatment (N)}
+\item{TRTA}{Actual Treatment}
+\item{TRTAN}{Actual Treatment (N)}
+\item{TRTSDT}{Date of First Exposure to Treatment}
+\item{TRTEDT}{Date of Last Exposure to Treatment}
+\item{AGE}{Age}
+\item{AGEGR1}{Age Group}
+\item{AGEGR1N}{Age Group (N)}
+\item{RACE}{Race}
+\item{RACEN}{Race (N)}
+\item{SEX}{Sex}
+\item{COMP24FL}{Completers Flag}
+\item{DSRAEFL}{Discontinued due to AE?}
+\item{SAFFL}{Safety Population Flag}
+\item{AVISIT}{Analysis Visit}
+\item{AVISITN}{Analysis Visit (N)}
+\item{ADY}{Analysis Relative Day}
+\item{ADT}{Analysis Relative Date}
+\item{VISIT}{Visit}
+\item{VISITNUM}{Visit (N)}
+\item{PARAM}{Parameter}
+\item{PARAMCD}{Parameter Code}
+\item{PARAMN}{Parameter (N)}
+\item{PARCAT1}{Parameter Category}
+\item{AVAL}{Analysis Value}
+\item{BASE}{Baseline Value}
+\item{CHG}{Change from Baseline}
+\item{A1LO}{Analysis Normal Range Lower Limit}
+\item{A1HI}{Analysis Normal Range Upper Limit}
+\item{R2A1LO}{Ratio to Low limit of Analysis Range}
+\item{R2A1HI}{Ratio to High limit of Analysis Range}
+\item{BR2A1LO}{Base Ratio to Analysis Range 1 Lower Lim}
+\item{BR2A1HI}{Base Ratio to Analysis Range 1 Upper Lim}
+\item{ANL01FL}{Analysis Population Flag}
+\item{ALBTRVAL}{Amount Threshold Range}
+\item{ANRIND}{Analysis Reference Range Indicator}
+\item{BNRIND}{Baseline Reference Range Indicator}
+\item{ABLFL}{Baseline Record Flag}
+\item{AENTMTFL}{Analysis End Date Flag}
+\item{LBSEQ}{Lab Sequence Number }
+\item{LBNRIND}{Reference Range Indicator}
+\item{LBSTRESN}{Numeric Result/Finding in Std Units}
}
}
\source{
diff --git a/man/makeChartConfig.Rd b/man/makeChartConfig.Rd
new file mode 100644
index 00000000..89bed087
--- /dev/null
+++ b/man/makeChartConfig.Rd
@@ -0,0 +1,29 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/makeChartConfig.R
+\name{makeChartConfig}
+\alias{makeChartConfig}
+\title{Make Chart Config}
+\usage{
+makeChartConfig(dirs, sourceFiles = TRUE)
+}
+\arguments{
+\item{dirs}{path to one or more directories containing yaml files (relative to working directory)}
+
+\item{sourceFiles}{boolean indicating whether to source all R files found in dirs.}
+}
+\value{
+returns a named list of charts derived from YAML files. Each element of the list contains information about a single chart, and has the following parameters:
+\itemize{
+\item{"name"}{ Name of the chart. Also the name of the element in the list - e.g. charts$aeExplorer$name is "aeExplorer"}
+\item{"label"}{ short description of the chart }
+\item{"type"}{ type of chart; options are: 'htmlwidget', 'module', 'plot', 'table', 'html' or 'plotly'.}
+\item{"domain"}{ data domain. Should correspond to a domain in \code{meta} or be set to "multiple" }
+\item{"package"}{ primary package (if any). Other packages can be loaded directly in workflow functions. }
+\item{"path"}{ Path to YAML file}
+\item{"workflow"}{ List of functions names used to render chart. See vignette for details. }
+\item{"functions"}{ List of functions for use in chart renderering. These functions must be located in the global environment or \code{package} field of the YAML config. Function names must include either the \code{name} or \code{workflow} fields of the YAML config. }
+}
+}
+\description{
+Converts YAML chart configuration files to an R list and binds workflow functions. See the vignette about creating custom charts for more details.
+}
diff --git a/man/meta.Rd b/man/meta.Rd
index 7d42e6bd..801bfebe 100644
--- a/man/meta.Rd
+++ b/man/meta.Rd
@@ -7,16 +7,16 @@
\format{
A data frame with 31 rows and 7 columns
\describe{
- \item{domain}{Data domain}
- \item{text_key}{Text key indicating the setting name. \code{'--'} delimiter indicates a field level data mapping}
- \item{col_key}{Key for the column mapping}
- \item{field_key}{Key for the field mapping (if any)}
- \item{type}{type of mapping - "field" or "column"}
- \item{label}{Label}
- \item{description}{Description}
- \item{multiple}{Mapping supports multiple columns/fields }
- \item{standard_adam}{Default values for the ADaM data standard}
- \item{standard_sdtm}{Default values for the SDTM data standard}
+\item{domain}{Data domain}
+\item{text_key}{Text key indicating the setting name. \code{'--'} delimiter indicates a field level data mapping}
+\item{col_key}{Key for the column mapping}
+\item{field_key}{Key for the field mapping (if any)}
+\item{type}{type of mapping - "field" or "column"}
+\item{label}{Label}
+\item{description}{Description}
+\item{multiple}{Mapping supports multiple columns/fields }
+\item{standard_adam}{Default values for the ADaM data standard}
+\item{standard_sdtm}{Default values for the SDTM data standard}
}
}
\source{
diff --git a/man/safetyGraphicsApp.Rd b/man/safetyGraphicsApp.Rd
index 282f3bea..d54c38e3 100644
--- a/man/safetyGraphicsApp.Rd
+++ b/man/safetyGraphicsApp.Rd
@@ -5,27 +5,24 @@
\title{Run the interactive safety graphics app}
\usage{
safetyGraphicsApp(
- maxFileSize = NULL,
- meta = safetyGraphics::meta,
domainData = list(labs = safetyGraphics::labs, aes = safetyGraphics::aes, dm =
safetyGraphics::dm),
- charts = safetyGraphics::charts,
+ meta = safetyGraphics::meta,
+ charts = NULL,
mapping = NULL,
chartSettingsPaths = NULL
)
}
\arguments{
-\item{maxFileSize}{maximum file size in MB allowed for file upload}
+\item{domainData}{named list of data.frames to be loaded in to the app.}
\item{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}.}
-\item{domainData}{named list of data.frames to be loaded in to the app.}
-
\item{charts}{data.frame of charts to be used in the app}
\item{mapping}{data.frame specifying the initial values for each data mapping. If no mapping is provided, the app will attempt to generate one via \code{detectStandard()}}
-\item{settingsPath}{path where customization functions are saved relative to your working directory. All charts can have itialization (e.g. [chart]Init.R) and static charts can have charting functions (e.g. [chart]Chart.R). All R files in this folder are sourced and files with the correct naming convention are linked to the chart. See the Custom Charts vignette for more details.}
+\item{chartSettingsPaths}{path(s) where customization functions are saved relative to your working directory. All charts can have itialization (e.g. \link{chart}Init.R) and static charts can have charting functions (e.g. \link{chart}Chart.R). All R files in this folder are sourced and files with the correct naming convention are linked to the chart. See the Custom Charts vignette for more details.}
}
\description{
Run the interactive safety graphics app
diff --git a/man/settingsData.Rd b/man/settingsData.Rd
index d2210eea..fe6554c1 100644
--- a/man/settingsData.Rd
+++ b/man/settingsData.Rd
@@ -13,8 +13,7 @@ settingsData(input, output, session, domains, filtered)
\item{session}{Shiny session object}
-\item{domains}{named list of the data.frames for each domain
-#'}
+\item{domains}{named list of the data.frames for each domain}
}
\description{
server for the display of the loaded data
diff --git a/man/settingsDataUI.Rd b/man/settingsDataUI.Rd
index 435571e4..1c50c9b5 100644
--- a/man/settingsDataUI.Rd
+++ b/man/settingsDataUI.Rd
@@ -4,7 +4,7 @@
\alias{settingsDataUI}
\title{Settings Module - data details}
\usage{
-settingsDataUI(id, domains)
+settingsDataUI(id)
}
\arguments{
\item{domains}{named list of the data.frames for each domain}
diff --git a/tests/testthat/module_examples/chartsRenderStatic/app.R b/tests/testthat/module_examples/chartsRenderStatic/app.R
index 32620db8..f16e5d78 100644
--- a/tests/testthat/module_examples/chartsRenderStatic/app.R
+++ b/tests/testthat/module_examples/chartsRenderStatic/app.R
@@ -6,6 +6,7 @@ library(dplyr)
data <- list(labs=safetyGraphics::labs, aes=safetyGraphics::aes)
mapping <- list(measure_col="PARAM", value_col="AVAL")
params<- reactive({list(data=data,settings=mapping)})
+
# Test app code
ui <- tagList(
tags$head(
diff --git a/tests/testthat/module_examples/chartsRenderWidget/app.R b/tests/testthat/module_examples/chartsRenderWidget/app.R
index ce665c72..fe5b3095 100644
--- a/tests/testthat/module_examples/chartsRenderWidget/app.R
+++ b/tests/testthat/module_examples/chartsRenderWidget/app.R
@@ -29,23 +29,23 @@ body<-dashboardBody(
tabItem(
tabName="ex1-tab",
{
- h2("Example 1 - hepexplorer- called directly from safetyGraphics hepexplorer")
- chartsRenderWidgetUI("ex1",chart="eDISH",package="safetyexploreR")
+ h2("Example 1 - hepexplorer - called directly from safetyCharts hepexplorer")
+ chartsRenderWidgetUI("ex1",chart="hepexplorer",package="safetyCharts")
}
),
tabItem(
tabName="ex2-tab",
{
- h2("Example 2 - AE Explorer - called from safetyexploreR using custom init function")
- chartsRenderWidgetUI("ex2",chart="aeExplorer",package="safetyexploreR")
+ h2("Example 2 - AE Explorer - called from safetyCharts using custom init function")
+ chartsRenderWidgetUI("ex2",chart="aeExplorer",package="safetyCharts")
}
),
tabItem(
tabName="ex3-tab",
{
- h2("Example 3 - Results over time - called from safetyexploreR")
- chartsRenderWidgetUI("ex3",chart="safetyResultsOverTime",package="safetyexploreR")
+ h2("Example 3 - Results over time - called from safetyCharts")
+ chartsRenderWidgetUI("ex3",chart="safetyResultsOverTime",package="safetyCharts")
}
)
)
@@ -73,13 +73,13 @@ ui <- tagList(
)
server <- function(input,output,session){
- # Example 1 - hep explorer
- paramsLabs <- reactive({list(data=domainData[["labs"]],settings=mappingLabs)})
- callModule(
+ # Example 1 - hep explorer
+ paramsLabs <- reactive({list(data=domainData[["labs"]],settings=mappingLabs)})
+ callModule(
chartsRenderWidget,
"ex1",
- chart="eDISH",
- package="safetyexploreR",
+ chart="hepexplorer",
+ package="safetyCharts",
params=paramsLabs
)
@@ -100,7 +100,7 @@ server <- function(input,output,session){
chartsRenderWidget,
"ex2",
chart="aeExplorer",
- package="safetyexploreR",
+ package="safetyCharts",
params=paramsAEs
)
@@ -109,7 +109,7 @@ server <- function(input,output,session){
chartsRenderWidget,
"ex3",
chart="safetyResultsOverTime",
- package="safetyexploreR",
+ package="safetyCharts",
params=paramsLabs
)
}
diff --git a/tests/testthat/module_examples/chartsTab/app.R b/tests/testthat/module_examples/chartsTab/app.R
index f1f8d809..b0d3ba51 100644
--- a/tests/testthat/module_examples/chartsTab/app.R
+++ b/tests/testthat/module_examples/chartsTab/app.R
@@ -29,7 +29,7 @@ body<-dashboardBody(
tabName="ex1-tab",
{
h2("Example 1 - hepexplorer- called directly from safetyGraphics hepexplorer")
- chartsTabUI("ex1",chart="hepexplorer",package="safetyGraphics",label="Hepatic Explorer",type="htmlwidget")
+ chartsTabUI("ex1",name="hepexplorer",package="safetyCharts",label="Hepatic Explorer",type="htmlwidget")
}
),
@@ -37,35 +37,35 @@ body<-dashboardBody(
tabName="ex2-tab",
{
h2("Example 2 - AE Explorer - called from safetyexploreR using custom init function")
- chartsTabUI("ex2",chart="aeExplorer",package="safetyexploreR",label="AE Explorer",type="htmlwidget")
+ chartsTabUI("ex2",name="aeExplorer",package="safetyexploreR",label="AE Explorer",type="htmlwidget")
}
),
tabItem(
tabName="ex3-tab",
{
h2("Example 3 - Results over time - called from safetyexploreR")
- chartsTabUI("ex3",chart="safetyResultsOverTime",label="Lab Results Over Time", package="safetyexploreR",type="htmlwidget")
+ chartsTabUI("ex3",name="safetyResultsOverTime",label="Lab Results Over Time", package="safetyexploreR",type="htmlwidget")
}
),
tabItem(
tabName="ex4-tab",
{
h2("Example 4 - Helloworld static chart")
- chartsTabUI("ex4",chart="HelloWorld",label="Hello World",type="static")
+ chartsTabUI("ex4",name="HelloWorld",label="Hello World",type="plot")
}
),
tabItem(
tabName="ex5-tab",
{
- h2("Example 5 - Helloworld static chart")
- chartsTabUI("ex5",chart="Boxplot1",label="Box Plot 1",type="static")
+ h2("Example 5 - Box plot")
+ chartsTabUI("ex5",name="Boxplot1",label="Box Plot 1",type="plot")
}
),
tabItem(
tabName="ex6-tab",
{
- h2("Example 6 - Helloworld static chart")
- chartsTabUI("ex6",chart="Boxplot2",label="Custom Box Plot",type="static")
+ h2("Example 6 - Custom Box plot")
+ chartsTabUI("ex6",name="Boxplot2",label="Custom Box Plot",type="plot")
}
)
)
@@ -97,22 +97,21 @@ ui <- tagList(
)
server <- function(input,output,session){
- # Example 1 - hep explorer
- paramsLabs <- reactive({list(data=domainData[["labs"]],settings=mappingLabs)})
- callModule(
- chartsTab,
- "ex1",
- chart="hepexplorer",
- type="htmlwidget",
- package="safetyGraphics",
- domain="labs",
- data=dataR,
- mapping=mappingR
-
- )
+ # Example 1 - hep explorer
+ charts<-MakeChartConfig(paste(.libPaths(),'safetygraphics','config', "charts", sep="/"))
+ paramsLabs <- reactive({list(data=domainData[["labs"]],settings=mappingLabs)})
+ callModule(
+ chartsTab,
+ "ex1",
+ chart=charts$hepexplorer,
+ data=dataR,
+ mapping=mappingR
+)
# Example 2 - AE Explorer
initAEE <- function(data, settings){
+ print("intiAEEE")
+ data<-data$aes
settings$variables=list(
major=settings[["bodsys_col"]],
minor=settings[["term_col"]],
@@ -123,26 +122,21 @@ server <- function(input,output,session){
)
return(list(data=data,settings=settings))
}
+
+ charts$aeExplorer$functions$init <- initAEE
callModule(
chartsTab,
"ex2",
- chart="aeExplorer",
- package="safetyexploreR",
- type="htmlwidget",
- domain="aes",
- data=dataR,
+ chart=charts$aeExplorer,
mapping=mappingR,
- initFunction=initAEE
+ data=dataR
)
#Example 3 - results over time
callModule(
chartsTab,
"ex3",
- chart="safetyResultsOverTime",
- package="safetyexploreR",
- domain="labs",
- type="htmlwidget",
+ chart=charts$safetyResultsOverTime,
data=dataR,
mapping=mappingR
)
@@ -152,15 +146,22 @@ server <- function(input,output,session){
plot(-1:1, -1:1)
text(runif(20, -1,1),runif(20, -1,1),"Hello World")
}
-
+
+ helloworld_chart<-list(
+ name="HelloWorld",
+ type="plot",
+ domain="aes",
+ functions=list(
+ main=helloWorld
+ )
+ )
+
callModule(
chartsTab,
"ex4",
- chart="HelloWorld",
+ chart=helloworld_chart,
data=dataR,
- mapping=mappingR,
- type="static",
- chartFunction=helloWorld
+ mapping=mappingR
)
#Example 5
@@ -177,13 +178,19 @@ server <- function(input,output,session){
axis.title = element_text(size = 12))
}
+ box1_chart<-list(
+ name="Box1",
+ type="plot",
+ domain="labs",
+ functions=list(
+ main=boxPlot
+ )
+ )
+
callModule(
chartsTab,
"ex5",
- chart="Boxplot1",
- chartFunction=boxPlot,
- type="static",
- domain="labs",
+ chart=box1_chart,
data=dataR,
mapping=mappingR
)
@@ -206,17 +213,22 @@ server <- function(input,output,session){
axis.text = element_text(size = 12),
axis.title = element_text(size = 12))
}
-
+ box2_chart<-list(
+ name="Box2",
+ type="plot",
+ domain="labs",
+ functions=list(
+ main=boxPlot2,
+ init=dataInit
+ )
+ )
+
callModule(
chartsTab,
"ex6",
- chartFunction=boxPlot2,
- chart="Boxplot2",
+ chart=box2_chart,
data=dataR,
- domain="labs",
- mapping=mappingR,
- initFunction=dataInit,
- type="static"
+ mapping=mappingR
)
}
diff --git a/tests/testthat/module_examples/settingsData/app.R b/tests/testthat/module_examples/settingsData/app.R
index a9b9c0f2..86fb772d 100644
--- a/tests/testthat/module_examples/settingsData/app.R
+++ b/tests/testthat/module_examples/settingsData/app.R
@@ -1,24 +1,21 @@
library(shiny)
library(safetyGraphics)
-
-domains <- list(labs=labs, aes=aes)
reactlogReset()
ui <- tagList(
-
fluidPage(
h1("Example 1: Labs Only"),
- settingsDataUI("ex1", domains),
- # h2("Example 2: Labs+AES"),
- # settingsDataUI("ex2"),
+ settingsDataUI("ex1"),
+ h2("Example 2: Labs+AES"),
+ settingsDataUI("ex2"),
# h2("Example 3: Labs+AEs+Extras"),
# settingsDataUI("ex3")
)
)
server <- function(input,output,session){
- callModule(settingsData, "ex1", domains = domains)
- # callModule(settingsData, "ex2", allData = rbind(lab_summary,ae_summary))
+ callModule(settingsData, "ex1", domains = list(labs=labs))
+ callModule(settingsData, "ex2", domains = list(labs=labs,aes=aes))
# callModule(settingsData, "ex3", allData = rbind(lab_summary,ae_summary,extra) )
}