Skip to content

Commit

Permalink
Dev v1.1 (#358)
Browse files Browse the repository at this point in the history
* create location for static R graphic code

* update metadata to include static plot demo

* if type=="static" create a static plot

* pass chart type to chart module

* shiny output binding depends on chart type

* replace hardcode w/ generalized code

* add overall loading indicator #286

* add workflows back in...

* add hepexplorer implementations

* incorporate plotly charts

* add package to app

* add prototype shiny module as custom chart

* add type=="module"

* meant to delete this

* tweak inst/ folder structure for custom code

* user settings #73

* add documentation for settingsLocation param

* add pkgdown website

* place custom charts in "examples" folder

* remove example charts from metadata

* update dependencies

* move createChart to its own file

* add hep explorer ggplot as an included chart

* do not load plotly by default

* move createChart to its own file

* add hepexplorer_ggplot as included chart

* add new chart to settingsMetadata docs

* functionalize report RMD #312

* update safety-histogram to fix #355

* include Jeremys updates to safety histogram js

* removing static hep explorer from included charts

* update with beccas suggestions

* make ggpot2 a suggested dependency

* move button to bottom left and show after 3 seconds

* adds addChart() function.

* tweak documentation

* add support for custom script in safetyGraphicsApp

* refactor to support addChart()

* minor tweaks

* more functions for easy metadata manipulation

* add default for charts

* fixes minor issues from code review.

* fix option logic. Clear tests.

* clear checks

* add text_key to settings description on hover

* update renderers

* update workflow link

* add vignette and rebuild pkgdown

* change hex to camel case

* tweak customization workflow

* update docs

* update R script to camelCase

* add delta-delta renderer. fix #380

* delete stray file. close #372

* tweak links. rebuild pkgdown site

* update vignette

* fix #383 and add option to pre-load custom datafiles

* accomodate custom datafiles in UI

* update safetyGraphicsApp params

* clean stray old code

* clear settings when ititializing app. fix #388.

* fix typo in fix #388

* update hep-explorer renderer

* update hep-explorer renderer

* add pALT setting.

* fix tests

* update vignette. rebuild docs

* update title

* remove metadata from pre-loaded data

* handle case where settingsLocation=NULL

* update docs

* spelling fixes

* update vignette

* remove old vignette

Co-authored-by: Becca Krouse <rebecca_krouse@rhoworld.com>
Co-authored-by: jwildfire <jwildfire@rhoworld.com>
  • Loading branch information
3 people authored and jwildfire committed Jan 15, 2020
1 parent 6e3192c commit 195d2c1
Show file tree
Hide file tree
Showing 107 changed files with 17,090 additions and 1,406 deletions.
6 changes: 6 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@
^packrat/
^\.Rprofile$
^cran-comments.md$
^docs$
^_pkgdown.yml$
^Meta$
^_pkgdown\.yml$
^pkgdown$
^doc$
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,7 @@ packrat/lib*/

#Local shinyTest folders
inst/eDISH_app/tests/*-current/
customSettings/

doc
Meta
14 changes: 9 additions & 5 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
Package: safetyGraphics
Title: Create Interactive Graphics Related to Clinical Trial Safety
Version: 1.0.0
Version: 1.1.0
Authors@R: c(
person("Jeremy", "Wildfire", email = "jeremy_wildfire@rhoworld.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("Rho Inc.", role = "cph"))
Maintainer: Jeremy Wildfire <jeremy_wildfire@rhoworld.com>
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/ASA-DIA-InteractiveSafetyGraphics/safetyGraphics
BugReports: https://github.com/ASA-DIA-InteractiveSafetyGraphics/safetyGraphics/issues
URL: https://github.com/SafetyGraphics/safetyGraphics
BugReports: https://github.com/SafetyGraphics/safetyGraphics/issues
Depends: R (>= 3.5)
License: MIT + file LICENSE
Encoding: UTF-8
Expand All @@ -21,7 +22,9 @@ RoxygenNote: 6.1.1
Suggests:
testthat,
shinytest,
knitr
knitr,
ggplot2,
plotly
Imports:
dplyr,
htmlwidgets,
Expand All @@ -38,5 +41,6 @@ Imports:
utils,
haven,
shinyWidgets,
tidyr
tidyr,
shinybusy
VignetteBuilder: knitr
5 changes: 5 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# Generated by roxygen2: do not edit by hand

export(addChart)
export(addSetting)
export(chartRenderer)
export(detectStandard)
export(generateSettings)
export(getRequiredSettings)
export(getSettingsMetadata)
export(output_chartRenderer)
export(removeCharts)
export(removeSettings)
export(render_chartRenderer)
export(safetyGraphicsApp)
export(trimSettings)
Expand All @@ -25,6 +29,7 @@ importFrom(purrr,map)
importFrom(purrr,map_chr)
importFrom(purrr,map_dbl)
importFrom(purrr,map_lgl)
importFrom(rlang,":=")
importFrom(rlang,.data)
importFrom(rlang,parse_expr)
importFrom(shiny,runApp)
Expand Down
6 changes: 5 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# safetyGraphics v1.1.0

Allows users to preload their own charts and data sets for use in the safetyGraphics Shiny Application. See the "Custom Workflows" Vignette for details and examples.

# safetyGraphics v1.0.0

The first production release of safetyGraphics includes many inprovements including the addition of 5 new interactive graphics and an embedded help page with a detailed clinical workflow for using the tool.
The first production release of safetyGraphics includes many improvements including the addition of 5 new interactive graphics and an embedded help page with a detailed clinical workflow for using the tool.

# safetyGraphics v0.7.3

Expand Down
96 changes: 96 additions & 0 deletions R/addChart.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#' Adds a new chart for use in the safetyGraphics shiny app
#'
#' This function updates settings objects to add a new chart to the safetyGraphics shiny app
#'
#' This function makes it easy for users to add a new chart to the safetyGraphics shiny app, by making updates to the underlying metadata used by the package. Specifically, the function adds a row to chartsMetadata.rda describing the chart and adds a column to settingsMetadata.rda specifying which settings are used with the chart. If new settings are needed for the chart, the user should call addSetting() for each new setting required.
#'
#' @param chart Name of the chart - one word, all lower case
#' @param label Nicely formatted name of the chart
#' @param description Description of the chart
#' @param repo_url Homepage for chart's code repository (if any)
#' @param settings_url Homepage for chart's settings documentation
#' @param main Name of the main function used to initialize the app. If the type is htmlwidgets, the js function must accept "location" and "settings" parameters (in that order) and have an .init() method, expecting a json data array. Otherwise, the r function should accept named data and settings parameters, and should be loaded in the user's namespace.
#' @param type type of chart. Should be 'static', 'plotly' or 'module'
#' @param maxWidth max width for the widget in pixels
#' @param requiredSettings array of text_key values (matching those used in settingsMetadata) for the required settings for this chart
#' @param settingsLocation path where the custom settings will be loaded/saved. If metadata is not found in that location, it will be read from the package (e.g. safetyGraphics::settingsMetadata), and then written to the specified location once the new chart has been added.
#' @param overwrite overwrite any existing chart metadata? Note that having multiple charts with the same name is not supported and will cause unexpected results. default = true
#'
#' @importFrom rlang ":="
#' @import dplyr
#'
#' @export
#'
addChart <- function(
chart,
label="",
description="",
repo_url="",
settings_url="",
main="character",
type='static',
maxWidth=1000,
requiredSettings=c(""),
settingsLocation=getwd(),
overwrite = TRUE
){

# check inputs
stopifnot(
typeof(chart)=="character",
typeof(label)=="character",
typeof(description)=="character",
typeof(repo_url)=="character",
typeof(settings_url)=="character",
typeof(main)=="character",
typeof(type)=="character",
type %in% c("htmlwidget","plotly","static","module"),
is.numeric(maxWidth)
)

if(nchar(label)==0){
label = chart
}

# create settings for new chart
newChart <- list(
chart=chart,
main=main,
label=label,
description=description,
repo_url=repo_url,
settings_url=settings_url,
type=type,
maxWidth=maxWidth
)

# load charts metadata
chartsMetaPath <- paste(settingsLocation,"chartsMetadata.Rds",sep="/")
if(file.exists(chartsMetaPath)){
chartsMeta <- readRDS(chartsMetaPath)
}else{
chartsMeta <- safetyGraphics::chartsMetadata
}

#delete rows for the specified chart if overwrite is true
if(overwrite){
chartsMeta <- chartsMeta %>% filter(.data$chart != !!chart)
}

# add custom chart settings and save
chartsMeta[nrow(chartsMeta)+1,] <- newChart
saveRDS(chartsMeta, chartsMetaPath)

# add a column for the new chart to the settings metadata
settingsMetaPath <- paste(settingsLocation,"settingsMetadata.Rds",sep="/")
if(file.exists(settingsMetaPath)){
settingsMeta <- readRDS(settingsMetaPath)
}else{
settingsMeta <- safetyGraphics::settingsMetadata
}

#Fill in the column based on requiredSettings and save
chart_col <- sym(paste0("chart_",chart))
settingsMeta <- settingsMeta %>% mutate(!!chart_col := .data$text_key %in% !!requiredSettings)
saveRDS(settingsMeta, settingsMetaPath)
}
98 changes: 98 additions & 0 deletions R/addSetting.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#' Adds a new setting for use in the safetyGraphics shiny app
#'
#' This function updates settings objects to add a new setting parameter to the safetyGraphics shiny app
#'
#' This function makes it easy for users to adds a new settings to the safetyGraphics shiny app by making updates to the underlying metadata used by the package. Specifically, the function adds a row to settingsMetadata.rda describing the setting.
#'
#' @param text_key Text key indicating the setting name. \code{'--'} delimiter indicates a nested setting
#' @param label Label
#' @param description Description
#' @param setting_type Expected type for setting value. Should be "character", "vector", "numeric" or "logical"
#' @param setting_required Flag indicating if the setting is required
#' @param column_mapping Flag indicating if the setting corresponds to a column in the associated data
#' @param column_type Expected type for the data column values. Should be "character","logical" or "numeric"
#' @param field_mapping Flag indicating whether the setting corresponds to a field-level mapping in the data
#' @param field_column_key Key for the column that provides options for the field-level mapping in the data
#' @param setting_cat Setting category (data, measure, appearance)
#' @param default Default value for non-data settings
#' @param charts character vector of charts using this setting
#' @param settingsLocation path where the custom settings will be loaded/saved. If metadata is not found in that location, it will be read from the package (e.g. safetyGraphics::settingsMetadata), and then written to the specified location once the new setting has been added.
#' @param overwrite overwrite any existing setting metadata? Note that having settings with the same name is not supported and will cause unexpected results. default = true
#'
#' @export
#'

addSetting<-function(
text_key,
label,
description,
setting_type,
setting_required=FALSE,
column_mapping=FALSE,
column_type=NA,
field_mapping=FALSE,
field_column_key='',
setting_cat,
default='',
charts=c(),
settingsLocation=getwd(),
overwrite=TRUE
){

# check inputs
stopifnot(
typeof(text_key)=="character",
typeof(label)=="character",
typeof(description)=="character",
typeof(setting_type)=="character",
setting_type %in% c("character","numeric","logical"),
typeof(setting_required)=="logical",
typeof(column_mapping)=="logical",
typeof(field_mapping)=="logical",
typeof(setting_cat)=="character"
)

if(nchar(label)==0){
label = text_key
}

# create object for new setting
newSetting <- list(
text_key=text_key,
label=label,
description=description,
setting_type=setting_type,
setting_required=setting_required,
column_mapping=column_mapping,
column_type=column_type,
field_mapping=field_mapping,
field_column_key=field_column_key,
setting_cat=setting_cat,
default=default
)

# load settings metadata
settingsMetaPath <- paste(settingsLocation,"settingsMetadata.Rds",sep="/")
if(file.exists(settingsMetaPath)){
settingsMeta <- readRDS(settingsMetaPath)
}else{
settingsMeta <- safetyGraphics::settingsMetadata
}


# set chart flags for new setting
chartVars <- names(settingsMeta)[substr(names(settingsMeta),0,6)=="chart_"]
settingCharts <- paste0("chart_",charts)
for(varName in chartVars){
newSetting[varName] <- varName %in% settingCharts
}

#delete row for the specified chart if overwrite is true
if(overwrite){
settingsMeta <- settingsMeta %>% filter(.data$text_key != !!text_key)
}

# add custom chart settings and save
settingsMeta[nrow(settingsMeta)+1,] <- newSetting
saveRDS(settingsMeta, settingsMetaPath)
}
42 changes: 28 additions & 14 deletions R/chartRenderer.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#' Create an interactive graphics widget
#'
#' This function creates an nice interactive widget. See this vingette for more details regarding how to customize charts.
#' This function creates an nice interactive widget. See the vignettes for more details regarding how to customize charts.
#'
#' @param data A data frame containing the labs data. Data must be structured as one record per study participant per time point per lab measure.
#' @param debug_js print settings in javascript before rendering chart. Default: \code{FALSE}.
Expand Down Expand Up @@ -42,6 +42,14 @@
#'
#' @export
chartRenderer <- function(data, debug_js = FALSE, settings = NULL, chart=NULL) {
# load chart metadata (use custom data if available)
chartmeta<-safetyGraphics::chartsMetadata
if(!(is.null(options('sg_chartsMetadata')[[1]]))){ #if the option exists
if(options('sg_chartsMetadata')[[1]]){ #and it's set to true
chartmeta<-options('sg_chartsMetadata_df')[[1]]
}
}

# Chart specific customizastions (to be removed after js updates)
if(chart %in% c("paneledoutlierexplorer","safetyoutlierexplorer")){
settings$time_cols <- list(list(),list());
Expand Down Expand Up @@ -83,16 +91,18 @@ chartRenderer <- function(data, debug_js = FALSE, settings = NULL, chart=NULL) {
rotate_tick_labels= TRUE,
vertical_space= 100
)

settings$groups = settings$group_cols
}

#Set Chart Width
chartMaxWidth<- safetyGraphics::chartsMetadata %>% filter(.data$chart==!!chart) %>% pull(.data$maxWidth)
chartMaxWidth<- chartmeta %>% filter(.data$chart==!!chart) %>% pull(.data$maxWidth)
settings$max_width <- chartMaxWidth

#Renderer
chartFunction<- safetyGraphics::chartsMetadata %>% filter(.data$chart==!!chart) %>% pull(.data$main)
chartFunction<- chartmeta %>% filter(.data$chart==!!chart) %>% pull(.data$main)
chartType <- chartmeta %>% filter(.data$chart==!!chart) %>% pull(.data$type)

rSettings = list(
data = data,
debug_js=debug_js,
Expand All @@ -104,15 +114,19 @@ chartRenderer <- function(data, debug_js = FALSE, settings = NULL, chart=NULL) {
)
)

# create widget
htmlwidgets::createWidget(
name = 'chartRenderer',
rSettings,
# width = width,
# height = height,
package = 'safetyGraphics',
sizingPolicy = htmlwidgets::sizingPolicy(viewer.suppress=TRUE, browser.external = TRUE)
)
if (chartType=="htmlwidget"){
# create widget
htmlwidgets::createWidget(
name = 'chartRenderer',
rSettings,
# width = width,
# height = height,
package = 'safetyGraphics',
sizingPolicy = htmlwidgets::sizingPolicy(viewer.suppress=TRUE, browser.external = TRUE)
)
} else {
createChart(chartType, rSettings)
}
}

#' Shiny bindings for chartRenderer
Expand Down
27 changes: 27 additions & 0 deletions R/createChart.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#' Create a custom static or plotly R graphic
#'
#' @param type Type of chart. Options are \code{"static"} or \code{plotly}.
#' @param rSettings List containing all arguments needed for chart creation:
#' \code{rSettings = list(
#' data = data,
#' debug_js=debug_js,
#' chartFunction = chartFunction,
#' settings = jsonlite::toJSON(
#' settings,
#' auto_unbox = TRUE,
#' null = "null"
#' ))}
#'
#' @keywords internal
createChart <- function(type, rSettings){

data <- rSettings[["data"]]
settings <- jsonlite::fromJSON(rSettings[["settings"]])
chartFunction <- rSettings[["chartFunction"]]

#chartCode <- system.file("custom", type, paste0(chartFunction, ".R"), package = "safetyGraphics")
#source(chartCode)
chartFunction <- match.fun(chartFunction)
chartFunction(data, settings)

}
1 change: 0 additions & 1 deletion R/data_checks.R

This file was deleted.

Loading

0 comments on commit 195d2c1

Please sign in to comment.