diff --git a/.Rbuildignore b/.Rbuildignore
index d0b2a8c..e7404bf 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -9,3 +9,5 @@
^\.lintr$
^doc$
^Meta$
+^README\.Rmd$
+^rsconnect$
diff --git a/.Rhistory b/.Rhistory
index 90e0c43..640390e 100644
--- a/.Rhistory
+++ b/.Rhistory
@@ -1 +1,512 @@
-renv::init()
+plotly::layout(
+height = 600,
+width = 800,
+xaxis = list(
+range = c(xmin, xmax),
+tickmode = "array",
+tickvals = sepby,
+ticktext = sepby
+)
+)
+empty_plot <- function(message = "No data available for these values") {
+g_plot <- ggplot() +
+theme_void()
+fig <- plotly::ggplotly(g_plot, height = 200) %>%
+plotly::add_annotations(
+text = message,
+x = 1,
+y = 1,
+xref = "paper",
+yref = "paper",
+showarrow = FALSE
+) %>%
+plotly::layout(
+xaxis = list(visible = FALSE), yaxis = list(visible = FALSE)
+)
+return(list(plot = g_plot, ptly = fig))
+}
+cm_int <- interval_plot(
+datain = datain[["CM"]],
+startvar = "CMSTDY",
+endvar = "CMENDY",
+yvar = "CMTRT",
+seriesvar = "CMCLAS",
+subjectid = subjectid,
+series_color = NA,
+yaxislab = "Drug/Med/Therapy"
+)
+rangeae <- layer_scales(ae_int$plot)$y$range$range
+rangecm <- layer_scales(cm_int$plot)$y$range$range
+xmin <- floor(min(rangeae, rangecm) / 5) * 5
+xmax <- ceiling(max(rangeae, rangecm) / 5) * 5
+sepby <- as.integer(seq(xmin, xmax, by = ceiling((xmax - xmin) / 10)))
+cm_int$ptly
+plotly::subplot(ae_int$ptly, cm_int$ptly,
+shareX = TRUE, nrows = 2,
+titleX = TRUE, titleY = TRUE, margin = 0.005
+) %>%
+plotly::layout(
+height = 600,
+width = 800,
+xaxis = list(
+range = c(xmin, xmax),
+tickmode = "array",
+tickvals = sepby,
+ticktext = sepby
+)
+)
+ae_int$ptly
+cm_int$ptly
+plotly::subplot(ae_int$ptly, cm_int$ptly,
+shareX = TRUE, nrows = 2,
+titleX = TRUE, titleY = TRUE, margin = 0.005
+)
+plotly::subplot(ae_int$ptly, cm_int$ptly,
+shareX = FALSE, nrows = 2,
+titleX = TRUE, titleY = TRUE, margin = 0.005
+)
+plotly::subplot(ae_int$ptly, cm_int$ptly,
+shareX = FALSE, nrows = 2,
+titleX = TRUE, titleY = TRUE, margin = 0.005
+) %>%
+plotly::layout(
+height = 600,
+width = 800,
+xaxis = list(
+range = c(xmin, xmax),
+tickmode = "array",
+tickvals = sepby,
+ticktext = sepby
+)
+)
+empty_plot <- function(message = "No data available for these values") {
+g_plot <- ggplot() +
+theme_void()
+fig <- plotly::ggplotly(g_plot, height = 200) %>%
+plotly::add_annotations(
+text = message,
+x = 1,
+y = 1,
+showarrow = FALSE
+) %>%
+plotly::layout(
+xaxis = list(visible = FALSE), yaxis = list(visible = FALSE)
+)
+return(list(plot = g_plot, ptly = fig))
+}
+("CM" %in% names(datain)) && (!is.null(datain$CM))
+cm_int <- interval_plot(
+datain = datain[["CM"]],
+startvar = "CMSTDY",
+endvar = "CMENDY",
+yvar = "CMTRT",
+seriesvar = "CMCLAS",
+subjectid = subjectid,
+series_color = NA,
+yaxislab = "Drug/Med/Therapy"
+)
+# Identify Axis range for combined plot
+rangeae <- layer_scales(ae_int$plot)$y$range$range
+rangecm <- layer_scales(cm_int$plot)$y$range$range
+xmin <- floor(min(rangeae, rangecm) / 5) * 5
+xmax <- ceiling(max(rangeae, rangecm) / 5) * 5
+sepby <- as.integer(seq(xmin, xmax, by = ceiling((xmax - xmin) / 10)))
+plotly::subplot(ae_int$ptly, cm_int$ptly,
+shareX = TRUE, nrows = 2,
+titleX = TRUE, titleY = TRUE, margin = 0.005
+) %>%
+plotly::layout(
+height = 600,
+width = 800,
+xaxis = list(
+range = c(xmin, xmax),
+tickmode = "array",
+tickvals = sepby,
+ticktext = sepby
+)
+)
+shiny::runApp()
+plotly::subplot(ae_int$ptly, cm_int$ptly,
+shareX = TRUE, nrows = 2,
+titleX = TRUE, titleY = TRUE, margin = 0.005
+) %>%
+plotly::layout(
+height = 600,
+width = 800,
+xaxis = list(
+range = c(xmin, xmax),
+tickmode = "array",
+tickvals = sepby,
+ticktext = sepby
+)
+)
+cm_int$ptly
+p1 <- cm_int$ptly
+View(p1)
+gc()
+gc()
+shiny::runApp()
+shiny::runApp()
+gc()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+devtools::document()
+devtools::document()
+devtools::check()
+devtools::document()
+lintr::lint_package()
+devtools::check_man()
+shiny::runApp()
+golem::add_module("plot_profile")
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+datain
+gc()
+shiny::runApp()
+datain
+gc()
+shiny::runApp()
+adam_read()
+adam_read() -> df
+View(df)
+adam_read()$adam
+shiny::runApp()
+names(adam_read()$adam)
+names(adam_read()$adam$adae)
+adam_read()$adam_attrib
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+domain()
+sourcedata()
+sourcedata()[[domain()]]
+shiny::runApp()
+sourcedata()[[domain()]]
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+sourcedata()
+domain()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+rv$sourcedata()
+shiny::runApp()
+shiny::runApp()
+rv$sourcedata()
+shiny::runApp()
+rv$sourcedata
+rv$sourcedata()
+shiny::runApp()
+shiny::runApp()
+rv$sourcedata
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+styler::style_pkg()
+gc()
+styler::style_pkg()
+shiny::runApp()
+styler::style_pkg()
+shiny::runApp()
+lintr::lint_package()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+gc()
+shiny::runApp()
+shiny::runApp()
+devtools::check()
+shiny::runApp()
+renv::status()
+renv::snapshot()
+renv::restore()
+renv::restore()
+renv::restore()
+renv::status()
+renv::dependencies()
+renv::status()
+remove.packages("shinydashboard")
+renv::status()
+renv::dependencies()
+renv::dependencies()
+renv::snapshot()
+renv::snapshot(exclude = "cvars")
+remove.packages("cvars")
+packageVersion("rsconnect")
+remove.packages("gert")
+renv::restore()
+remove.packages("gert")
+renv::purge("gert")
+renv::restore()
+renv::restore()
+remove.packages("gert")
+renv::install("gert@1.9.2")
+renv::snapshot()
+library(shiny)
+library(shiny)
+detach("package:shiny", unload = TRUE)
+usethis::use_package("dplyr", min_version = TRUE)
+usethis::use_package("flextable", min_version = TRUE)
+usethis::use_package("ggplot2", min_version = TRUE)
+usethis::use_package("golem", min_version = TRUE)
+usethis::use_package("officer", min_version = TRUE)
+usethis::use_package("scales", min_version = TRUE)
+usethis::use_package("shiny", min_version = TRUE)
+usethis::use_package("shinyjs", min_version = TRUE)
+usethis::use_package("shinyWidgets", min_version = TRUE)
+usethis::use_package("stringr", min_version = TRUE)
+usethis::use_package("tibble", min_version = TRUE)
+usethis::use_build_ignore("rsconnect")
+usethis::use_git_ignore("rsconnect")
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+View(event)
+test <- rv$goutput$rpt_data
+trt_level_diff <- length(levels(test$TRTVAR)) - length(unique(test$TRTVAR))
+test <- test %>%
+mutate(point_n = as.numeric(as.factor(TRTVAR)) - trt_level_diff)
+View(test)
+test <- rv$goutput
+View(test)
+event$curveNumber
+repName()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+View(out)
+devtools::test_active_file()
+gc()
+devtools::test_coverage_active_file()
+devtools::test_active_file()
+View(out)
+out$ptly
+out <- interval_plot(
+datain = adae,
+startvar = "ASTDY",
+endvar = "AENDY",
+yvar = "AETERM",
+seriesvar = "AESEV1",
+subjectid = "01-701-1302",
+series_color = NA,
+yaxislab = "Reported Term for the Adverse Event"
+)
+out$ptly
+View(out)
+out[["rpt_data"]][["TOTAL"]]
+gc()
+devtools::test_active_file()
+devtools::test_coverage_active_file()
+data(adae)
+data(cm)
+multi_interval(
+datain = list(AE = adae, CM = cm),
+subjectid = "01-701-1275"
+)$ptly
+gc()
+devtools::load_all(".")
+usethis::use_test("multi_interval")
+devtools::test_active_file()
+devtools::test_active_file()
+nrow(out$rpt_data)
+expect_equal(unique(out$rpt_data$USUBJID), "01-701-1302")
+expect_true(all(!is.na(complete_stat$ASTDY)))
+complete_stat <- out$rpt_data %>%
+filter(Status == "Complete")
+expect_true(all(!is.na(complete_stat$ASTDY)))
+View(complete_stat)
+out$ptly
+out$title
+expect_equal(out$title, "Events over Study Period for Participant: 01-701-1302\n; Age: 61; Sex: M; Race: WHITE") #nolint
+View(out)
+expect_true(c("CMSTDY", "CMENDY", "CMTRT", "CMCLAS" %in% names(out$rpt_data)))
+expect_true(c("CMSTDY", "CMENDY", "CMTRT", "CMCLAS") %in% names(out$rpt_data))
+expect_true(all(c("CMSTDY", "CMENDY", "CMTRT", "CMCLAS") %in% names(out$rpt_data)))
+out[["ptly"]][["x"]][["subplot"]]
+expect_true(out[["ptly"]][["x"]][["subplot"]])
+devtools::test_active_file()
+devtools::test_coverage_active_file()
+adae$USUBJID
+adae$USUBJID %>% unique()
+devtools::test_active_file()
+expect_true(nrow(out$rpt_data) > 0)
+expect_equal(unique(out$rpt_data$USUBJID), "01-703-1299")
+expect_equal(out$title, "Events over Study Period for Participant: 01-703-1299\n; Age: 61; Sex: M; Race: WHITE")
+expect_equal(out$title, "Events over Study Period for Participant: 01-703-1299\n; Age: 81; Sex: F; Race: WHITE") #nolint
+out$ptly
+View(out)
+out[["ptly"]][["x"]][["data"]][[4]][["text"]]
+expect_equal(out[["ptly"]][["x"]][["data"]][[4]][["text"]], "No data for this participant/period")
+expect_true(out[["ptly"]][["x"]][["subplot"]])
+expect_true(all(is.na(out$rpt_data$CMDECOD)))
+devtools::test_active_file()
+devtools::test_coverage_active_file()
+devtools::test_active_file()
+out$ptly
+expect_true(nrow(out$rpt_data) > 0)
+nrow(out$rpt_data)
+expect_null(nrow(out$rpt_data))
+View(out)
+expect_true(out[["ptly"]][["x"]][["subplot"]])
+expect_null(out[["ptly"]][["x"]][["subplot"]])
+View(out)
+out[["ptly"]][["x"]][["data"]][[1]][["text"]]
+expect_equal(out[["ptly"]][["x"]][["data"]][[1]][["text"]], "No AE data available")
+devtools::test_active_file()
+devtools::test_coverage_active_file()
+styler::style_pkg()
+lintr::lint_package()
+usethis::use_description()
+usethis::use_package("admiral")
+usethis::use_package("admiral", min_version = TRUE)
+usethis::use_package("DT", type = "suggests")
+usethis::use_package("DT", type = "suggests", min_version = TRUE)
+usethis::use_import_from("plotly", "layout")
+data(adae)
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+?tooltip()
+?bs4Dash::addTooltip()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+input$theme_switch
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+styler::style_pkg()
+shiny::runApp()
+shiny::runApp()
+lintr::lint_package()
+devtools::check()
+styler::style_pkg()
+shiny::runApp()
+shiny::runApp()
+styler::style_pkg()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+styler::style_pkg()
+lintr::lint_package()
+usethis::use_package("waiter", type = "suggests")
+devtools::check()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+NS()
+?NS()
+NS("aqe")
+shiny::runApp()
+shiny::runApp()
+devtools::test_active_file()
+shiny::runApp()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+shiny::runApp()
+shiny::runApp()
+View(statistics_data)
+statistics_data %>%
+group_by() %>%
+filter(ADJPVALUE <= pvalcut) %>%
+arrange(desc(ADJPVALUE))
+?p.adjust()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+gc()
+gc()
+shiny::runApp()
+gc()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+shiny::runApp()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+devtools::test_active_file()
+styler::style_pkg()
+lintr::lint_package()
+lintr::lint_package()
+devtools::check()
+?format()
+format(1, justify = "centre")
+?cat()
+packageVersion("httpuv")
+packageVersion("rsconnect")
+shiny::runApp()
+shiny::runApp()
+?recode()
+devtools::document()
+devtools::load_all(".")
+?cvars::add()
+devtools::document()
+devtools::load_all(".")
+?cvars::add()
+?cvars::mcatstat()
+devtools::document()
+?cvars::add_var()
+devtools::document()
+?cvars::add_var()
+cvars::add_var(1,1)
+add_var(10, 1)
+devtools::document()
+?cvars::add_var()
+devtools::document()
+?cvars::mult_var()
+devtools::document()
+?cvars::div_var()
+usethis::use_r("test_new")
+div_var(3.5)
+div_var(3, 5)
+renv::status()
+renv::snapshot(exclude='cvars')
+renv::restore()
diff --git a/.github/workflows/lint-changed-files.yaml b/.github/workflows/lint-changed-files.yaml
index c65dc5f..46504c5 100644
--- a/.github/workflows/lint-changed-files.yaml
+++ b/.github/workflows/lint-changed-files.yaml
@@ -40,7 +40,7 @@ jobs:
lint_package(linters = linters_with_defaults(
line_length_linter(100),
object_length_linter(50L),
- cyclocomp_linter(75L),
+ cyclocomp_linter(100L),
indentation_linter = NULL,
object_usage_linter = NULL,
object_name_linter = NULL
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index e635418..ce00fc3 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -37,11 +37,11 @@ jobs:
lint_package(linters = linters_with_defaults(
line_length_linter(100),
object_length_linter(50L),
- cyclocomp_linter(75L),
+ cyclocomp_linter(100L),
indentation_linter = NULL,
object_usage_linter = NULL,
object_name_linter = NULL
))
shell: Rscript {0}
env:
- LINTR_ERROR_ON_LINT: true
\ No newline at end of file
+ LINTR_ERROR_ON_LINT: true
diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml
index b19d938..8d8fc90 100644
--- a/.github/workflows/test-coverage.yaml
+++ b/.github/workflows/test-coverage.yaml
@@ -37,7 +37,7 @@ jobs:
)
print(coverage)
percent_coverage <- covr::percent_coverage(coverage)
- threshold <- 50
+ threshold <- 10
cli::cli_rule()
if (percent_coverage < threshold) {
cli::cli_abort("Code coverage is below the required threshold ({threshold}%).")
diff --git a/.gitignore b/.gitignore
index 3cbd67f..0896549 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ inst/doc
.Renviron
/doc/
/Meta/
+rsconnect
diff --git a/.lintr b/.lintr
index 268b7e1..e83a75f 100644
--- a/.lintr
+++ b/.lintr
@@ -1,2 +1,2 @@
-linters: linters_with_defaults(line_length_linter(100), object_length_linter(50), cyclocomp_linter(75L), object_usage_linter=NULL, object_name_linter=NULL)
+linters: linters_with_defaults(line_length_linter(100), object_length_linter(50), cyclocomp_linter(80L), indentation_linter=NULL, object_usage_linter=NULL, object_name_linter=NULL)
encoding: "UTF-8"
diff --git a/DESCRIPTION b/DESCRIPTION
index b49ce66..fb19f40 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,3 +1,85 @@
+<<<<<<< HEAD
+Package: cvars
+Title: Clinical Visual Analytics for Review and Submission
+Version: 0.1.0
+Authors@R: c(
+ person("Smriti", "Anand", email = "xxx@xxx.com", role = c("aut", "cre")),
+ person("Jayashree", "V", role = "aut"),
+ person("Sukalpo", "Saha", role = "aut"),
+ person("Vikram", "S", role = "aut"),
+ person("Jagadish", "Katam", role = "aut"),
+ person("Arjun", "Rubalingam", role = "aut"),
+ person("Amol Bandu", "Gorde", role = "aut"),
+ person("Gomathi", "S", role = "aut"),
+ person("Dhivya", "Kanagaraj", role = "ctb"),
+ person("Neetu", "Sangari", role = "ctb"),
+ person("Aishwarya", "LR", role = "ctb"),
+ person("Manali", "Jadhav", role = "ctb"),
+ person("Prakasam", "R", role = "ctb")
+ )
+Description: Development of an open-source tool and package to enable
+ generation of identified interactive plots for clinical review and
+ direct inclusion in submission for regulatory agencies. The initial
+ scope is to develop a package to generate interactive forest and
+ volcano plots for adverse event and FDA Medical Queries (FMQs)
+ analysis outputs for inclusion in submissions to the FDA. This work is
+ a collaboration among the American Statistical Association (ASA),
+ PHUSE, and FDA.
+License: Apache License (>= 2)
+URL: https://github.com/phuse-org/aesummaries/
+BugReports: https://github.com/phuse-org/aesummaries/issues/
+Depends:
+ R (>= 3.5)
+Imports:
+ bs4Dash (>= 2.3.0),
+ dplyr (>= 1.1.2),
+ DT (>= 0.28),
+ epitools (>= 0.5.10.1),
+ flextable (>= 0.9.2),
+ forcats (>= 0.5.1),
+ ggplot2 (>= 3.4.3),
+ golem (>= 0.4.1),
+ htmltools (>= 0.5.6),
+ magrittr (>= 2.0.3),
+ officer (>= 0.6.2),
+ rlang (>= 1.1.1),
+ scales (>= 1.2.1),
+ shiny (>= 1.7.5),
+ shinyjs (>= 2.1.0),
+ shinyWidgets (>= 0.7.6),
+ stringr (>= 1.5.0),
+ tibble (>= 3.2.1)
+Suggests:
+ cli,
+ config,
+ cowplot,
+ ftExtra,
+ ggstance,
+ glue,
+ haven,
+ knitr (>= 1.36),
+ lifecycle,
+ markdown (>= 1.1),
+ plotly,
+ plyr,
+ purrr,
+ RCurl,
+ rmarkdown,
+ shinycssloaders,
+ testthat (>= 3.1.0),
+ tidyr,
+ utils,
+ waiter,
+ withr
+VignetteBuilder:
+ knitr
+Config/testthat/edition: 3
+Encoding: UTF-8
+Language: en-US
+LazyData: true
+Roxygen: list(markdown = TRUE)
+RoxygenNote: 7.2.3
+=======
Package: cvars
Title: Clinical Visual Analytics for Review and Submission
Version: 0.1.0
@@ -77,3 +159,4 @@ Language: en-US
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
+>>>>>>> 0cd101109665f2699b442aa971069068a28e65d5
diff --git a/NAMESPACE b/NAMESPACE
index cfc215f..2034f02 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -4,13 +4,16 @@ export(adae_r001)
export(ae_pre_processor)
export(data_attrib)
export(data_read)
+export(empty_plot)
export(event_analysis)
export(forest_plot)
export(g_seriescol)
export(g_seriessym)
+export(interval_plot)
export(mcatstat)
export(mdisplay)
export(mentry)
+export(multi_interval)
export(reverselog_trans)
export(risk_stat)
export(riskdiff_wald)
@@ -27,7 +30,6 @@ import(officer)
import(scales)
import(shiny)
import(shinyWidgets)
-import(shinydashboard)
import(tools)
importFrom(DT,addRow)
importFrom(DT,colReorder)
@@ -46,12 +48,35 @@ importFrom(DT,styleEqual)
importFrom(DT,styleInterval)
importFrom(DT,tableFooter)
importFrom(DT,tableHeader)
+importFrom(bs4Dash,accordion)
+importFrom(bs4Dash,accordionItem)
+importFrom(bs4Dash,box)
+importFrom(bs4Dash,boxSidebar)
+importFrom(bs4Dash,bs4Card)
+importFrom(bs4Dash,dashboardBody)
+importFrom(bs4Dash,dashboardHeader)
+importFrom(bs4Dash,dashboardPage)
+importFrom(bs4Dash,dashboardSidebar)
+importFrom(bs4Dash,menuItem)
+importFrom(bs4Dash,menuItemOutput)
+importFrom(bs4Dash,navbarTab)
+importFrom(bs4Dash,renderMenu)
+importFrom(bs4Dash,sidebarMenu)
+importFrom(bs4Dash,tabBox)
+importFrom(bs4Dash,tabItem)
+importFrom(bs4Dash,tabItems)
+importFrom(bs4Dash,tooltip)
+importFrom(bs4Dash,updateNavbarTabs)
importFrom(forcats,fct_inorder)
importFrom(forcats,fct_match)
importFrom(forcats,fct_recode)
importFrom(forcats,fct_relabel)
importFrom(forcats,fct_relevel)
importFrom(forcats,fct_reorder)
+importFrom(golem,activate_js)
+importFrom(golem,add_resource_path)
+importFrom(golem,bundle_resources)
+importFrom(golem,favicon)
importFrom(golem,with_golem_options)
importFrom(magrittr,"%>%")
importFrom(rlang,.data)
@@ -85,7 +110,9 @@ importFrom(rlang,sym)
importFrom(rlang,syms)
importFrom(rlang,type_of)
importFrom(rlang,warn)
+importFrom(shiny,NS)
importFrom(shiny,shinyApp)
+importFrom(shiny,tagList)
importFrom(shinyjs,click)
importFrom(shinyjs,delay)
importFrom(shinyjs,disable)
diff --git a/R/adae_r001.R b/R/adae_r001.R
index 67f6364..cf6591d 100644
--- a/R/adae_r001.R
+++ b/R/adae_r001.R
@@ -117,11 +117,16 @@ adae_r001 <- function(datain,
ui_dptvar = ui_ht,
ui_pctdisp = recode(ui_pctdisp, "HT" = "TRT")
) %>% ungroup()
-
# Cut off - apply to high term only:
ht_dat <-
subset(ht_dat, BYVAR1 %in% unique(BYVAR1[as.numeric(PCT) > ui_cutoff]))
-
+ if (is.null(ht_dat) || nrow(ht_dat) == 0) {
+ final_cts <- data.frame("Note" = "No data available under these conditions")
+ return(list(
+ tout = flextable(final_cts),
+ rpt_data = final_cts
+ ))
+ }
# Vector of Unique High terms
uniqHT1 <- unique(ht_dat[ht_dat$TRTVAR == levels(ht_dat$TRTVAR)[1], ]$DPTVAL)
uniqHT <- c(
@@ -199,8 +204,7 @@ adae_r001 <- function(datain,
sort_opt = ui_sortopt,
sort_var = ui_sortvar
) %>% mutate(DPTVAR = ui_lt, CN = "C")
-
- if (is.null(ht_dat)) {
+ if (is.null(ht_dat) || nrow(ht_dat) == 0) {
final_cts <- data.frame("Note" = "No data available under these conditions")
return(list(
tout = flextable(final_cts),
@@ -242,8 +246,6 @@ adae_r001 <- function(datain,
# Order of terms only:
comb_order <- rbind(ht_dati, lt_dati)
-
-
# Merge to get correct order:
final_cts <- bind_rows(ht_dat, lt_dat) %>%
select(-any_of(c("DPTVARN", "DPTVALN"))) %>%
@@ -270,8 +272,8 @@ adae_r001 <- function(datain,
"Participants With ",
AE_cond,
" Adverse Events by Higher Term and Lower Term \n",
- population,
- " population"
+ "Population: ",
+ population
)
footnote <-
paste0(
@@ -312,7 +314,6 @@ adae_r001 <- function(datain,
} else {
extra_var <- ""
}
-
### Mdisplay:
report1 <- mdisplay(
datain = final_cts,
@@ -323,8 +324,6 @@ adae_r001 <- function(datain,
trtbign = datain$bigN,
colformat = " n(%)"
)
-
-
print("adae table sucess")
return(list(
tout = report1$tout,
diff --git a/R/ae_pre_processor.R b/R/ae_pre_processor.R
index a13dab3..122095e 100644
--- a/R/ae_pre_processor.R
+++ b/R/ae_pre_processor.R
@@ -95,60 +95,54 @@ ae_pre_processor <- function(
left_join(fmq, by = c("PT_NAME" = "PT"))
}
- ## Calling Mentry to process treatment variable , grouping variables, total trt, Big N calculation
- mdsin <- mentry(
- datain = datain,
- ui_aSubset = aeSubset,
- ui_dSubset = aeDenomSubset,
- ui_byvar = aeByVar,
- ui_subgrpvar = aeSubGrpVar,
- ui_trtvar = trtvar,
- ui_trtsort = trtsort,
- ui_trttotalyn = aeTrtTot,
- ui_sgtotalyn = aeSubGrpTot,
- ui_bign = aeBigN,
- ui_addGrpMiss = aeGrpVarMiss,
- ui_pop_fil = pop_fil
- )
# pre process for AE data
- dsin <- mdsin$dsin
# standardizing date format to common format
date_formats <- c("%d%b%Y", "%Y-%m-%d", "%m/%d/%Y", "%d/%m/%Y")
- if ("AESTDT" %in% names(dsin)) {
- df1 <- dsin %>% mutate(AESTDT = as.Date(AESTDT, tryFormats = date_formats, optional = FALSE))
+ if ("AESTDT" %in% names(datain)) {
+ data_pro <- datain %>%
+ mutate(AESTDT = as.Date(AESTDT, tryFormats = date_formats, optional = FALSE))
} else {
- df1 <- dsin %>% mutate(AESTDT = as.Date(ASTDT, tryFormats = date_formats, optional = FALSE))
+ data_pro <- datain %>%
+ mutate(AESTDT = as.Date(ASTDT, tryFormats = date_formats, optional = FALSE))
}
- if ("AEENDT" %in% names(dsin)) {
- df1 <- df1 %>% mutate(AEENDT = as.Date(AEENDT, tryFormats = date_formats, optional = FALSE))
+ if ("AEENDT" %in% names(datain)) {
+ data_pro <- data_pro %>%
+ mutate(AEENDT = as.Date(AEENDT, tryFormats = date_formats, optional = FALSE))
} else {
- df1 <- df1 %>% mutate(AEENDT = as.Date(AENDT, tryFormats = date_formats, optional = FALSE))
+ data_pro <- data_pro %>%
+ mutate(AEENDT = as.Date(AENDT, tryFormats = date_formats, optional = FALSE))
}
- if ("RFSTDTC" %in% names(dsin)) {
- df1 <- df1 %>% mutate(RFSTDTC = as.Date(RFSTDTC, tryFormats = date_formats, optional = FALSE))
+ if ("RFSTDTC" %in% names(datain)) {
+ data_pro <- data_pro %>%
+ mutate(RFSTDTC = as.Date(RFSTDTC, tryFormats = date_formats, optional = FALSE))
} else {
- df1 <- df1 %>% mutate(RFSTDTC = as.Date(TRTSDT, tryFormats = date_formats, optional = FALSE))
+ data_pro <- data_pro %>%
+ mutate(RFSTDTC = as.Date(TRTSDT, tryFormats = date_formats, optional = FALSE))
}
- if ("RFENDTC" %in% names(dsin)) {
- df1 <- df1 %>% mutate(RFENDTC = as.Date(RFENDTC, tryFormats = date_formats, optional = FALSE))
+ if ("RFENDTC" %in% names(datain)) {
+ data_pro <- data_pro %>%
+ mutate(RFENDTC = as.Date(RFENDTC, tryFormats = date_formats, optional = FALSE))
} else {
- df1 <- df1 %>% mutate(RFENDTC = as.Date(TRTEDT, tryFormats = date_formats, optional = FALSE))
+ data_pro <- data_pro %>%
+ mutate(RFENDTC = as.Date(TRTEDT, tryFormats = date_formats, optional = FALSE))
}
# Eliminating not coded AE terms and recodeing Toxicity to severity
- df1 <- df1 %>%
+ data_pro <- data_pro %>%
tidyr::drop_na(RFSTDTC) %>%
mutate(
- AEDECOD = ifelse(!is.na(AESTDT) & is.na(AEDECOD), "Not yet coded", AEDECOD),
- AESTDT = ifelse(is.na(AESTDT) & !is.na(AEDECOD), RFSTDTC, AESTDT)
+ AEDECOD = if_else(!is.na(AESTDT) & is.na(AEDECOD), "Not yet coded", AEDECOD),
+ AESTDT = if_else(is.na(AESTDT) & !is.na(AEDECOD), RFSTDTC, AESTDT)
)
- if ("AESEV" %in% (names(df1))) {
- df1 <- df1 %>% mutate(AESEV = toupper(AESEV))
- } else if ("ATOXGR" %in% (names(df1))) {
- df1 <- df1 %>% mutate(AESEV = recode(toupper(ATOXGR),
+ if ("AESEV" %in% (names(data_pro))) {
+ data_pro <- data_pro %>% mutate(AESEV = toupper(AESEV))
+ } else if ("ASEV" %in% names(data_pro)) {
+ data_pro <- data_pro %>% mutate(AESEV = toupper(ASEV))
+ } else if ("ATOXGR" %in% (names(data_pro))) {
+ data_pro <- data_pro %>% mutate(AESEV = recode(toupper(ATOXGR),
"GRADE 0" = "MILD",
"GRADE 1" = "MILD",
"GRADE 2" = "MODERATE",
@@ -157,26 +151,41 @@ ae_pre_processor <- function(
"GRADE 5" = "SEVERE"
))
}
-
+ ## Calling Mentry to process treatment variable , grouping variables, total trt, Big N calculation
+ mdsin <- mentry(
+ datain = data_pro,
+ ui_aSubset = aeSubset,
+ ui_dSubset = aeDenomSubset,
+ ui_byvar = aeByVar,
+ ui_subgrpvar = aeSubGrpVar,
+ ui_trtvar = trtvar,
+ ui_trtsort = trtsort,
+ ui_trttotalyn = aeTrtTot,
+ ui_sgtotalyn = aeSubGrpTot,
+ ui_bign = aeBigN,
+ ui_addGrpMiss = aeGrpVarMiss,
+ ui_pop_fil = pop_fil
+ )
+ dsin <- mdsin$dsin
# applying fliter conditional from the UI filter element for AE reports
# filter data for seriousness, drug-related, and severity
if (length(ae_filter) > 0) {
if ("Any Event" %in% ae_filter) {
- df1 <- df1
+ dsin <- dsin
}
if ("Treatment emergent" %in% ae_filter) {
- df1 <- df1 %>% filter(TRTEMFL == "Y")
+ dsin <- dsin %>% filter(TRTEMFL == "Y")
}
if ("Serious" %in% ae_filter) {
- df1 <- df1 %>% filter(AESER == "Y")
+ dsin <- dsin %>% filter(AESER == "Y")
}
if ("Drug-related" %in% ae_filter) {
- df1 <- df1 %>% filter(AEREL == "RELATED")
+ dsin <- dsin %>% filter(AEREL == "RELATED")
}
if (sum(c("Mild", "Moderate", "Severe") %in% ae_filter) > 0) {
severity_filter <- ae_filter[which(ae_filter %in% c("Mild", "Moderate", "Severe"))]
- df1 <- df1 %>% filter(AESEV %in% toupper(severity_filter))
+ dsin <- dsin %>% filter(AESEV %in% toupper(severity_filter))
}
if (sum(c(
@@ -188,21 +197,21 @@ ae_pre_processor <- function(
"Recovering/Resolving",
"Not Recovered/Not Resolved", "Fatal"
))]
- df1 <- df1 %>% filter(AEOUT %in% toupper(severity_filter))
+ dsin <- dsin %>% filter(AEOUT %in% toupper(severity_filter))
}
}
# filter ae data occurred in the given time frame
if (aeObsPeriod == "Overall Duration") {
- if ("STUDYFL" %in% names(df1)) {
- df1 <- df1 %>%
+ if ("STUDYFL" %in% names(dsin)) {
+ dsin <- dsin %>%
filter(STUDYFL == "Y")
} else {
- df1 <- df1
+ dsin <- dsin
}
} else if (aeObsPeriod == "Other") {
- df1 <- df1 %>%
+ dsin <- dsin %>%
filter((AESTDT > RFSTDTC) & (AESTDT < (RFENDTC + aeObsResidual)))
}
- return(list(dsin = df1, dout = mdsin$dout, bigN = mdsin$bign))
+ return(list(dsin = dsin, dout = mdsin$dout, bigN = mdsin$bign))
}
diff --git a/R/app_server.R b/R/app_server.R
index 384ac12..a36afa5 100644
--- a/R/app_server.R
+++ b/R/app_server.R
@@ -1,1084 +1,110 @@
-################################################################################
-# app_server.R
-# This R Script defines the server logic for the Shiny App.
-################################################################################
-
-############ Capture Reactive input values ###########
-## Get the session Input element values
-
#' The application server-side
#'
#' @param input,output,session Internal parameters for {shiny}.
-#'
#' @import shiny
#' @noRd
-
app_server <- function(input, output, session) {
- ReVal <- reactiveValues()
- observe({
- ReVal <- reactiveValuesToList(input)
- })
-
- ReVal <- reactiveValues(
- goutput = NULL,
- toutput = NULL
- )
+ Sys.sleep(2)
+ options(shiny.maxRequestSize = 4096 * 1024^2)
- #################### Reading Data #################
- ## Read the input dataset from the source location
- output$readDataBtn_UI <- renderUI({
+ observe({
if (input$source == "Default") {
- req(input$ADaM_Data_d)
+ toggleState("readData", condition = !is.null(input$ADaM_Data_d))
} else if (input$source == "Local") {
- req(input$analysis_data)
+ toggleState("readData", condition = !is.null(input$analysis_data))
}
- actionButton(
- "readData",
- "Read Data",
- color = "primary",
- style = "color: #fff; background-color: #337ab7;height: 25px;
- border-color: #2e6da4;font-size: 12px;text-align: center;"
- )
})
- observeEvent(input$readData,
- {
- print("reading data begin")
- if (input$source == "Default") {
- adam_data <- paste(input$ADaM_Data_d, collapse = ",")
- } else {
- adam_data <- input$analysis_data
- }
- withProgress(
- ReVal$adam <- data_read(
- ui_data_source = input$source,
- ui_adam_data = adam_data
- ),
- message = "Processing data reading step...",
- detail = "This step should take a while.",
- min = 0,
- max = 1,
- value = 1
- )
- removeUI("#readData")
- print("reading data success")
- },
- ignoreInit = TRUE
- )
-
- ## get the domain and analysis dataset
observe({
- if (!is.null(ReVal$adam)) {
- print("Checking data read")
- temp1 <- ReVal$adam
- ReVal$sourcedata <- temp1$adam
- ReVal$domain <- names(temp1$adam)
- ReVal$data_attr <- temp1$adam_attrib
- test_domain <- names(temp1$adam)
- print("Checking data success")
+ if (is.null(input$data_upload)) {
+ hide("rep_input")
+ hide("gen_filter")
+ } else {
+ show("rep_input")
+ show("gen_filter")
}
})
- ## session output object to check if the Input data is not null
-
- output$dataUpload <- reactive({
- return(!is.null(ReVal$sourcedata))
- })
- outputOptions(output, "dataUpload", suspendWhenHidden = FALSE)
-
- ## To identify the base domain that is required for the report
- output$report_base_domain_UI <- renderUI({
- req(ReVal$sourcedata)
- selectInput("bdomain", "Report base domain", choices = ReVal$domain)
- })
-
- ####### Report Selection ####################
- ## Get the list of reports for option for a given domain
observe({
- print("loading report meta begin")
- req(input$source)
- req(ReVal$sourcedata)
- ReVal$report_meta <- tibble::tribble(
- ~TA,
- ~DOMAIN,
- ~REPNAME,
- ~REPDESC,
- ~REPNO,
- ~REPTYPE,
- "Any",
- "ADAE",
- "adae_r001",
- "Summary of Adverse Events by System Organ Class and Preferred Term",
- "2.1",
- "Table",
- "Any",
- "ADAE",
- "Forest Plot",
- "Forest plot for adverse events",
- "2.2",
- "Figure",
- "Any",
- "ADAE",
- "Volcano Plot",
- "Volcano plot for adverse events",
- "2.4",
- "Figure",
- "Any",
- "ADAE",
- "Event Analysis",
- "Event analysis of MedRA query",
- "2.5",
- "Figure",
- )
-
- print("loading report meta success")
- })
-
- ## session output object to check domain split character
- output$report_meta <- reactive({
- return(!is.null(ReVal$report_meta))
- })
- outputOptions(output, "report_meta", suspendWhenHidden = FALSE)
-
- ## Create report selection input elements
- observe({
- req(ReVal$report_meta)
- req(input$bdomain)
- tempRepMeta <- ReVal$report_meta %>% filter(DOMAIN %in% c(toupper(input$bdomain)))
- output$report_TA_UI <- renderUI({
- req(tempRepMeta)
- selectInput("tarea", "Therapeutic Area", choices = pull(unique(tempRepMeta["TA"])))
- })
- output$report_Type_UI <- renderUI({
- req(tempRepMeta)
- req(input$tarea)
- selectInput("repType",
- "Report Type",
- choices = unique(tempRepMeta["REPTYPE"][tempRepMeta["TA"] == input$tarea])
- )
- })
- output$report_Nam_UI <- renderUI({
- req(input$repType)
- req(input$tarea)
- selectInput("repName",
- "Report Name",
- choices =
- unique(tempRepMeta["REPNAME"][tempRepMeta["TA"] == input$tarea &
- tempRepMeta["REPTYPE"] == input$repType])
- )
- })
- output$report_Num_UI <- renderUI({
- req(input$repType)
- req(input$repName)
- selectInput("repnum", "Report Number",
- choices = unique(tempRepMeta["REPNO"][tempRepMeta["REPNAME"] == input$repName])
- )
- })
- output$report_desc_UI <- renderUI({
- req(input$repType)
- req(input$repName)
- selectInput("repdesc", "Report Description",
- choices = unique(tempRepMeta["REPDESC"][tempRepMeta["REPNAME"] == input$repName])
- )
- })
- })
-
- output$repName <- reactive({
- return(tolower(input$repName))
- })
- outputOptions(output, "repName", suspendWhenHidden = FALSE)
-
- output$repType <- reactive({
- return(tolower(input$repType))
- })
- outputOptions(output, "repType", suspendWhenHidden = FALSE)
- ############## Treatment & Population Selection ############
-
- output$treatment_population_UI <- renderUI({
- req(ReVal$data_attr)
- req(input$repName)
- # Get list Treatment Variables as per CDISC ADaM IG
- trtv <-
- c(
- "ARM", "ARMCD", "ACTARM", "ACTARMCD", "STUDYID",
- "COHORT", "TRTA", "TRTP", "TRTAN", "TRTPN"
- )
- # Get the treatment variable from the input dataset
- trtvar <- ReVal$data_attr[[input$bdomain]] %>%
- filter(VAR_NAMES %in% trtv |
- str_detect(VAR_NAMES, "TRT[:digit:]+[AP]")) %>%
- select(VAR_NAMES) %>%
- pull()
-
- # Get the Population variable from the input dataset
- popvar <- ReVal$data_attr[[input$bdomain]] %>%
- filter(str_detect(tolower(VAR_LABEL), "population")) %>%
- mutate(pop = paste0(VAR_NAMES, " ~ ", VAR_LABEL)) %>%
- select(pop) %>%
- pull()
-
- # create select input element for Treatment Variable & Population variable
- fluidRow(
- column(
- width = 4,
- selectInput("trt_var",
- "Treatment Variable",
- choices = c(trtvar), selected = trtvar[2]
- )
- ),
- column(
- width = 4,
- selectInput("trt_sort",
- "Treatment Sort Variable",
- choices = c(trtvar), selected = trtvar[2]
- )
- ),
- column(
- width = 4,
- selectInput("popfilter", "Population Filter",
- choices = c("Overall Population", popvar)
- )
- )
- )
- })
+ req(rep_inputs$repType())
+ if (rep_inputs$repType() == "Figure") {
+ choices <- c("html", "pdf", "docx", "pptx", "interactive")
+ } else {
+ choices <- c("html", "pdf", "docx")
+ }
- ################## Display Input Data #########################
- ## Get the list of variable from Input data for select input for basic data check
- output$source_data_varlist_UI <- renderUI({
- req(ReVal$sourcedata)
- varSelectInput("data_varlist",
- "Select Variables to be viewed",
- data = ReVal$sourcedata[[input$bdomain]],
- selected = NULL,
- multiple = TRUE
+ updateRadioButtons(session,
+ "save_fmt",
+ choices = choices
)
})
- ## Display the values of selected variables in the source data
- output$sourcedata_display <- DT::renderDataTable(
- {
- req(input$data_varlist)
-
- data_lkup <- ReVal$sourcedata[[input$bdomain]] %>%
- select(unlist(strsplit(paste(input$data_varlist, collapse = ","), ",")))
-
- datatable(
- data_lkup,
- extensions = "Buttons",
- options = list(
- dom = "Bfrtip",
- buttons = I("colvis"),
- pageLength = 10
- )
- )
- },
- server = FALSE
- )
-
- ## Get the list of variable from Input data for select input for distinct value check
-
- output$categorical_variable_list_UI <- renderUI({
- req(ReVal$sourcedata)
- varSelectInput("categorical_variable",
- "Select Variable to see distinct values",
- data = ReVal$sourcedata[[input$bdomain]],
- selected = NULL
+ adam_read <-
+ mod_data_read_server(
+ "data_read_1",
+ source = reactive(input$source),
+ df_adam = reactive(input$ADaM_Data_d),
+ analysis_data = reactive(input$analysis_data),
+ read_btn = reactive(input$readData)
)
- })
- ## Display the distinct values of the selected variables
- output$distinct_value_display <- DT::renderDataTable(
- {
- req(input$categorical_variable)
- if (length(input$categorical_variable) > 0) {
- distinct_value <-
- distinct(ReVal$sourcedata[[input$bdomain]], !!!input$categorical_variable)
-
- datatable(
- distinct_value,
- extensions = "Buttons",
- options = list(
- dom = "Bfrtip",
- buttons = I("colvis"),
- pageLength = 10
- )
- )
- }
- },
- server = FALSE
- )
-
-
- ########## ADAE Analysis Module ###########
- output$AE_Event_Filter_UI <- renderUI({
- req(ReVal$sourcedata)
- req(input$repName)
- if (tolower(input$bdomain) == "adae") {
- print("AE filter UI field processing")
- if (tolower(input$repName) %in% c(
- "volcano plot", "forest plot",
- "adae_r001", "event analysis"
- )) {
- aeFil <- c(
- "Any",
- "Treatment Emergent",
- "Serious",
- "Drug-related",
- "Mild",
- "Moderate",
- "Severe",
- "Recovered/Resolved",
- "Recovering/Resolving",
- "Not Recovered/Not Resolved",
- "Fatal"
- )
- } else if (tolower(input$repName) %in% c("tornado plot")) {
- aeFil <- c(
- "Any Event",
- "Treatment Emergent",
- "Serious",
- "Drug-related",
- "Recovered/Resolved",
- "Recovering/Resolving",
- "Not Recovered/Not Resolved",
- "Fatal"
- )
- }
- selectInput("ae_filter",
- "Adverse Event Filter(s)",
- choices = aeFil,
- selected = aeFil[1],
- multiple = TRUE
- )
- }
- })
-
- output$aeCatVar_UI <- renderUI({
- req(ReVal$sourcedata)
- req(input$repName)
- req(ReVal$data_attr)
- if (tolower(input$bdomain) == "adae" &&
- tolower(input$repName) == "tornado plot") {
- print("AE categorical variable processing for Tornado plot")
- aCatV <- c("ASEV", "AESEV", "AETOXGR", "ATOXGR")
- # Get the treatment variable from the input dataset
- aeCatV <- ReVal$data_attr %>%
- filter(VAR_NAMES %in% aCatV) %>%
- select(VAR_NAMES) %>%
- pull()
- selectInput("aeCatVar",
- "AE Catagorical Variable",
- choices = aeCatV
- )
- }
- })
-
- # Get the variable list input for subgroup and By group selection for adae report
observe({
- req(ReVal$sourcedata)
- req(input$repType)
- req(input$repName)
- req(input$bdomain)
- if (tolower(input$bdomain) == "adae" && input$repType == "Table") {
- print("AE Group variable and analysis variable processing")
- output$ae_subgrp_UI <- renderUI({
- varSelectInput(
- "aeSubGrpVar",
- "Sub Group Variables",
- data = ReVal$sourcedata[[input$bdomain]],
- selected = NULL,
- multiple = TRUE
- )
- })
- output$ae_byvar_UI <- renderUI({
- varSelectInput(
- "aeByVar",
- "By Group Variables",
- data = ReVal$sourcedata[[input$bdomain]],
- selected = NULL,
- multiple = TRUE
- )
- })
- output$ae_dptvar_UI <- renderUI({
- varSelectInput(
- "aeDptVar",
- "Dependent Variables",
- data = ReVal$sourcedata[[input$bdomain]],
- selected = NULL,
- multiple = TRUE
- )
- })
-
- output$pct_disp_UI <- renderUI({
- if (input$aeRiskYN == "N") {
- pct_denom <- c("Treatment" = "TRT", "Total" = "VAR", "High Term" = "HT")
- } else {
- pct_denom <- c("Treatment" = "TRT")
- }
- selectInput(
- inputId = "ui_pctdisp",
- label = "Percentage Denominator",
- choices = pct_denom
- )
- })
- }
- })
-
- observe({
- req(ReVal$sourcedata)
- req(input$bdomain)
- req(input$repName)
- req(input$trt_var)
- req(input$ae_filter)
- req(input$repType)
- if (tolower(input$bdomain) == "adae") {
- print("AE byVar processing start")
- ## evaluating the by variables based on report selection
- if (input$repType == "Table") {
- if (is.null(input$aeByVar)) {
- aeByV <- input$ae_hlt
- } else {
- aeByV <- c(paste(input$sl_byvar, collapse = ","), input$ae_hlt)
- }
- } else {
- if (tolower(input$repName) %in% c("volcano plot", "forest plot", "event analysis")) {
- aeByV <- input$ae_hlt
- } else {
- aeByV <- NA
- }
- }
-
- print("AE preprocessing start")
- ### calling Pre Processing AE data
- withProgress(
- ReVal$ae_pre <- ae_pre_processor(
- datain = ReVal$sourcedata[[input$bdomain]],
- ae_filter = input$ae_filter,
- aeSubset = ifelse(input$repType == "Table", input$aeSubset, NA),
- aeDenomSubset = ifelse(input$repType == "Table", input$aeDenomSubset, NA),
- aeObsPeriod = input$period,
- aeObsResidual = input$period_please_specify,
- trtvar = toupper(input$trt_var),
- trtsort = input$trt_sort,
- pop_fil = str_trim(unlist(strsplit(
- unique(input$popfilter), "~"
- ))[1]),
- fmq_data = utils::read.csv(paste0(
- app_sys("extdata"), "/FMQ_Consolidated_List.csv"
- )),
- aeEventVar = ifelse(is.null(input$ae_llt), input$ae_hlt, input$ae_llt),
- aeByVar = aeByV,
- aeSubGrpVar = ifelse(input$repType == "Table",
- ifelse(
- is.null(input$aeSubGrpVar),
- NA,
- paste(input$sl_subgrpvar, collapse = ",")
- ), NA
- ),
- aeBigN = ifelse(input$repType == "Table", input$aeBigN, "N"),
- aeGrpVarMiss = ifelse(input$repType == "Table", input$aeGrpVarMiss, "N"),
- aeTrtTot = ifelse(input$repType == "Table", input$aeTrtTot, "N"),
- aeSubGrpTot = ifelse(input$repType == "Table", input$aeSubGrpTot, "N")
- ),
- message = "Executing pre processing for EVENTS/ PT...",
- detail = "This step should take a while.",
- min = 0,
- max = 1,
- value = 1
- )
- print("AE preprocessing end")
- }
- })
-
- # deriving treatment pair for risk analysis
-
- observe({
- req(ReVal$ae_pre)
- req(input$repName)
- if (tolower(input$repName) %in% c("volcano plot", "forest plot") ||
- (tolower(input$repName) == "adae_r001" & input$aeRiskYN == "Y")) {
- print("AE treatment pair processing start")
- TRTCD <-
- reactive({
- return(unique(ReVal$ae_pre$dout$TRTVAR[ReVal$ae_pre$dout$TRTVAR != ""]))
- })
-
- ## Single pair radio button selection for Volcano plot
-
- output$treatment1_UI <- renderUI({
- radioButtons(
- "treatment1",
- "Control Group",
- choices = TRTCD(),
- selected = TRTCD()[1]
- )
- })
-
- output$treatment2_UI <- renderUI({
- radioButtons(
- "treatment2",
- "Treatment Group",
- choices = setdiff(TRTCD(), input$treatment1),
- selected = setdiff(TRTCD(), input$treatment1)[1]
- )
- })
-
- output$treatment1_label_UI <- renderUI({
- textInput("treatment1_label",
- "Label for Control Group",
- value = "Control"
- )
- })
-
- output$treatment2_label_UI <- renderUI({
- textInput("treatment2_label",
- "Label for Treatment Group",
- value = "Treatment"
- )
- })
-
- ## Multiple pair check box selection for forest plot
-
- output$ctrlgrp_UI <- renderUI({
- radioButtons(
- "ctrlgrp",
- "Control Group",
- choices = TRTCD(),
- selected = TRTCD()[1],
- inline = FALSE
- )
- })
-
- output$trtgrp_UI <- renderUI({
- checkboxGroupInput(
- "trtgrp",
- "Treatment Group",
- choices = setdiff(TRTCD(), input$ctrlgrp),
- selected = setdiff(TRTCD(), input$ctrlgrp)[1]
- )
- })
- print("AE treatment pair processing end")
- }
-
- output$aeSortBy_UI <- renderUI({
- req(input$repName)
- req(input$repName != "Event Analysis")
-
- if (tolower(input$repName) == "volcano plot") {
- print("")
- } else {
- if (tolower(input$repName) == "adae_r001" & input$aeRiskYN == "Y") {
- by_var <- c("Count", "Percent", "RiskValue")
- } else if (tolower(input$repName) == "forest plot") {
- by_var <- c("Count", "Percent", "RiskValue")
- } else if (tolower(input$repName) == "adae_r001" & input$aeRiskYN == "N") {
- by_var <- c("Count", "Percent")
- }
- selectInput(
- "sort_by",
- "Sorting Variable",
- choices = by_var
- )
- }
- })
- })
-
- ## event analysis related input fields
- observe({
- req(ReVal$ae_pre$dsin)
- req(input$repName)
- if (tolower(input$repName) %in% c("event analysis")) {
- print("AE event analysis hlt list input process start")
- output$aeHLT_list_UI <- renderUI({
- req(ReVal$ae_pre$dsin)
- req(input$ae_hlt)
- temp1 <- ReVal$ae_pre$dsin
- temp2 <- input$ae_hlt
- if (input$ae_hlt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
- hlt_list <- unlist(strsplit(unique(temp1[[temp2]]), "~~"))
- hlt_list1 <- sort(unique(gsub("/\\w+", "", hlt_list[!is.na(hlt_list)])))
- } else {
- hlt_list1 <- sort(unique(temp1[[temp2]]))
- }
- selectInput(
- "hlt_val",
- "Event Higher Classification",
- choices = hlt_list1,
- selected = hlt_list1[1]
- )
- })
- print("AE event analysis hlt list input process end")
-
- print("AE event analysis hlt scope input process start")
- output$aeHLT_query_cat_UI <- renderUI({
- req(input$ae_hlt)
- if (input$ae_hlt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
- selectInput("hlt_cat", "Query Scope", choices = c("Narrow", "Broad"))
- } else {
- print("")
- }
- })
- print("AE event analysis hlt scope input process end")
-
- print("AE event analysis llt list input process start")
- output$aeLLT_list_UI <- renderUI({
- req(ReVal$ae_pre$dsin)
- req(input$ae_hlt)
- req(input$hlt_val)
- if (input$ae_hlt %in% c("FMQ_NAM", "SMQ_NAM", "CQ_NAM")) {
- req(input$hlt_cat)
- }
- temp1 <- ReVal$ae_pre$dsin
- temp2 <- input$ae_hlt
-
- if (input$ae_hlt %in% c("FMQ_NAM", "SMQ_NAM", "CQ_NAM")) {
- if (toupper(input$hlt_cat) == "NARROW") {
- hl_val1 <- paste0(str_to_upper(input$hlt_val), "/", str_to_upper(input$hlt_cat))
- } else {
- hl_val1 <- input$hlt_val
- }
- } else {
- hl_val1 <- input$hlt_val
- }
-
- temp3 <- input$ae_llt
-
- llt_list <- unique(temp1[[temp3]][str_detect(toupper(temp1[[temp2]]), toupper(hl_val1))])
-
- if (input$ae_llt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
- llt_list_ <- unlist(strsplit(unique(llt_list), "~~"))
- llt_list1 <- sort(unique(gsub("/\\w+", "", llt_list_[!is.na(llt_list_)])))
- } else {
- llt_list1 <- sort(llt_list)
- }
-
- selectInput(
- "llt_val",
- "Event Term",
- choices = llt_list1,
- selected = llt_list1[1]
- )
- })
- print("AE event analysis llt list input process end")
-
- print("AE event analysis llt scope input process start")
- output$aeLLT_query_cat_UI <- renderUI({
- req(input$ae_llt)
- if (input$ae_llt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
- selectInput("llt_cat", "Query Scope", choices = c("Narrow", "Broad"))
- } else {
- print("")
- }
- })
- print("AE event analysis llt scope input process end")
- }
- })
-
-
- # Generating risk values
-
- observeEvent(input$process, {
- req(input$repName)
- req(ReVal$ae_pre$dsin)
- req(ReVal$ae_pre$dout)
- req(input$statistics)
- req(input$ae_hlt)
- req(input$ae_llt)
- req(input$summary_by)
- if (tolower(input$repName) %in% c("volcano plot")) {
- req(input$treatment1)
- req(input$treatment2)
- }
- if (tolower(input$repName) %in% c("forest plot")) {
- req(input$ctrlgrp)
- req(input$trtgrp)
- req(input$sort_opt)
- req(input$sort_by)
- }
- req(input$alpha)
- req(input$cutoff)
- if (tolower(input$repName) %in% c("volcano plot", "forest plot")) {
- print("AE risk_stat process start")
- withProgress(
- ReVal$statistics <- risk_stat(
- datain = ReVal$ae_pre$dsin,
- d_datain = ReVal$ae_pre$dout,
- eventVar = ifelse(is.null(input$ae_llt), input$ae_hlt, input$ae_llt),
- summary_by = input$summary_by,
- ctrlgrp = ifelse(tolower(input$repName) == "volcano plot",
- input$treatment1,
- input$ctrlgrp
- ),
- trtgrp = ifelse(
- tolower(input$repName) == "volcano plot",
- input$treatment2,
- paste(input$trtgrp, collapse = "~~")
- ),
- statistics = input$statistics,
- alpha = input$alpha,
- cutoff = input$cutoff,
- sort_opt = ifelse(tolower(input$repName) == "forest plot", input$sort_opt, NA),
- sort_var = ifelse(tolower(input$repName) == "forest plot", input$sort_by, NA)
- ),
- message = "Executing Get Statistics for EVENTS/ PT...",
- detail = "This step should take a while.",
- min = 0,
- max = 1,
- value = 1
- )
- print("AE risk_stat process end")
- }
- })
-
- observeEvent(input$process, {
- req(input$repName)
- # generating Volcano plot
-
- if (tolower(input$repName) == "volcano plot") {
- req(ReVal$statistics)
- req(input$ae_filter)
- req(ReVal$statistics)
- req(input$statistics)
- req(input$treatment1)
- req(input$treatment2)
- req(input$X_ref)
- req(input$summary_by)
- req(input$pvalue_label)
-
- print("AE Volcano Plot process start")
- withProgress(message = "Generating Volcano Plot", value = 0, {
- ReVal$goutput <- try(volcano_plot(
- datain = isolate(ReVal$ae_pre$dsin),
- AE_Filter = input$ae_filter,
- statistics_data = isolate(ReVal$statistics),
- statistics = input$statistics,
- treatment1 = input$treatment1,
- treatment2 = input$treatment2,
- X_ref = as.numeric(input$X_ref),
- summary_by = input$summary_by,
- pvalue_label = input$pvalue_label,
- treatment1_label = input$treatment1_label,
- treatment2_label = input$treatment2_label,
- pvalcut = input$pvalcut
- ))
- })
- print("AE Volcano Plot process end")
- }
-
- # Generating Forest Plot
-
- if (tolower(input$repName) %in% c("forest plot")) {
- req(ReVal$statistics)
- req(input$ae_filter)
- req(input$ae_hlt)
- req(input$ae_llt)
- req(input$summary_by)
- req(input$statistics)
- req(input$pvalcut)
- req(input$X_ref)
- req(input$riskScale)
- print("AE Forest Plot process start")
- withProgress(message = "Generating Forest Plot", value = 0, {
- ReVal$goutput <- try(forest_plot(
- datain = isolate(ReVal$statistics),
- AE_Filter = input$ae_filter,
- review_by = c(input$ae_hlt, input$ae_llt),
- summary_by = input$summary_by,
- statistics = input$statistics,
- xref = as.numeric(input$X_ref),
- pvalcut = input$pvalcut,
- scale_trans = input$riskScale
- ))
- })
- print("AE Forest Plot process end")
- }
- })
-
- ## Generating Adae summary table
- observeEvent(input$process, {
- req(input$repName)
- if (tolower(input$repName) %in% c("adae_r001")) {
- req(ReVal$ae_pre)
- req(input$ae_filter)
- req(input$ae_llt)
- req(input$ae_hlt)
- req(input$summary_by)
- req(input$aeRiskYN)
- if (input$aeRiskYN == "Y") {
- req(input$treatment1)
- req(input$treatment2)
- req(input$statistics)
- req(input$alpha)
- }
- req(input$ui_pctdisp)
- req(input$cutoff)
- req(input$sort_opt)
- req(input$sort_by)
- print("AE Summary table process start")
- withProgress(message = "Generating AE Summary table", value = 0, {
- ReVal$toutput <- try(
- adae_r001(
- datain = ReVal$ae_pre,
- population = str_trim(unlist(strsplit(unique(input$popfilter), "~"))[1]),
- AE_Filter = input$ae_filter,
- riskyn = input$aeRiskYN,
- summary_by = input$summary_by,
- ctrlgrp = ifelse(input$aeRiskYN == "Y", input$treatment1, NA),
- trtgrp = ifelse(input$aeRiskYN == "Y", input$treatment2, NA),
- ui_lt = input$ae_llt,
- ui_ht = input$ae_hlt,
- ui_pctdisp = input$ui_pctdisp,
- ui_statistics = input$statistics,
- ui_trttotalyn = input$ui_trttotyn,
- ui_alpha = input$alpha,
- ui_cutoff = input$cutoff,
- ui_sortopt = input$sort_opt,
- ui_sortvar = input$sort_by
- )
- )
- })
- print("AE Summary table process end")
- }
- })
-
- ## Generate Event Analysis
- observe({
- req(ReVal$ae_pre)
- req(input$repName)
- req(input$ae_hlt)
- req(input$hlt_val)
- if (input$ae_hlt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
- req(input$hlt_cat)
- }
- req(input$ae_llt)
- req(input$llt_val)
- if (input$ae_llt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
- req(input$llt_cat)
- }
- req(input$summary_by)
- if (tolower(input$repName) %in% c("event analysis")) {
- print("AE event analysis process start")
- withProgress(message = "Generating AE event analysis", value = 0, {
- ReVal$goutput <- try(event_analysis(
- datain = ReVal$ae_pre$dsin,
- datain_N = ReVal$ae_pre$dout,
- hl_var = input$ae_hlt,
- hl_val = toupper(input$hlt_val),
- hl_scope = toupper(input$hlt_cat),
- ll_var = input$ae_llt,
- ll_val = toupper(input$llt_val),
- ll_scope = toupper(input$llt_cat),
- summary_by = input$summary_by,
- ref_line = input$ref_line
- ))
- })
- print("AE event analysis process end")
- }
- })
-
- ############ Display Panel #############
- ## session output object to check if the graph is created
- output$g_output <- reactive({
- if (!is.null(ReVal$goutput)) {
- return(!is.null(ReVal$goutput))
- }
- })
- outputOptions(output, "g_output", suspendWhenHidden = FALSE)
-
- ## session output object to check if the table is created
- output$t_output <- reactive({
- if (!is.null(ReVal$toutput)) {
- return(!is.null(ReVal$toutput))
+ if (!is.null(adam_read())) {
+ removeUI("#readData")
+ runjs("Shiny.setInputValue('data_upload', true);")
}
- })
- outputOptions(output, "t_output", suspendWhenHidden = FALSE)
-
- ## display the interactive plot object on the dashboard area
- output$plot_output <- plotly::renderPlotly({
- ReVal$goutput$ptly
- })
-
- output$figure_UI <- renderUI({
- req(ReVal$goutput$ptly)
- div(
- plotly::plotlyOutput("plot_output", width = "auto", height = "auto") %>%
- shinycssloaders::withSpinner(type = 5),
- style = "overflow-x: scroll;"
- )
- })
-
- ## title for plot
- output$g_title_UI <- renderText({
- req(ReVal$goutput$ptly)
- rpt_title <- ReVal$goutput$title
- return(HTML(rpt_title))
- })
-
- ## footnote for Plot
- output$g_footnote_UI <- renderText({
- req(ReVal$goutput$ptly)
- rpt_ftnote <- ReVal$goutput$footnote
- return(HTML(rpt_ftnote))
- })
-
- ## display the summary table object on the dashboard area
- output$table_UI <- renderUI({
- req(ReVal$toutput)
- summary_out <- ReVal$toutput$tout
- div(style = "overflow-x: scroll;", htmltools_value(summary_out))
- })
-
- ## title for table
- output$t_title_UI <- renderText({
- req(ReVal$toutput)
- rpt_title <- ReVal$toutput$title
- return(HTML(rpt_title))
- })
-
- ## footnote for table
- output$t_footnote_UI <- renderText({
- req(ReVal$toutput)
- rpt_ftnote <- ReVal$toutput$footnote
- return(HTML(rpt_ftnote))
- })
-
- ############### Listing Generation ###########################
- ## creating listing for the data point selected in the interactive plot
- output$plot_listing <- DT::renderDataTable(
- {
- s <- plotly::event_data("plotly_click", source = "plot_output")
- req(length(s) > 0)
-
- ## getting the click event value key variables
- if (tolower(input$repName) == "forest plot" || tolower(input$repName) == "adae_r001") {
- test <- ReVal$goutput$drill_plt$data[as.numeric(s$key), ]
- } else {
- test <- ReVal$goutput$plot$data[as.numeric(s$key), ]
- }
+ }) %>%
+ bindEvent(adam_read())
- ## Getting Variables for AE plots and merging with key values to get selected records
- if (tolower(input$repName) == "forest plot" || tolower(input$repName) == "volcano plot" ||
- tolower(input$repName) == "adae_r001") {
- display <- ReVal$ae_pre$dout %>%
- select(any_of(
- c(
- "USUBJID",
- "TRTVAR",
- "BYVAR1",
- "DPTVAL",
- "AESER",
- "AEOUT",
- "AESTDT",
- "ASTTM",
- "AEENDT",
- "TRTSTDT",
- "TRTEDT",
- "TRTEMFL"
- )
- ))
- plot_table <- select(test, "BYVAR1", "DPTVAL", "TRTVAR") %>%
- inner_join(display) %>%
- rename(
- !!input$ae_hlt := "BYVAR1",
- !!input$ae_llt := "DPTVAL",
- !!input$trt_var := "TRTVAR"
- )
- }
-
- ## displaying the listing table
-
- plot_table <- plot_table %>% distinct()
- datatable(
- plot_table,
- extensions = "Buttons",
- options = list(
- dom = "Bfrtip",
- buttons = I("colvis"),
- pageLength = 10
- )
- )
- },
- server = FALSE
+ rep_inputs <- mod_report_selection_server(
+ "report_selection_1",
+ sourcedata = reactive(adam_read()$adam),
+ domain = reactive(names(adam_read()$adam)),
+ data_attr = reactive(adam_read()$adam_attrib)
)
- ############### Save Reports ###########################
+ mod_data_check_server(
+ "data_check_1",
+ sourcedata = reactive(adam_read()$adam),
+ domain = reactive(rep_inputs$bdomain())
+ )
- ## getting the file formats selection values for graph, table and data frame
- output$save_fmt_ui <- renderUI({
- req(input$repType)
- if (input$repType == "Table") {
- save_fmt <- c("pdf", "html", "docx")
- } else if (input$repType == "Figure") {
- save_fmt <- c("pdf", "html", "docx", "pptx", "interactive")
- }
- radioButtons("save_fmt", "", choices = save_fmt)
- })
+ filters <- mod_generic_filters_server(
+ "generic_filters_1",
+ sourcedata = reactive(adam_read()$adam),
+ domain = reactive(rep_inputs$bdomain()),
+ repName = reactive(rep_inputs$repName()),
+ repType = reactive(rep_inputs$repType()),
+ trt_var = reactive(rep_inputs$trt_var()),
+ trt_sort = reactive(rep_inputs$trt_sort()),
+ popfilter = reactive(rep_inputs$popfilter())
+ )
- ## generate the file name for the save file and dummy output if graph or table object is empty
- observe({
- req(input$repName)
- req(input$bdomain)
- req(input$save_fmt)
- ReVal$Save_Filename <- paste0(
- input$repName, "_",
- str_replace(input$repnum, "[[:punct:][:space:]]", "_"),
- str_replace_all(Sys.time(), "[[:punct:][:space:]]", "_"),
- ifelse(input$save_fmt == "interactive", "_I.html", paste0(".", input$save_fmt))
+ tout <-
+ mod_toutput_server(
+ "toutput_1",
+ repName = reactive(rep_inputs$repName()),
+ filters = eventReactive(filters(), filters()),
+ popfilter = reactive(rep_inputs$popfilter()),
+ process_btn = reactive(input$process)
)
- if (is.null(ReVal$goutput)) {
- ReVal$goutput$plot <- cowplot::ggdraw() + cowplot::draw_label(
- "Graph not created for this report, might be due to insufficient data",
- size = 9,
- x = 0.05,
- hjust = 0,
- y = 0.5
- )
- ReVal$goutput$title <- NULL
- ReVal$goutput$footnote <- NULL
- ReVal$goutput$rpt_data <- NULL
- }
- if (is.null(ReVal$toutput)) {
- ReVal$toutput$tout <-
- flextable(
- data.frame(Note = "Summary output not created for this report,
- might be due to insufficient data"),
- cwidth = 5,
- cheight = 0.25
- )
- ReVal$toutput$title <- NULL
- ReVal$toutput$footnote <- NULL
- ReVal$toutput$rpt_data <- NULL
- }
- if (!is.null(ReVal$toutput) || !is.null(ReVal$goutput)) {
- if (input$repType == "Table") {
- ReVal$saveObj <- ReVal$toutput
- } else {
- ReVal$saveObj <- ReVal$goutput
- }
- }
- })
+ gout <-
+ mod_goutput_server(
+ "goutput_1",
+ sourcedata = reactive(adam_read()$adam),
+ repName = reactive(rep_inputs$repName()),
+ filters = eventReactive(filters(), filters()),
+ process_btn = reactive(input$process)
+ )
- ## Download the generated report if the data source is local or default
- output$save <- downloadHandler(
- filename = function() {
- ReVal$Save_Filename
- },
- content = function(file) {
- withProgress(
- save_file(
- save_object = ReVal$saveObj,
- file_format = input$save_fmt,
- report_type = input$repType,
- report_name = input$repName,
- file = file
- ),
- message = "Saving file...",
- detail = "This step should take a while.",
- min = 0,
- max = 1,
- value = 1
- )
- }
+ mod_download_report_server(
+ "download_report_1",
+ repType = reactive(rep_inputs$repType()),
+ repName = reactive(rep_inputs$repName()),
+ repNum = reactive(rep_inputs$repnum()),
+ save_fmt = reactive(input$save_fmt),
+ toutput = tout,
+ goutput = gout
)
}
diff --git a/R/app_ui.R b/R/app_ui.R
index 06b25f0..552f7c5 100644
--- a/R/app_ui.R
+++ b/R/app_ui.R
@@ -1,474 +1,201 @@
-################################################################################
-# ui.R
-# This R Script only deconflict_preferfines the Web layout for the Shiny App.
-################################################################################
-
-###### Shiny data size option and reactlog #####
-options(shiny.maxRequestSize = 30 * 1024^4)
-options(shiny.reactlog = TRUE)
-
#' The application User-Interface
#'
#' @param request Internal parameter for `{shiny}`.
-#'
+#' DO NOT REMOVE.
#' @import shiny
#' @noRd
-
-###### Defining Select Choices for Users #########
-
app_ui <- function(request) {
- data_source <- c(
- "Default (CDISC Pilot Data)" = "Default",
- "Local (Study Data)" = "Local"
- )
-
- aeTerm <- c(
- "Reported Term for the Adverse Event (AETERM)" = "AETERM",
- "AE Lowest Level Term (AELLT)" = "AELLT",
- "AE Dictionary-Derived Term (AEDECOD)" = "AEDECOD",
- "AE High Level Term (AEHLT)" = "AEHLT",
- "AE High Level Group Term (AEHLGT)" = "AEHLGT",
- "Primary System Organ Class (AESOC)" = "AESOC",
- "Body System or Organ Class (AEBODSYS)" = "AEBODSYS",
- "FMQ Name (FMQ_NAM)" = "FMQ_NAM"
- )
-
- dashboardPage(
- dashboardHeader(
- title = span("Clinical Visual Analytics for Review and Submission",
- style = "color:#FF9A9E; font-weight:bold;"
- ),
- titleWidth = 600
- ),
- # Begin of Sidebar
- dashboardSidebar(
- fluidRow(
- column( # Begin Data source
- width = 12,
- selectInput("source", "Data Source", choices = data_source),
- conditionalPanel(
- condition = 'input.source=="Local"',
- div("This option is only available", br(),
- "for app developement",
- style = "text-align:center"
+ tagList(
+ # Leave this function for adding external resources
+ golem_add_external_resources(),
+ # Your application UI logic
+ bs4Dash::dashboardPage(
+ header = bs4Dash::dashboardHeader(
+ title = "CVARS",
+ status = "white",
+ border = TRUE,
+ skin = "light",
+ bs4Dash::navbarMenu(
+ id = "navmenu",
+ tooltip(
+ navbarTab(
+ tabName = "Tab1",
+ text = tags$span(icon("gears"), "Report Inputs")
),
- fileInput(
- "analysis_data",
- label = "Import data",
- accept = c(".csv", ".sas7bdat", ".xls", ".xpt", ".Rda"),
- multiple = TRUE
- )
- ), ### end of local data source
- conditionalPanel(
- condition = 'input.source=="Default"',
- div("This option is only available for", br(),
- "training and understanding app", br(),
- "using CDISC data",
- style = "text-align:center"
+ title = "Report Inputs"
+ ),
+ tooltip(
+ navbarTab(
+ tabName = "Tab2",
+ text = tags$span(icon("database"), "Data Check")
),
- selectInput("ADaM_Data_d",
- "CDISC ADaM Data",
- choices = c("ADSL", "ADAE"),
- multiple = TRUE
- )
- ), ### end of Default Data source
-
- uiOutput("readDataBtn_UI"), ### Read data action button placeholder
-
- conditionalPanel(
- condition = "output.dataUpload",
- ### Buttons to process report inputs , create/refresh graph/table
- actionButton("process", "Process Report Input",
- color = "primary",
- style = "color:#fff;background-color:#337ab7;height:25px;
- border-color:#2e6da4;font-size:12px;text-align:center;"
+ title = "Data Check"
+ ),
+ tooltip(
+ navbarTab(
+ tabName = "Tab3",
+ text = tags$span(icon("table-list"), "Table Output")
),
- hr(),
- ### Download button and related file options
- column(
- width = 12,
- downloadButton("save", "SAVE", class = "btn"),
- tags$head(tags$style(".btn{background-color: #337ab7;}"))
+ title = "Table Output"
+ ),
+ tooltip(
+ navbarTab(
+ tabName = "Tab4",
+ text = tags$span(icon("chart-line"), "Graph Output")
),
- column(width = 5, background = "black", uiOutput("save_fmt_ui"))
+ title = "Graph Output"
)
)
- )
- ), ### End of Sidebar Elements
- ### Begin report save input elements
- ### Begin dashboard body
- dashboardBody(
- ### applying Background color for header, side panel and main panel
- style = ("font-size: 10px; background-color: #212F3D ;"),
- tags$head(tags$style(HTML("
- /* logo */
- .skin-blue .main-header .logo {
- background-color: #212F3D;
- }
- /* navbar (rest of the header) */
- .skin-blue .main-header .navbar {
- background-color: #212F3D; font-size: 10px;
- }
- /* main sidebar */
- .skin-blue .main-sidebar {
- background-color: #212F3D; font-size: 10px;
- }
- "))),
- ### Begin the tab panels
- tabBox(
- id = "tabvals",
- width = NULL,
- tabsetPanel(
- ### Tab to for providing report inputs
- tabPanel(
- "Report Inputs",
- # Report, Treatment & population inputs
- box(
- width = 12,
- style = ("font-size: 10px; background-color: #ECF8F8 ;"),
- collapsible = TRUE,
- title = h5("Report Selection"),
- conditionalPanel(
- condition = "output.dataUpload",
- column(
- width = 4,
- uiOutput("report_base_domain_UI"),
- uiOutput("report_TA_UI"),
- uiOutput("report_Type_UI")
- ),
- column(
- width = 4,
- uiOutput("report_Nam_UI"),
- uiOutput("report_Num_UI"),
- uiOutput("report_desc_UI")
- )
+ ),
+ sidebar = bs4Dash::dashboardSidebar(
+ status = "info",
+ skin = "light",
+ minified = FALSE,
+ width = "300px",
+ accordion(
+ id = "load_data",
+ accordionItem(
+ title = tags$strong("Read/Upload Data"),
+ collapsed = FALSE,
+ selectInput(
+ "source",
+ "Data Source",
+ choices = c(
+ "Default (CDISC Pilot Data)" = "Default",
+ "Local (Study Data)" = "Local"
)
),
- # Treatment variable and Population selection
- wellPanel(
- style = ("font-size: 10px; background-color: #ECF8F8 ;"),
- fluidRow(
- h5("Treatment & Population Selection"),
- conditionalPanel(
- condition = "output.dataUpload",
- uiOutput("treatment_population_UI")
- )
+ conditionalPanel(
+ condition = 'input.source=="Local"',
+ fileInput(
+ "analysis_data",
+ label = "Import data",
+ accept = c(".csv", ".sas7bdat", ".xls", ".xpt", ".Rda"),
+ multiple = TRUE
)
),
- # Begin ADAE report Plot Input Elements
conditionalPanel(
- condition = 'output.dataUpload && input.bdomain=="adae"',
- wellPanel(
- style = ("font-size: 10px; background-color: #ECF8F8 ;"),
- fluidRow(
- column(
- width = 3,
- textInput("aeSubset", "Analysis Subset Condition", value = "USUBJID!=''")
- ),
- column(
- width = 3,
- textInput("aeDenomSubset",
- "Denominator Subset Condition",
- value = "STUDYID!=''"
- )
- ),
- conditionalPanel(
- condition = 'output.repName=="adae_r001"',
- column(
- width = 3,
- uiOutput("pct_disp_UI")
- )
- )
- ),
- conditionalPanel(
- condition = 'output.repName=="adae_r001"',
- fluidRow(
- column(
- width = 3,
- radioButtons(
- inputId = "aeBigN",
- label = "Treatment Big N",
- choices = c("Y", "N"),
- selected = "N",
- inline = TRUE
- )
- ),
- column(
- width = 3,
- radioButtons(
- inputId = "aeTrtTot",
- label = "Total treatment",
- choices = c("Y", "N"),
- selected = "N",
- inline = TRUE
- )
- ),
- column(
- width = 3,
- radioButtons(
- inputId = "aeGrpVarMiss",
- label = "Add Missing Grouping Variable",
- choices = c("Y", "N"),
- selected = "N",
- inline = TRUE
- )
- ),
- column(
- width = 3,
- radioButtons(
- inputId = "aeRiskYN",
- label = "Calculate Risk",
- choices = c("Y", "N"),
- selected = "N",
- inline = TRUE
- )
- )
- )
+ condition = 'input.source=="Default"',
+ div(
+ HTML(
+ "This option is only available for
training and understanding
+ app
using CDISC data"
),
- fluidRow(
- column(width = 12, hr(style = "border-top: 1px solid #000000;")),
- column(
- width = 4,
- uiOutput("AE_Event_Filter_UI"),
- selectInput(
- "period",
- "Period",
- choices = c("Overall Duration", "Other")
- ),
- conditionalPanel(
- condition = 'input.period == "Other"',
- numericInput(
- "period_please_specify",
- HTML("Please enter residual period (in days)"),
- value = 30,
- min = 0,
- max = 10^5
- )
- )
- ),
- column(
- width = 4,
- conditionalPanel(
- condition = 'output.repName=="forest plot" || output.repName=="volcano plot"
- || output.repName=="tornado plot"||output.repName=="adae_r001"',
- selectInput(
- "summary_by",
- "Summary By",
- choices = c("Participants" = "Patients", "Events" = "Events")
- ),
- ),
- selectInput("ae_hlt", "Higher Level Event Term",
- choices = aeTerm,
- selected = c("Body System or Organ Class (AEBODSYS)" = "AEBODSYS")
- ),
- conditionalPanel(
- condition = 'output.repName!=="tornado plot"',
- selectInput("ae_llt", "Lower Level Event Term",
- choices = aeTerm,
- selected = c("AE Dictionary-Derived Term (AEDECOD)" = "AEDECOD")
- )
- ),
- conditionalPanel(
- condition = 'output.repName=="forest plot" || output.repName=="volcano plot"
- || (output.repName=="adae_r001" && input.aeRiskYN=="Y")',
- selectInput(
- "statistics",
- "Measure of Association",
- choices = c("Risk Ratio", "Risk Difference")
- )
- )
- ),
- column(
- width = 4,
- style = "border-left: 1px solid",
- conditionalPanel(
- condition =
- 'output.repName=="forest plot" || output.repName=="volcano plot" ||
- (output.repName=="adae_r001" && input.aeRiskYN=="Y")',
- numericInput(
- "alpha",
- "Alpha Value(CI)",
- value = 0.05,
- min = 0.01,
- max = 0.1
- )
- ),
- conditionalPanel(
- condition = 'output.repName=="forest plot" || output.repName=="volcano plot"',
- numericInput(
- "pvalcut",
- "p Value Cutoff",
- value = 0.05,
- min = 0.01,
- max = 0.1
- ),
- numericInput(
- "X_ref",
- "Risk Reference Lines",
- value = 0,
- )
- ),
- conditionalPanel(
- condition = 'output.repName=="forest plot"',
- selectInput(
- "riskScale",
- "Risk Axis Scale",
- choices = c("Log10", "Identity", "Log2")
- )
- ),
- conditionalPanel(
- condition = 'output.repName=="event analysis"',
- numericInput("ref_line", "Reference Line (%)", min = 0, max = 100, value = 5)
- )
- ),
- column(width = 12, hr())
- ),
- fluidRow(
- column(
- width = 4,
- conditionalPanel(
- condition = 'output.repName=="volcano plot"||
- (output.repName=="adae_r001" && input.aeRiskYN=="Y")',
- uiOutput("treatment1_UI"),
- br()
- ),
- conditionalPanel(
- condition = 'output.repName=="forest plot"',
- uiOutput("ctrlgrp_UI"),
- br(),
- ),
- conditionalPanel(
- condition = 'output.repName=="forest plot"||output.repName=="adae_r001"',
- selectInput(
- "sort_opt",
- "Sorting Option",
- choices = c("Ascending", "Descending", "Alphabetical")
- )
- )
- ),
- column(
- width = 4,
- conditionalPanel(
- condition = 'output.repName=="volcano plot"||
- (output.repName=="adae_r001" && input.aeRiskYN=="Y")',
- uiOutput("treatment2_UI"),
- br()
- ),
- conditionalPanel(
- condition = 'output.repName=="forest plot"',
- uiOutput("trtgrp_UI"),
- br(),
- br(),
- ),
- conditionalPanel(
- condition = 'output.repName!=="volcano plot"',
- uiOutput("aeSortBy_UI")
- )
- ),
- column(
- width = 4,
- style = "border-left: 1px solid",
- conditionalPanel(
- condition = 'output.repName=="forest plot" ||
- output.repName=="volcano plot" || output.repName=="adae_r001" ',
- sliderInput(
- "cutoff",
- "Cutoff of Incidence (%)",
- min = 0,
- max = 10,
- value = 5
- )
- ),
- br(),
- conditionalPanel(
- condition = 'output.repName=="forest plot" ||
- output.repName=="volcano plot"',
- selectInput(
- "pvalue_label",
- "P-value Transformation",
- choices = c("None", "-log10"),
- selected = "None"
- )
- )
- )
- )
- )
- )
- ), # End of Report input tab
- ### Tab to view analysis data loaded to shiny app
- tabPanel(
- "Data Check",
- fluidRow(
- conditionalPanel(
- condition = "output.dataUpload",
- box(
- width = 12,
- style = ("font-size: 10px; background-color: #ECF8F8 ;"),
- uiOutput("source_data_varlist_UI"),
- column(
- width = 12,
- style = "height:500px; overflow-y: scroll;overflow-x: scroll;",
- DT::dataTableOutput("sourcedata_display")
- ),
- uiOutput("categorical_variable_list_UI"),
- DT::dataTableOutput("distinct_value_display")
- )
- )
- )
- ),
- # Begin graph display and input element
- tabPanel(
- "Graph Output",
- conditionalPanel(
- condition = "output.g_output",
- column(
- style = ("font-size: 10px; background-color: #ECF8F8 ;"),
- width = 12,
- div(htmlOutput("g_title_UI"), style = "white-space: pre"),
- div(uiOutput("figure_UI")),
- div(htmlOutput("g_footnote_UI"), style = "white-space: pre")
+ style = "text-align:center"
+ ),
+ selectInput("ADaM_Data_d",
+ "CDISC ADaM Data",
+ choices = c("ADSL", "ADAE", "CM"),
+ multiple = TRUE
)
),
- wellPanel(
- style = ("font-size: 10px; background-color: #ECF8F8 ;"),
- fluidRow(
- column(
- width = 12,
- conditionalPanel(
- condition = 'output.repName=="event analysis"',
- column(width = 3, uiOutput("aeHLT_list_UI")),
- column(width = 3, uiOutput("aeHLT_query_cat_UI")),
- column(width = 3, uiOutput("aeLLT_list_UI")),
- column(width = 3, uiOutput("aeLLT_query_cat_UI"))
- ),
- conditionalPanel(
- condition = 'output.repName=="forest plot"||output.repName=="volcano plot"',
- DT::dataTableOutput("plot_listing")
- )
- )
- )
+ div(
+ tagAppendAttributes(
+ actionButton(
+ "readData",
+ "Read Data"
+ ),
+ class = "sidebar-btn"
+ ),
+ style = "display: flex; justify-content: center;"
)
- ), # End graph display and input element
- # Begin Table display Tab and Input element
- tabPanel(
- "Table Output",
- conditionalPanel(
- condition = "output.t_output",
- wellPanel(
- style = ("font-size: 10px; background-color: #ECF8F8 ;"),
- fluidRow(
- column(
- width = 12,
- div(htmlOutput("t_title_UI"), style = "white-space: pre"),
- div(uiOutput("table_UI")),
- div(htmlOutput("t_footnote_UI"), style = "white-space: pre")
- )
- )
+ )
+ ),
+ conditionalPanel(
+ condition = "input.data_upload",
+ div(
+ tagAppendAttributes(
+ actionButton(
+ "process",
+ "Run Report"
+ ),
+ class = "sidebar-btn"
+ ),
+ style = "display: flex; justify-content: center;
+ padding-left: 1rem; padding-right: 1rem; padding-bottom: 0.75rem;"
+ )
+ ),
+ conditionalPanel(
+ condition = "input.data_upload",
+ accordion(
+ id = "save_down",
+ accordionItem(
+ title = tags$strong("Download Report"),
+ collapsed = FALSE,
+ div(
+ radioButtons(
+ "save_fmt",
+ "",
+ choices = "pdf",
+ ),
+ style = "display:flex; justify-content: center; margin-right: 35px;"
+ ),
+ div(
+ mod_download_report_ui("download_report_1"),
+ style = "display:flex; justify-content: center; padding-bottom: 7px;"
)
)
- ) # End Table display Tab and Input element
- ) # End of tabset panel
- ) # End of tab box
- ) # end of dashboard body
- ) # end of dashboard page
+ )
+ )
+ ),
+ body = bs4Dash::dashboardBody(
+ tabItems(
+ tabItem(
+ tabName = "Tab1",
+ mod_data_read_ui("data_read_1"),
+ div(id = "rep_input", mod_report_selection_ui("report_selection_1")),
+ div(id = "gen_filter", mod_generic_filters_ui("generic_filters_1"))
+ ),
+ tabItem(
+ tabName = "Tab2",
+ mod_data_check_ui("data_check_1")
+ ),
+ tabItem(
+ tabName = "Tab3",
+ mod_toutput_ui("toutput_1")
+ ),
+ tabItem(
+ tabName = "Tab4",
+ mod_goutput_ui("goutput_1")
+ )
+ )
+ ),
+ fullscreen = TRUE,
+ dark = NULL,
+ help = NULL,
+ scrollToTop = TRUE,
+ preloader =
+ list(
+ html = tagList(
+ waiter::spin_inner_circles(),
+ "Loading CVARS..."
+ ),
+ color = "#8DCBE6"
+ )
+ )
+ )
+}
+
+#' Add external Resources to the Application
+#'
+#' This function is internally used to add external
+#' resources inside the Shiny application.
+#'
+#' @import shiny
+#' @importFrom golem add_resource_path activate_js favicon bundle_resources
+#' @noRd
+golem_add_external_resources <- function() {
+ add_resource_path(
+ "www",
+ app_sys("app/www")
+ )
+
+ tags$head(
+ favicon(),
+ bundle_resources(
+ path = app_sys("app/www"),
+ app_title = "cvars"
+ ),
+ useShinyjs()
+ )
}
diff --git a/R/cvars-package.R b/R/cvars-package.R
index 3a981de..9279588 100644
--- a/R/cvars-package.R
+++ b/R/cvars-package.R
@@ -1,4 +1,4 @@
-#' @import shiny ggplot2 dplyr scales shinyWidgets shinydashboard
+#' @import shiny ggplot2 dplyr scales shinyWidgets
#' flextable epitools htmltools tools officer
#' @importFrom DT addRow colReorder datatable formatDate saveWidget
#' formatPercentage formatRound formatStyle selectCells
@@ -22,6 +22,26 @@
## usethis namespace: start
+#' @importFrom bs4Dash navbarTab
+#' @importFrom bs4Dash accordion
+#' @importFrom bs4Dash accordionItem
+#' @importFrom bs4Dash box
+#' @importFrom bs4Dash boxSidebar
+#' @importFrom bs4Dash bs4Card
+#' @importFrom bs4Dash dashboardBody
+#' @importFrom bs4Dash dashboardHeader
+#' @importFrom bs4Dash dashboardPage
+#' @importFrom bs4Dash dashboardSidebar
+#' @importFrom bs4Dash menuItem
+#' @importFrom bs4Dash menuItemOutput
+#' @importFrom bs4Dash navbarTab
+#' @importFrom bs4Dash renderMenu
+#' @importFrom bs4Dash sidebarMenu
+#' @importFrom bs4Dash tabBox
+#' @importFrom bs4Dash tabItem
+#' @importFrom bs4Dash tabItems
+#' @importFrom bs4Dash tooltip
+#' @importFrom bs4Dash updateNavbarTabs
#' @importFrom magrittr %>%
## usethis namespace: end
NULL
diff --git a/R/data.R b/R/data.R
index 83db121..2608fe4 100644
--- a/R/data.R
+++ b/R/data.R
@@ -59,3 +59,13 @@
#' @format List containing 2 data frames `dsin` and `dout` (to be passed in `event_analysis`) and
#' `bigN` value
"event_df"
+
+#' CM
+#'
+#' Concomitant Medications Dataset
+#'
+#' @source ,
+#' downloaded 2023-08-24
+#'
+#' @format Data frame with 7510 rows and 21 variables
+"cm"
diff --git a/R/event_analysis.R b/R/event_analysis.R
index e2b9969..1a9901b 100644
--- a/R/event_analysis.R
+++ b/R/event_analysis.R
@@ -79,7 +79,7 @@ event_analysis <- function(datain = NULL,
if (hl_var %in% c("FMQ_NAM", "SMQ_NAM", "CQ_NAM")) {
hl_summ <- event_mcat %>% # filter(BYVAR1%in%hl_val1) %>%
filter(str_detect(toupper(BYVAR1), toupper(hl_val1))) %>%
- mutate(Percent = paste(PCT, "% \n PT:", DPTVAL)) %>%
+ mutate(Percent = paste(PCT, "% \n Low Term:", DPTVAL)) %>%
group_by(TRTVAR) %>%
mutate(
pct = as.numeric(PCT),
@@ -88,7 +88,7 @@ event_analysis <- function(datain = NULL,
} else {
hl_summ <- event_mcat %>% # filter(BYVAR1%in%hl_val1) %>%
filter(toupper(BYVAR1) == toupper(hl_val1)) %>%
- mutate(Percent = paste(PCT, "% \n PT:", DPTVAL)) %>%
+ mutate(Percent = paste(PCT, "% \n Low Term:", DPTVAL)) %>%
group_by(TRTVAR) %>%
mutate(
pct = as.numeric(PCT),
@@ -148,7 +148,7 @@ event_analysis <- function(datain = NULL,
)
pt_plot1 <- pt_plot + ggtitle(paste0(str_to_title(ll_val), " PT"))
- pt_ptly <- plotly::ggplotly(pt_plot, tooltip = "text") %>%
+ pt_ptly <- plotly::ggplotly(pt_plot, tooltip = "text", source = "plot_output") %>%
plotly::add_annotations(
text = paste0(str_to_title(ll_val), " PT"),
x = 0.5,
@@ -209,7 +209,7 @@ event_analysis <- function(datain = NULL,
toupper(sub("\\_.*", "", hl_var)),
" Categorization of ", str_to_title(hl_val)
), width = 80))
- query_ptly <- plotly::ggplotly(query_plot, tooltip = "text") %>%
+ query_ptly <- plotly::ggplotly(query_plot, tooltip = "text", source = "plot_output") %>%
plotly::add_annotations(
text = str_wrap(paste0(
toupper(sub("\\_.*", "", hl_var)),
@@ -226,7 +226,6 @@ event_analysis <- function(datain = NULL,
font = list(size = 12)
) %>%
plotly::layout(legend = list(title = ""))
-
inter_fig <- plotly::subplot(
pt_ptly,
query_ptly,
@@ -235,7 +234,7 @@ event_analysis <- function(datain = NULL,
shareY = TRUE,
widths = c(0.5, 0.5),
margin = 0.005
- ) %>% plotly::layout(showlegend = TRUE)
+ ) %>% plotly::layout(showlegend = TRUE, height = 600)
static_fig <- cowplot::plot_grid(
pt_plot1,
@@ -251,17 +250,15 @@ event_analysis <- function(datain = NULL,
"* N is the total number of ",
ifelse(tolower(summary_by) == "patients", "participants", "events"),
". \n",
- "Classifications of adverse events are based on the Medical Dictionary for Regulatory
- Activities (MedDRA v21.1). \n",
+ "Classifications of adverse events are based on the Medical Dictionary for Regulatory Activities (MedDRA v21.1). \n", # nolint
"FMQ classification is based on FDA FMQ consolidated list. \n",
"Dashed Horizontal line represents incidence percentage reference line. \n",
- "Totals for the No. of Participants/Events at a higher level are not necessarily the sum of
- those at the lower levels since a participant may report two or more \n",
+ "Totals for the No. of Participants/Events at a higher level are not necessarily the sum of those at the lower levels since a participant may report two or more. \n", # nolint
"PT - Preferred Term ; FMQ - FDA MedDRA Queries \n",
ifelse(
tolower(summary_by) == "patients",
"The number of participants reporting at least 1 occurrence of the event specified.",
- "Event counts are the sum of individual occurrences within that category"
+ "Event counts are the sum of individual occurrences within that category."
)
)
@@ -271,6 +268,7 @@ event_analysis <- function(datain = NULL,
ptly = inter_fig,
plot = static_fig,
rpt_data = hl_summ,
+ rpt_data1 = ll_summ,
title = title,
footnote = footnote
)
diff --git a/R/event_interval.R b/R/event_interval.R
new file mode 100644
index 0000000..0c385a3
--- /dev/null
+++ b/R/event_interval.R
@@ -0,0 +1,158 @@
+#' Patient-Level Interval Plot
+#'
+#' @param datain Input events/concomitant medication dataset
+#' @param startvar Event/Treatment Start Day Variable name (X axis)
+#' @param endvar Event/Treatment End Day Variable name (X axis)
+#' @param yvar Variable containing event terms or medications to be plotted in Y axis
+#' @param seriesvar Variable to stratify plot by color or NA to have no stratification
+#' @param subjectid Selected `USUBJID` variable value
+#' @param series_color List of colors to be assigned to levels in `seriesvar` or
+#' NA to use package defaults
+#' @param xaxislab Label for plot X axis
+#' @param yaxislab Label for plot Y axis
+#'
+#' @return : a list containing 3 objects
+#' \itemize{
+#' \item ptly - Interactive plot output for display
+#' \item plot - Static plot output for saving externally
+#' \item rpt_data - Dataset used to create forest plot, for validation purpose
+#' }
+#' @export
+#'
+#' @examples
+#' data(adae)
+#' interval_plot(
+#' datain = adae,
+#' startvar = "ASTDY",
+#' endvar = "AENDY",
+#' yvar = "AEDECOD",
+#' seriesvar = "AESEV",
+#' subjectid = "01-701-1302",
+#' series_color = NA,
+#' yaxislab = "Reported Term for the Adverse Event"
+#' )$ptly
+interval_plot <- function(datain,
+ startvar,
+ endvar,
+ yvar,
+ seriesvar,
+ subjectid,
+ series_color = NA,
+ xaxislab = "Start and End Study Day",
+ yaxislab = "") {
+ # Filter subject and get info
+ ad_plot <- datain %>%
+ filter(USUBJID == subjectid) %>%
+ mutate(Status = case_when(
+ (is.na(get(startvar)) & get(endvar) >= 0) ~ "End Day",
+ (is.na(get(endvar)) & get(startvar) >= 0) ~ "Start Day",
+ (!is.na(get(startvar)) & !is.na(get(endvar))) ~ "Complete",
+ TRUE ~ "Remove"
+ )) %>%
+ filter(Status != "Remove")
+ # Check if no data left and return accordingly
+ if (nrow(ad_plot) == 0) {
+ output <- empty_plot(
+ message = "No data for this participant/period",
+ fontsize = 4
+ )
+ return(list(ptly = output$ptly, plot = output$plot, rpt_data = ad_plot))
+ }
+ if (is.na(seriesvar) || (!seriesvar %in% names(ad_plot))) {
+ seriesvar <- "TOTAL"
+ ad_plot[[seriesvar]] <- "All"
+ }
+ # If colors not preset - set here for analysis variable
+ if (all(is.null(names(series_color)))) {
+ series_color <- g_seriescol(ad_plot, series_color, seriesvar)
+ }
+ # Hover Information:
+ ad_plot <- ad_plot %>%
+ select(all_of(c("USUBJID", startvar, endvar, yvar, seriesvar, "Status"))) %>%
+ mutate(
+ HOVER_TEXT = paste0(
+ !!sym(yvar), "\n",
+ "Start Day: ", !!sym(startvar), "\n",
+ "End Day: ", !!sym(endvar), "\n",
+ !!sym(seriesvar)
+ ),
+ HOVER_TEXT = gsub(": NA", ": -", HOVER_TEXT),
+ !!yvar := as.factor(!!sym(yvar))
+ )
+ # Use data with both dates present for segment plot
+ segmentdata <- ad_plot %>%
+ filter(Status == "Complete")
+
+ # Use data with either Start or end dates only for scatter plot
+ scatterdata <- ad_plot %>%
+ filter(Status != "Complete" | !!sym(startvar) == !!sym(endvar)) %>%
+ tidyr::pivot_longer(c(startvar, endvar), names_to = "key", values_to = "Value") %>%
+ filter(!is.na(Value)) %>%
+ select(-key) %>%
+ distinct(.keep_all = TRUE)
+
+ # Create ggplot object - segment plot for Complete intervals and scatter for incomplete
+ gplot <- ggplot(mapping = aes(text = HOVER_TEXT)) +
+ scale_color_manual(name = "", values = series_color) +
+ labs(x = yaxislab, y = xaxislab) +
+ coord_flip() +
+ theme_bw() +
+ theme(
+ axis.title.x = element_text(size = 8),
+ axis.title.y = element_text(size = 10),
+ plot.margin = unit(c(0, 0, 0, 0), "cm")
+ )
+ # Check if data exists for intervals
+ if (nrow(segmentdata) != 0) {
+ gplot <- gplot +
+ geom_linerange(
+ data = segmentdata,
+ aes(
+ ymin = !!sym(startvar), ymax = !!sym(endvar),
+ x = !!sym(yvar), group = !!sym(seriesvar),
+ color = !!sym(seriesvar)
+ ),
+ position = position_dodge(width = 0.3),
+ size = 1.2
+ )
+ # Convert to plotly object
+ splotly <- plotly::ggplotly(gplot, tooltip = "text")
+ }
+
+ # Check if data exists for dot plot
+ if (nrow(scatterdata) != 0) {
+ # Assign shapes by Status
+ shapelist <- c("End Day" = 18, "Start Day" = 17, "Complete" = 15)
+ gplot <- gplot +
+ geom_point(
+ data = scatterdata,
+ aes(
+ y = Value, x = !!sym(yvar),
+ shape = Status,
+ color = !!sym(seriesvar)
+ ),
+ size = 1.5,
+ position = position_dodge(width = 0.3)
+ ) +
+ scale_shape_manual(name = "", values = shapelist)
+ # Convert to plotly object
+ splotly <- plotly::ggplotly(gplot, tooltip = "text")
+ }
+
+ # To remove the duplicate values in legend and edit labels
+ legdf <- data.frame(
+ id = seq_along(splotly$x$data),
+ legend_entries = unlist(lapply(splotly$x$data, "[[", "name"))
+ )
+ legdf$legend_group <- gsub(
+ "\\(|\\)", "",
+ gsub(",1", ",Complete", legdf$legend_entries)
+ )
+ legdf$is_first <- !duplicated(legdf$legend_group)
+ for (i in legdf$id) {
+ splotly$x$data[[i]]$name <- legdf$legend_group[[i]]
+ splotly$x$data[[i]]$legendgroup <- splotly$x$data[[i]]$name
+ if (!legdf$is_first[[i]]) splotly$x$data[[i]]$showlegend <- FALSE
+ }
+ return(list(plot = gplot, ptly = splotly, rpt_data = ad_plot))
+}
diff --git a/R/forest_plot.R b/R/forest_plot.R
index bd1c094..fa9e616 100644
--- a/R/forest_plot.R
+++ b/R/forest_plot.R
@@ -80,6 +80,11 @@ forest_plot <-
pvalcut = 0.05,
trtbign = "Y",
scale_trans = "identity") {
+ # Check risk data exists:
+ if (nrow(datain) == 0) {
+ output <- empty_plot()
+ return(list(ptly = output$ptly, plot = output$plot, rpt_data = datain))
+ }
## If trtbign is Y (default) then treatment label gets (N=count) added:
if (trtbign == "Y") {
datain <- datain %>% mutate(TRTTXT = paste0(TRTVAR, " (N=", TOTAL_N, ")"))
@@ -217,22 +222,22 @@ forest_plot <-
source = "plot_output"
)
+
+ splotly <- splotly %>%
+ plotly::layout(xaxis = list(side = "top"))
+
# Fixing legend with parantheses
for (i in seq_along(splotly$x$data)) {
if (!is.null(splotly$x$data[[i]]$name)) {
splotly$x$data[[i]]$name <- sub(
"\\(", "",
- sapply(lapply(strsplit(
- splotly$x$data[[i]]$name,
- ","
- ), head, -1), paste, collapse = ",")
- ) # [1]
+ sub(
+ ",1,NA\\)|,1\\)", "",
+ splotly$x$data[[i]]$name
+ )
+ )
}
}
- splotly <- splotly %>%
- plotly::layout(xaxis = list(side = "top"))
-
-
### Prepare Data for forest plot:
# Adding treatment pair, remove count from hover info
dat_out <- dat_out %>%
@@ -418,9 +423,6 @@ forest_plot <-
size = 8, xanchor = "center", yanchor = "top", font = list(size = 8)
)
)
-
-
-
inter_fig$x$source <- "plot_output"
### Combine for For static ggplot output for download purposes:
@@ -480,15 +482,14 @@ forest_plot <-
"* N is the total number of ",
ifelse(tolower(summary_by) == "patients", "participants", "events"),
". \nClassifications of adverse events are based on the Medical Dictionary for Regulatory ",
- "Activities (MedDRA v21.1). \nDashed Vertical line represents risk value reference line \n",
+ "Activities (MedDRA v21.1). \nDashed Vertical line represents risk value reference line. \n",
"Totals for the No. of Participants/Events at a higher level are not necessarily ",
- "the sum of those at the lower levels since a participant may report two or more \n",
+ "the sum of those at the lower levels since a participant may report two or more. \n",
ifelse(tolower(summary_by) == "patients",
"The number of participants reporting at least 1 occurrence of the event specified.",
- "Event counts are the sum of individual occurrences within that category"
+ "Event counts are the sum of individual occurrences within that category."
)
)
-
return(list(
ptly = inter_fig,
plot = static_fig,
diff --git a/R/global.R b/R/global.R
index 6e91490..18b41ad 100644
--- a/R/global.R
+++ b/R/global.R
@@ -83,5 +83,10 @@ globalVariables(c(
"FMQ_NAM",
"USUBJID",
"key",
- ":="
+ ":=",
+ "curve_n",
+ "point_n",
+ "Status",
+ "Value",
+ "ASEV"
))
diff --git a/R/mod_data_check.R b/R/mod_data_check.R
new file mode 100644
index 0000000..c11ef90
--- /dev/null
+++ b/R/mod_data_check.R
@@ -0,0 +1,126 @@
+#' data_check UI Function
+#'
+#' @description A shiny Module.
+#'
+#' @param id,input,output,session Internal parameters for {shiny}.
+#'
+#' @noRd
+#'
+#' @importFrom shiny NS tagList
+mod_data_check_ui <- function(id) {
+ ns <- NS(id)
+ tagList(
+ fluidRow(
+ column(
+ width = 6,
+ box(
+ id = ns("box_1"),
+ title = tags$strong("Variable Check"),
+ maximizable = TRUE,
+ width = 12,
+ varSelectInput(ns("data_varlist"),
+ "Select Variables to be viewed",
+ data = NULL,
+ selected = NULL,
+ multiple = TRUE,
+ width = "50vw"
+ ),
+ div(
+ DT::dataTableOutput(ns("sourcedata_display")),
+ style = "overflow-x: scroll;"
+ )
+ )
+ ),
+ column(
+ width = 6,
+ box(
+ id = ns("box_2"),
+ title = tags$strong("Distinct Values Check"),
+ maximizable = TRUE,
+ width = 12,
+ varSelectInput(ns("categorical_variable"),
+ "Select Variable to see distinct values",
+ data = NULL,
+ selected = NULL,
+ multiple = TRUE,
+ width = "50vw"
+ ),
+ div(
+ DT::dataTableOutput(ns("distinct_value_display")),
+ style = "overflow-x: scroll;"
+ )
+ )
+ )
+ )
+ )
+}
+
+#' data_check Server Functions
+#'
+#' @noRd
+mod_data_check_server <- function(id, sourcedata, domain) {
+ moduleServer(id, function(input, output, session) {
+ ns <- session$ns
+
+ observe({
+ req(sourcedata())
+ req(domain())
+
+ updateVarSelectInput(
+ session,
+ "data_varlist",
+ data = sourcedata()[[domain()]],
+ selected = NULL
+ )
+
+ updateVarSelectInput(
+ session,
+ "categorical_variable",
+ data = sourcedata()[[domain()]],
+ selected = NULL
+ )
+ })
+
+ output$sourcedata_display <- DT::renderDataTable(
+ {
+ req(input$data_varlist)
+
+ data_lkup <- sourcedata()[[domain()]] %>%
+ select(unlist(strsplit(paste(input$data_varlist, collapse = ","), ",")))
+
+ datatable(
+ data_lkup,
+ extensions = "Buttons",
+ options = list(
+ dom = "Bfrtip",
+ buttons = I("colvis"),
+ pageLength = 10
+ )
+ )
+ },
+ server = FALSE
+ )
+
+ output$distinct_value_display <- DT::renderDataTable(
+ {
+ req(input$categorical_variable)
+
+ if (length(input$categorical_variable) > 0) {
+ distinct_value <-
+ distinct(sourcedata()[[domain()]], !!!input$categorical_variable)
+
+ datatable(
+ distinct_value,
+ extensions = "Buttons",
+ options = list(
+ dom = "Bfrtip",
+ buttons = I("colvis"),
+ pageLength = 10
+ )
+ )
+ }
+ },
+ server = FALSE
+ )
+ })
+}
diff --git a/R/mod_data_read.R b/R/mod_data_read.R
new file mode 100644
index 0000000..6dc87c7
--- /dev/null
+++ b/R/mod_data_read.R
@@ -0,0 +1,37 @@
+#' data_read UI Function
+#'
+#' @description A shiny Module.
+#'
+#' @param id,input,output,session Internal parameters for {shiny}.
+#'
+#' @noRd
+#'
+#' @importFrom shiny NS tagList
+mod_data_read_ui <- function(id) {
+ ns <- NS(id)
+ tagList()
+}
+
+#' data_read Server Functions
+#'
+#' @noRd
+mod_data_read_server <-
+ function(id, source, df_adam, analysis_data, read_btn) {
+ moduleServer(id, function(input, output, session) {
+ ns <- session$ns
+
+ df_read <- reactive({
+ req(source())
+ if (source() == "Default") {
+ adam_data <- paste(df_adam(), collapse = ",")
+ } else {
+ adam_data <- analysis_data()
+ }
+ adam <- data_read(
+ ui_data_source = source(),
+ ui_adam_data = adam_data
+ )
+ }) %>%
+ bindEvent(read_btn())
+ })
+ }
diff --git a/R/mod_download_report.R b/R/mod_download_report.R
new file mode 100644
index 0000000..64572c9
--- /dev/null
+++ b/R/mod_download_report.R
@@ -0,0 +1,110 @@
+#' download_report UI Function
+#'
+#' @description A shiny Module.
+#'
+#' @param id,input,output,session Internal parameters for {shiny}.
+#'
+#' @noRd
+#'
+#' @importFrom shiny NS tagList
+mod_download_report_ui <- function(id) {
+ ns <- NS(id)
+ tagList(
+ div(
+ id = ns("btn_down"),
+ downloadButton(
+ ns("save_btn"),
+ "Save Report",
+ class = "download-btn"
+ )
+ )
+ )
+}
+
+#' download_report Server Functions
+#'
+#' @noRd
+mod_download_report_server <- function(id, repType, repName, repNum, save_fmt, toutput, goutput) {
+ moduleServer(id, function(input, output, session) {
+ ns <- session$ns
+
+ rv <- reactiveValues(
+ saveObj = NULL,
+ Save_Filename = NULL,
+ g_ind = FALSE,
+ t_ind = FALSE
+ )
+
+ observe({
+ req(repType())
+ req(repName())
+ req(repNum())
+ req(save_fmt())
+ rv$Save_Filename <- paste0(
+ repName(), "_",
+ str_replace(repNum(), "[[:punct:][:space:]]", "_"),
+ str_replace_all(Sys.time(), "[[:punct:][:space:]]", "_"),
+ ifelse(save_fmt() == "interactive", "_I.html", paste0(".", save_fmt()))
+ )
+ })
+
+ observe({
+ if (repType() == "Table") {
+ req(toutput())
+ } else {
+ req(goutput())
+ }
+
+ print("create save report object start")
+
+ if (!is.null(toutput()) || !is.null(goutput())) {
+ if (repType() == "Table") {
+ rv$t_ind <- TRUE
+ rv$saveObj <- toutput()
+ } else {
+ rv$g_ind <- TRUE
+ rv$saveObj <- goutput()
+ }
+ }
+ print("save report object created")
+ }) %>%
+ bindEvent(list(repType(), toutput(), goutput(), save_fmt()))
+
+ observe({
+ if (is.null(rv$saveObj)) {
+ disable("save_btn")
+ } else {
+ if (repType() == "Table") {
+ toggleState("save_btn", condition = rv$t_ind)
+ } else {
+ toggleState("save_btn", condition = rv$g_ind)
+ }
+ }
+ })
+
+ ## Download the generated report if the data source is local or default
+ output$save_btn <- downloadHandler(
+ filename = function() {
+ rv$Save_Filename
+ },
+ content = function(file) {
+ withProgress(
+ save_file(
+ save_object = rv$saveObj,
+ file_format = save_fmt(),
+ report_type = repType(),
+ report_name = repName(),
+ file = file
+ ),
+ message = "Saving file...",
+ detail = "This step should take a while.",
+ min = 0,
+ max = 1,
+ value = 1
+ )
+ }
+ )
+
+ return(reactive(rv$Save_Filename))
+ })
+}
diff --git a/R/mod_generic_filters.R b/R/mod_generic_filters.R
new file mode 100644
index 0000000..59d162b
--- /dev/null
+++ b/R/mod_generic_filters.R
@@ -0,0 +1,566 @@
+#' generic_filters UI Function
+#'
+#' @description A shiny Module.
+#'
+#' @param id,input,output,session Internal parameters for {shiny}.
+#'
+#' @noRd
+#'
+#' @importFrom shiny NS tagList
+mod_generic_filters_ui <- function(id) {
+ ns <- NS(id)
+ tagList(
+ box(
+ id = ns("box_1"),
+ title = tags$strong("Subsetting Conditions"),
+ maximizable = TRUE,
+ width = 12,
+ fluidRow(
+ column(
+ width = 4,
+ textInput(ns("aeSubset"),
+ "Analysis Subset Condition",
+ value = "USUBJID!=''"
+ )
+ ),
+ column(
+ width = 4,
+ textInput(ns("aeDenomSubset"),
+ "Denominator Subset Condition",
+ value = "STUDYID!=''"
+ )
+ ),
+ column(
+ width = 4,
+ selectInput(
+ inputId = ns("ui_pctdisp"),
+ label = "Percentage Denominator",
+ choices = NULL
+ )
+ )
+ )
+ ),
+ box(
+ id = ns("adae_r001"),
+ title = tags$strong("AE Summary Table Inputs"),
+ maximizable = TRUE,
+ width = 12,
+ fluidRow(
+ column(
+ width = 2,
+ radioButtons(
+ inputId = ns("aeBigN"),
+ label = "Treatment Big N",
+ choices = c("Y", "N"),
+ selected = "N",
+ inline = TRUE
+ )
+ ),
+ column(
+ width = 2,
+ offset = 1,
+ radioButtons(
+ inputId = ns("aeTrtTot"),
+ label = "Total treatment",
+ choices = c("Y", "N"),
+ selected = "N",
+ inline = TRUE
+ )
+ ),
+ column(
+ width = 3,
+ radioButtons(
+ inputId = ns("aeGrpVarMiss"),
+ label = "Add Missing Grouping Variable",
+ choices = c("Y", "N"),
+ selected = "N",
+ inline = TRUE
+ )
+ ),
+ column(
+ width = 2,
+ offset = 1,
+ radioButtons(
+ inputId = ns("aeRiskYN"),
+ label = "Calculate Risk",
+ choices = c("Y", "N"),
+ selected = "N",
+ inline = TRUE
+ )
+ )
+ )
+ ),
+ box(
+ id = ns("box_2"),
+ title = tags$strong("Generic Inputs"),
+ maximizable = TRUE,
+ width = 12,
+ fluidRow(
+ column(
+ width = 4,
+ selectInput(
+ ns("ae_filter"),
+ "Adverse Event Filter(s)",
+ choices = c(
+ "Any", "Treatment Emergent", "Serious", "Drug-related", "Mild", "Moderate",
+ "Severe", "Recovered/Resolved", "Recovering/Resolving",
+ "Not Recovered/Not Resolved", "Fatal"
+ ),
+ selected = "Any",
+ multiple = TRUE
+ )
+ ),
+ column(
+ width = 4,
+ selectInput(
+ ns("period"),
+ "Period",
+ choices = c("Overall Duration", "Other")
+ )
+ ),
+ column(
+ width = 4,
+ numericInput(
+ ns("period_spec"),
+ HTML("Residual period (in days)"),
+ value = 30,
+ min = 0,
+ max = 10^5
+ )
+ )
+ ),
+ fluidRow(
+ column(
+ width = 4,
+ selectInput(
+ ns("ae_hlt"),
+ "Higher Level Event Term",
+ choices = get_ae_term(),
+ selected = c("Body System or Organ Class (AEBODSYS)" = "AEBODSYS")
+ )
+ ),
+ column(
+ width = 4,
+ selectInput(
+ ns("ae_llt"),
+ "Lower Level Event Term",
+ choices = get_ae_term(),
+ selected = c("AE Dictionary-Derived Term (AEDECOD)" = "AEDECOD")
+ )
+ ),
+ column(
+ width = 4,
+ selectInput(
+ ns("summary_by"),
+ "Summary By",
+ choices = c("Participants" = "Patients", "Events" = "Events")
+ )
+ )
+ ),
+ fluidRow(
+ column(
+ width = 4,
+ selectInput(
+ ns("statistics"),
+ "Measure of Association",
+ choices = c("Risk Ratio", "Risk Difference")
+ ),
+ numericInput(
+ ns("X_ref"),
+ "Risk Reference Lines",
+ value = 0,
+ )
+ ),
+ column(
+ width = 4,
+ numericInput(
+ ns("alpha"),
+ "Alpha Value(CI)",
+ value = 0.05,
+ min = 0.01,
+ max = 0.1
+ ),
+ selectInput(
+ ns("riskScale"),
+ "Risk Axis Scale",
+ choices = c("Log10", "Identity", "Log2")
+ )
+ ),
+ column(
+ width = 4,
+ numericInput(
+ ns("pvalcut"),
+ "p Value Cutoff",
+ value = 0.05,
+ min = 0.01,
+ max = 0.1
+ )
+ )
+ ),
+ fluidRow(
+ column(
+ width = 4,
+ numericInput(
+ ns("ref_line"),
+ "Reference Line (%)",
+ min = 0,
+ max = 100,
+ value = 5
+ )
+ )
+ ),
+ hr(),
+ fluidRow(
+ column(
+ width = 4,
+ uiOutput(ns("treatment1_UI")),
+ uiOutput(ns("treatment1_label_UI")),
+ uiOutput(ns("ctrlgrp_UI")),
+ selectInput(
+ ns("sort_opt"),
+ "Sorting Option",
+ choices = c("Ascending", "Descending", "Alphabetical")
+ )
+ ),
+ column(
+ width = 4,
+ uiOutput(ns("treatment2_UI")),
+ br(),
+ uiOutput(ns("treatment2_label_UI")),
+ uiOutput(ns("trtgrp_UI"))
+ )
+ ),
+ fluidRow(
+ column(
+ width = 4,
+ selectInput(
+ ns("sort_by"),
+ "Sorting Variable",
+ choices = NULL
+ )
+ ),
+ column(
+ width = 4,
+ sliderInput(
+ ns("cutoff"),
+ "Cutoff of Incidence (%)",
+ min = 0,
+ max = 10,
+ value = 5
+ )
+ ),
+ column(
+ width = 4,
+ selectInput(
+ ns("pvalue_label"),
+ "P-value Transformation",
+ choices = c("None", "-log10"),
+ selected = "None"
+ )
+ )
+ )
+ )
+ )
+}
+
+#' generic_filters Server Functions
+#'
+#' @noRd
+mod_generic_filters_server <-
+ function(id, sourcedata, domain, repName, repType, trt_var, trt_sort, popfilter) {
+ moduleServer(id, function(input, output, session) {
+ ns <- session$ns
+
+ rv <- reactiveValues(ae_pre = NULL, ae_pre_comp = 0)
+
+ observe({
+ req(domain())
+ hide("ui_pctdisp")
+ req(repType() == "Table")
+ show("ui_pctdisp")
+
+ if (input$aeRiskYN == "N") {
+ pct_denom <- c("Treatment" = "TRT", "Total" = "VAR", "High Term" = "HT")
+ } else {
+ pct_denom <- c("Treatment" = "TRT")
+ }
+
+ updateSelectInput(
+ session,
+ "ui_pctdisp",
+ choices = pct_denom
+ )
+ })
+
+ # observer to control showing/hiding inputs based on report selection
+ observe({
+ req(domain())
+ req(repType())
+ req(repName())
+
+ if (input$period == "Other") {
+ show("period_spec")
+ } else {
+ hide("period_spec")
+ }
+
+ if (repName() == "adae_r001") show("adae_r001") else hide("adae_r001")
+
+ if (repName() == "Forest Plot" || repName() == "Volcano Plot" ||
+ (repName() == "adae_r001") && input$aeRiskYN == "Y") {
+ show("statistics")
+ show("alpha")
+ } else {
+ hide("statistics")
+ hide("alpha")
+ }
+
+ if (repName() == "Forest Plot" || repName() == "Volcano Plot") {
+ show("pvalcut")
+ show("X_ref")
+ show("pvalue_label")
+ } else {
+ hide("pvalcut")
+ hide("X_ref")
+ hide("pvalue_label")
+ }
+
+ if (repName() == "Forest Plot" || repName() == "adae_r001") {
+ show("sort_opt")
+ show("sort_by")
+ } else {
+ hide("sort_opt")
+ hide("sort_by")
+ }
+
+ if (repName() == "Forest Plot") {
+ show("riskScale")
+ } else {
+ hide("riskScale")
+ }
+
+ if (repName() == "Event Analysis") {
+ show("ref_line")
+ hide("summary_by")
+ hide("cutoff")
+ } else {
+ hide("ref_line")
+ show("summary_by")
+ show("cutoff")
+ }
+ })
+
+ observe({
+ req(repName())
+ req(tolower(repName()) %in% c("forest plot", "adae_r001"))
+ req(input$sort_opt != "Alphabetical")
+
+ if (tolower(repName()) == "adae_r001" && input$aeRiskYN == "Y") {
+ by_var <- c("Count", "Percent", "RiskValue")
+ } else if (tolower(repName()) == "forest plot") {
+ by_var <- c("Count", "Percent", "RiskValue")
+ } else if (tolower(repName()) == "adae_r001" && input$aeRiskYN == "N") {
+ by_var <- c("Count", "Percent")
+ }
+
+ updateSelectInput(
+ session,
+ "sort_by",
+ choices = by_var
+ )
+ print("AE Sort Variable updated")
+ })
+
+ observe({
+ req(sourcedata())
+ req(domain())
+ req(repName())
+ req(repType())
+ req(trt_var())
+ req(trt_sort())
+ req(popfilter())
+ req(input$ae_filter)
+ req(input$ae_hlt)
+ if (tolower(domain()) == "adae") {
+ print("AE byVar processing start")
+ ## evaluating the by variables based on report selection
+ if (repType() == "Table") {
+ aeByV <- input$ae_hlt
+ } else {
+ if (tolower(repName()) %in% c("volcano plot", "forest plot", "event analysis")) {
+ aeByV <- input$ae_hlt
+ } else {
+ aeByV <- NA
+ }
+ }
+ print("AE byVar processing end")
+
+ print("AE preprocessing start")
+ ### calling Pre Processing AE data
+ withProgress(
+ rv$ae_pre <- ae_pre_processor(
+ datain = sourcedata()[[domain()]],
+ ae_filter = input$ae_filter,
+ aeSubset = ifelse(repType() == "Table", input$aeSubset, NA),
+ aeDenomSubset = ifelse(repType() == "Table", input$aeDenomSubset, NA),
+ aeObsPeriod = input$period,
+ aeObsResidual = input$period_spec,
+ trtvar = toupper(trt_var()),
+ trtsort = trt_sort(),
+ pop_fil = str_trim(unlist(strsplit(
+ unique(popfilter()), "~"
+ ))[1]),
+ fmq_data = utils::read.csv(paste0(
+ app_sys("extdata"), "/FMQ_Consolidated_List.csv"
+ )),
+ aeEventVar = ifelse(is.null(input$ae_llt), input$ae_hlt, input$ae_llt),
+ aeByVar = aeByV,
+ aeSubGrpVar = NA,
+ aeBigN = ifelse(repType() == "Table", input$aeBigN, "N"),
+ aeGrpVarMiss = ifelse(repType() == "Table", input$aeGrpVarMiss, "N"),
+ aeTrtTot = ifelse(repType() == "Table", input$aeTrtTot, "N"),
+ aeSubGrpTot = "N"
+ ),
+ message = "Executing pre processing for EVENTS/ PT...",
+ detail = "This step should take a while.",
+ min = 0,
+ max = 1,
+ value = 1
+ )
+ print("AE preprocessing end")
+
+ rv$ae_pre_comp <- rv$ae_pre_comp + 1
+ }
+ }) %>%
+ bindEvent(
+ list(
+ repName(), trt_var(), trt_sort(), popfilter(), input$ae_filter, input$aeSubset,
+ input$aeDenomSubset, input$period, input$period_spec, input$ae_hlt, input$ae_llt,
+ input$aeBigN, input$aeGrpVarMiss, input$aeTrtTot
+ )
+ )
+
+ observe({
+ req(rv$ae_pre)
+ if (tolower(repName()) %in% c("volcano plot", "forest plot") ||
+ (tolower(repName()) == "adae_r001" && input$aeRiskYN == "Y")) {
+ print("AE treatment pair processing start")
+
+ TRTCD <- unique(rv$ae_pre$dout$TRTVAR[rv$ae_pre$dout$TRTVAR != ""])
+
+ ## Single pair radio button selection for Volcano plot
+ output$treatment1_UI <- renderUI({
+ req(repName() == "Volcano Plot" || (repName() == "adae_r001") && input$aeRiskYN == "Y")
+ radioButtons(
+ ns("treatment1"),
+ "Control Group",
+ choices = TRTCD,
+ selected = TRTCD[1]
+ )
+ })
+
+ output$treatment2_UI <- renderUI({
+ req(repName() == "Volcano Plot" || (repName() == "adae_r001") && input$aeRiskYN == "Y")
+ radioButtons(
+ ns("treatment2"),
+ "Treatment Group",
+ choices = setdiff(TRTCD, input$treatment1),
+ selected = setdiff(TRTCD, input$treatment1)[1]
+ )
+ })
+
+ output$treatment1_label_UI <- renderUI({
+ req(tolower(repName()) == "volcano plot")
+ textInput(ns("treatment1_label"),
+ "Label for Control Group",
+ value = "Control"
+ )
+ })
+
+ output$treatment2_label_UI <- renderUI({
+ req(tolower(repName()) == "volcano plot")
+ textInput(ns("treatment2_label"),
+ "Label for Treatment Group",
+ value = "Treatment"
+ )
+ })
+
+ ## Multiple pair check box selection for forest plot
+
+ output$ctrlgrp_UI <- renderUI({
+ req(tolower(repName()) == "forest plot")
+ radioButtons(
+ ns("ctrlgrp"),
+ "Control Group",
+ choices = TRTCD,
+ selected = TRTCD[1],
+ inline = FALSE
+ )
+ })
+
+ output$trtgrp_UI <- renderUI({
+ req(tolower(repName()) == "forest plot")
+ checkboxGroupInput(
+ ns("trtgrp"),
+ "Treatment Group",
+ choices = setdiff(TRTCD, input$ctrlgrp),
+ selected = setdiff(TRTCD, input$ctrlgrp)[1]
+ )
+ })
+ print("AE treatment pair processing end")
+ }
+ }) %>%
+ bindEvent(list(rv$ae_pre_comp, input$aeRiskYN))
+
+ filters <- reactive({
+ req(rv$ae_pre)
+ req(input$ae_filter)
+ if ((repName() == "adae_r001") && input$aeRiskYN == "Y") {
+ req(input$treatment1)
+ req(input$treatment2)
+ req(input$statistics)
+ req(input$alpha)
+ }
+ if (repName() == "Volcano Plot") {
+ req(input$treatment1)
+ req(input$treatment2)
+ req(input$treatment1_label)
+ req(input$treatment2_label)
+ }
+ if (tolower(repName()) == "forest plot") {
+ req(input$ctrlgrp)
+ req(input$trtgrp)
+ req(!identical(input$ctrlgrp, input$trtgrp))
+ }
+
+ list(
+ ae_pre = rv$ae_pre,
+ trt_var = trt_var(),
+ ae_filter = input$ae_filter,
+ ae_hlt = input$ae_hlt,
+ ae_llt = input$ae_llt,
+ summary_by = input$summary_by,
+ aeRiskYN = input$aeRiskYN,
+ treatment1 = input$treatment1,
+ treatment2 = input$treatment2,
+ treatment1_label = input$treatment1_label,
+ treatment2_label = input$treatment2_label,
+ statistics = input$statistics,
+ alpha = input$alpha,
+ ui_pctdisp = input$ui_pctdisp,
+ cutoff = input$cutoff,
+ sort_opt = input$sort_opt,
+ sort_by = input$sort_by,
+ ctrlgrp = input$ctrlgrp,
+ trtgrp = input$trtgrp,
+ pvalcut = input$pvalcut,
+ riskScale = input$riskScale,
+ X_ref = input$X_ref,
+ pvalue_label = input$pvalue_label,
+ ref_line = input$ref_line
+ )
+ })
+
+ return(filters)
+ })
+ }
diff --git a/R/mod_goutput.R b/R/mod_goutput.R
new file mode 100644
index 0000000..24a4265
--- /dev/null
+++ b/R/mod_goutput.R
@@ -0,0 +1,466 @@
+#' goutput UI Function
+#'
+#' @description A shiny Module.
+#'
+#' @param id,input,output,session Internal parameters for {shiny}.
+#'
+#' @noRd
+#'
+#' @importFrom shiny NS tagList
+mod_goutput_ui <- function(id) {
+ ns <- NS(id)
+ tagList(
+ box(
+ id = ns("event_box"),
+ title = tags$strong("Event Analysis Inputs"),
+ maximizable = TRUE,
+ width = 12,
+ fluidRow(
+ column(
+ width = 3,
+ selectInput(
+ ns("hlt_val"),
+ "Event Higher Classification",
+ choices = NULL
+ )
+ ),
+ column(
+ width = 3,
+ uiOutput(ns("aeHLT_query_cat_UI"))
+ ),
+ column(
+ width = 3,
+ selectInput(
+ ns("llt_val"),
+ "Event Lower Classification",
+ choices = NULL
+ )
+ ),
+ column(
+ width = 3,
+ uiOutput(ns("aeLLT_query_cat_UI"))
+ )
+ )
+ ),
+ box(
+ id = ns("box_1"),
+ title = tags$strong(htmlOutput(ns("g_title_UI"))),
+ maximizable = TRUE,
+ width = 12,
+ headerBorder = FALSE,
+ footer = htmlOutput(ns("g_footnote_UI")),
+ div(
+ shinycssloaders::withSpinner(
+ plotly::plotlyOutput(ns("figure_UI"), width = "80vw"),
+ type = 5,
+ color = "cadetblue"
+ ),
+ style = "overflow-x: scroll; height: 650px;"
+ )
+ ),
+ box(
+ id = ns("box_2"),
+ title = tags$strong("Plot Listing"),
+ maximizable = TRUE,
+ width = 12,
+ DT::dataTableOutput(ns("plot_listing"))
+ ),
+ mod_plot_profile_ui(ns("plot_profile_1"))
+ )
+}
+
+#' goutput Server Functions
+#'
+#' @noRd
+mod_goutput_server <- function(id, sourcedata, repName, filters, process_btn) {
+ moduleServer(id, function(input, output, session) {
+ ns <- session$ns
+
+ rv <- reactiveValues(
+ statistics = NULL,
+ goutput = NULL,
+ output_trigger = 0
+ )
+
+ observe({
+ req(repName())
+ req(filters()$ae_pre$dsin)
+ req(filters()$ae_pre$dout)
+ req(filters()$ae_filter)
+ req(filters()$statistics)
+ req(filters()$ae_hlt)
+ req(filters()$ae_llt)
+ req(filters()$summary_by)
+ if (tolower(repName()) %in% c("volcano plot")) {
+ req(filters()$treatment1)
+ req(filters()$treatment1_label)
+ req(filters()$treatment2)
+ req(filters()$treatment2_label)
+ }
+ if (tolower(repName()) %in% c("forest plot")) {
+ req(filters()$ctrlgrp)
+ req(filters()$trtgrp)
+ req(filters()$sort_opt)
+ req(filters()$sort_by)
+ }
+ req(filters()$alpha)
+ req(filters()$cutoff)
+ if (tolower(repName()) %in% c("volcano plot", "forest plot")) {
+ print("AE risk_stat process start")
+ withProgress(
+ rv$statistics <- risk_stat(
+ datain = filters()$ae_pre$dsin,
+ d_datain = filters()$ae_pre$dout,
+ eventVar = ifelse(is.null(filters()$ae_llt), filters()$ae_hlt, filters()$ae_llt),
+ summary_by = filters()$summary_by,
+ ctrlgrp = ifelse(tolower(repName()) == "volcano plot",
+ filters()$treatment1,
+ filters()$ctrlgrp
+ ),
+ trtgrp = ifelse(
+ tolower(repName()) == "volcano plot",
+ filters()$treatment2,
+ paste(filters()$trtgrp, collapse = "~~")
+ ),
+ statistics = filters()$statistics,
+ alpha = filters()$alpha,
+ cutoff = filters()$cutoff,
+ sort_opt = ifelse(tolower(repName()) == "forest plot", filters()$sort_opt, NA),
+ sort_var = ifelse(tolower(repName()) == "forest plot", filters()$sort_by, NA)
+ ),
+ message = "Executing Get Statistics for EVENTS/ PT...",
+ detail = "This step should take a while.",
+ min = 0,
+ max = 1,
+ value = 1
+ )
+ print("AE risk_stat process end")
+ rv$output_trigger <- rv$output_trigger + 1
+ }
+ }) %>%
+ bindEvent(process_btn())
+
+ observe({
+ req(tolower(repName()) %in% c("forest plot"))
+ req(rv$statistics)
+ req(filters()$ae_filter)
+ req(filters()$pvalcut)
+ req(filters()$X_ref)
+ req(filters()$riskScale)
+ print("AE Forest Plot process start")
+ withProgress(message = "Generating Forest Plot", value = 0, {
+ rv$goutput <- try(forest_plot(
+ datain = isolate(rv$statistics),
+ AE_Filter = filters()$ae_filter,
+ review_by = c(filters()$ae_hlt, filters()$ae_llt),
+ summary_by = filters()$summary_by,
+ statistics = filters()$statistics,
+ xref = as.numeric(filters()$X_ref),
+ pvalcut = filters()$pvalcut,
+ scale_trans = filters()$riskScale
+ ))
+ })
+ print("AE Forest Plot process end")
+ }) %>%
+ bindEvent(rv$output_trigger)
+
+ observe({
+ req(tolower(repName()) %in% c("volcano plot"))
+ req(filters()$ae_pre$dsin)
+ req(rv$statistics)
+ req(filters()$ae_filter)
+ req(filters()$statistics)
+ req(filters()$treatment1)
+ req(filters()$treatment2)
+ req(filters()$X_ref)
+ req(filters()$summary_by)
+ req(filters()$pvalue_label)
+
+ print("AE Volcano Plot process start")
+ withProgress(message = "Generating Volcano Plot", value = 0, {
+ rv$goutput <- try(volcano_plot(
+ datain = isolate(filters()$ae_pre$dsin),
+ AE_Filter = filters()$ae_filter,
+ statistics_data = isolate(rv$statistics),
+ statistics = filters()$statistics,
+ treatment1 = filters()$treatment1,
+ treatment2 = filters()$treatment2,
+ X_ref = as.numeric(filters()$X_ref),
+ summary_by = filters()$summary_by,
+ pvalue_label = filters()$pvalue_label,
+ treatment1_label = filters()$treatment1_label,
+ treatment2_label = filters()$treatment2_label,
+ pvalcut = filters()$pvalcut
+ ))
+ })
+ print("AE Volcano Plot process end")
+ }) %>%
+ bindEvent(rv$output_trigger)
+
+ observe({
+ req(repName())
+ if (tolower(repName()) %in% c("event analysis")) {
+ show("event_box")
+ } else {
+ hide("event_box")
+ }
+ })
+
+ observe({
+ req(tolower(repName()) %in% c("event analysis"))
+ req(filters()$ae_pre$dsin)
+ req(filters()$ae_hlt)
+
+ print("AE event analysis hlt list input process start")
+
+ temp1 <- filters()$ae_pre$dsin
+
+ if (filters()$ae_hlt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
+ if (filters()$ae_hlt %in% names(temp1)) {
+ hlt_list <- unlist(strsplit(unique(temp1[[filters()$ae_hlt]]), "~~"))
+ hlt_list <-
+ sort(unique(gsub("/\\w+", "", hlt_list[!is.na(hlt_list)])))
+ } else {
+ hlt_list <- NULL
+ }
+ } else {
+ hlt_list <- sort(unique(temp1[[filters()$ae_hlt]]))
+ }
+
+ updateSelectInput(
+ session,
+ "hlt_val",
+ "Event Higher Classification",
+ choices = hlt_list,
+ selected = hlt_list[1]
+ )
+ print("AE event analysis hlt list input process end")
+ })
+
+ observe({
+ req(tolower(repName()) %in% c("event analysis"))
+ req(filters()$ae_pre$dsin)
+ req(filters()$ae_hlt)
+ req(input$hlt_val)
+ if (filters()$ae_hlt %in% c("FMQ_NAM", "SMQ_NAM", "CQ_NAM")) {
+ req(input$hlt_cat)
+ }
+ print("AE event analysis llt list input process start")
+ temp1 <- filters()$ae_pre$dsin
+
+ if (filters()$ae_hlt %in% c("FMQ_NAM", "SMQ_NAM", "CQ_NAM")) {
+ if (toupper(input$hlt_cat) == "NARROW") {
+ hl_val1 <- paste0(str_to_upper(input$hlt_val), "/", str_to_upper(input$hlt_cat))
+ } else {
+ hl_val1 <- input$hlt_val
+ }
+ } else {
+ hl_val1 <- input$hlt_val
+ }
+
+ if (filters()$ae_hlt %in% names(temp1) && filters()$ae_llt %in% names(temp1)) {
+ llt_list <-
+ unique(temp1[[filters()$ae_llt]][str_detect(
+ toupper(temp1[[filters()$ae_hlt]]),
+ toupper(hl_val1)
+ )])
+ } else {
+ llt_list <- NULL
+ }
+
+ if (filters()$ae_llt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
+ if (!is.null(llt_list)) {
+ llt_list <- unlist(strsplit(unique(llt_list), "~~"))
+ llt_list <- sort(unique(gsub("/\\w+", "", llt_list[!is.na(llt_list)])))
+ }
+ } else {
+ llt_list <- sort(llt_list)
+ }
+
+ updateSelectInput(
+ session,
+ "llt_val",
+ "Event Term",
+ choices = llt_list,
+ selected = llt_list[1]
+ )
+ print("AE event analysis llt list input process end")
+ })
+
+ observe({
+ req(tolower(repName()) %in% c("event analysis"))
+ req(filters()$ae_pre$dsin)
+ print("AE event analysis hlt scope input process start")
+
+ output$aeHLT_query_cat_UI <- renderUI({
+ req(filters()$ae_hlt)
+ req(filters()$ae_hlt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM"))
+ tagList(
+ selectInput(
+ ns("hlt_cat"),
+ "Query Scope",
+ choices = c("Narrow", "Broad")
+ )
+ )
+ })
+ print("AE event analysis hlt scope input process end")
+ print("AE event analysis llt scope input process start")
+
+ output$aeLLT_query_cat_UI <- renderUI({
+ req(filters()$ae_llt)
+ req(filters()$ae_llt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM"))
+ tagList(
+ selectInput(
+ ns("llt_cat"),
+ "Query Scope",
+ choices = c("Narrow", "Broad")
+ )
+ )
+ })
+ print("AE event analysis llt scope input process end")
+ })
+
+ observe({
+ req(tolower(repName()) %in% c("event analysis"))
+ req(filters()$ae_pre$dsin)
+ req(filters()$ae_hlt)
+ req(filters()$ae_llt)
+ req(input$hlt_val)
+ req(input$llt_val)
+ if (filters()$ae_hlt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
+ req(input$hlt_cat)
+ }
+ if (filters()$ae_llt %in% c("SMQ_NAM", "FMQ_NAM", "CQ_NAM")) {
+ req(input$llt_cat)
+ }
+ req(filters()$summary_by)
+
+ print("AE event analysis process start")
+ withProgress(message = "Generating AE event analysis", value = 0, {
+ rv$goutput <- try(event_analysis(
+ datain = filters()$ae_pre$dsin,
+ datain_N = filters()$ae_pre$dout,
+ hl_var = filters()$ae_hlt,
+ hl_val = toupper(input$hlt_val),
+ hl_scope = toupper(input$hlt_cat),
+ ll_var = filters()$ae_llt,
+ ll_val = toupper(input$llt_val),
+ ll_scope = toupper(input$llt_cat),
+ summary_by = filters()$summary_by,
+ ref_line = filters()$ref_line
+ ))
+ })
+ print("AE event analysis process end")
+ }) %>%
+ bindEvent(process_btn())
+
+ plot_data <- reactive({
+ event <- plotly::event_data("plotly_click", source = "plot_output")
+ req(length(event) > 0)
+
+ if (tolower(repName()) == "forest plot") {
+ test <- rv$goutput$drill_plt$data[as.numeric(event$key), ]
+ } else if (tolower(repName()) == "volcano plot") {
+ test <- rv$goutput$plot$data[as.numeric(event$key), ]
+ } else {
+ if (event$curveNumber == 0 && event$x > 0) {
+ test <- NULL
+ } else {
+ test <- rv$goutput$rpt_data
+ trt_level_diff <- length(levels(test$TRTVAR)) - length(unique(test$TRTVAR))
+ test <- test %>%
+ mutate(point_n = as.numeric(as.factor(TRTVAR)) - trt_level_diff)
+ order_df <- data.frame(DPTVAL = levels(reorder(test$DPTVAL, -test$DECODh))) %>%
+ mutate(curve_n = row_number() + 1)
+ test <- full_join(test, order_df, by = "DPTVAL") %>%
+ filter(point_n == event$x, curve_n == event$curveNumber)
+ }
+ }
+
+ req(test)
+
+ display <- filters()$ae_pre$dout %>%
+ select(any_of(c(
+ "USUBJID", "TRTVAR", "BYVAR1", filters()$ae_llt, "AESER", "AEOUT", "AESEV",
+ "AESTDT", "ASTTM", "AEENDT", "TRTSTDT", "TRTEDT", "TRTEMFL"
+ )))
+ plot_table <- select(test, "BYVAR1", "DPTVAL", "TRTVAR") %>%
+ rename(!!filters()$ae_llt := "DPTVAL") %>%
+ inner_join(display) %>%
+ relocate(c("USUBJID", "TRTVAR"))
+
+ ## displaying the listing table
+ plot_table <- plot_table %>%
+ rename(
+ !!filters()$ae_hlt := "BYVAR1",
+ !!filters()$trt_var := "TRTVAR"
+ ) %>%
+ distinct()
+ }) %>%
+ bindEvent(plotly::event_data("plotly_click", source = "plot_output"))
+
+ # set selected point to null every time plot updates
+ observe({
+ req(length(plotly::event_data("plotly_click", source = "plot_output")) > 0)
+ runjs("Shiny.setInputValue('plotly_click-plot_output', null);")
+ }) %>%
+ bindEvent(list(repName(), rv$goutput$drill_plt$data, rv$goutput$plot$data))
+
+ observe({
+ if (is.null(plotly::event_data("plotly_click", source = "plot_output"))) {
+ hide("box_2")
+ runjs("Shiny.setInputValue('goutput_1-plot_listing_rows_selected', null);")
+ } else {
+ show("box_2")
+ }
+ })
+
+ output$figure_UI <- plotly::renderPlotly({
+ req(rv$goutput)
+ req(rv$goutput$ptly)
+ rv$goutput$ptly
+ })
+
+ output$g_title_UI <- renderText({
+ req(rv$goutput$ptly)
+ rpt_title <- str_replace_all(rv$goutput$title, "\n", "
")
+ return(HTML(rpt_title))
+ })
+
+ ## footnote for Plot
+ output$g_footnote_UI <- renderText({
+ req(rv$goutput$ptly)
+ rpt_ftnote <- str_replace_all(rv$goutput$footnote, "\n", "
")
+ return(HTML(rpt_ftnote))
+ })
+
+ output$plot_listing <- DT::renderDataTable(
+ {
+ req(plot_data())
+
+ datatable(
+ plot_data(),
+ extensions = "Buttons",
+ selection = list(mode = "single"),
+ options = list(
+ dom = "Bfrtip",
+ buttons = I("colvis"),
+ pageLength = 10,
+ scrollX = TRUE
+ )
+ )
+ },
+ server = FALSE
+ )
+
+ mod_plot_profile_server(
+ "plot_profile_1",
+ sourcedata = reactive(sourcedata()),
+ sel_rows = reactive(input$plot_listing_rows_selected),
+ datain = reactive(filters()$ae_pre$dout),
+ plot_data = plot_data
+ )
+
+ return(reactive(rv$goutput))
+ })
+}
diff --git a/R/mod_plot_profile.R b/R/mod_plot_profile.R
new file mode 100644
index 0000000..d6aedfd
--- /dev/null
+++ b/R/mod_plot_profile.R
@@ -0,0 +1,117 @@
+#' plot_profile UI Function
+#'
+#' @description A shiny Module.
+#'
+#' @param id,input,output,session Internal parameters for {shiny}.
+#'
+#' @noRd
+#'
+#' @importFrom shiny NS tagList
+mod_plot_profile_ui <- function(id) {
+ ns <- NS(id)
+ tagList(
+ box(
+ id = ns("box_1"),
+ title = tags$strong("Subject Profile"),
+ maximizable = TRUE,
+ width = 12,
+ div(
+ uiOutput(ns("profile_plot_title")),
+ style = "font-weight: 600;"
+ ),
+ div(
+ plotly::plotlyOutput(ns("profile_plot")),
+ style = "height:600px; overflow-y: scroll; display: flex; justify-content: center;"
+ )
+ )
+ )
+}
+
+#' plot_profile Server Functions
+#'
+#' @noRd
+mod_plot_profile_server <- function(id, sourcedata, sel_rows, datain, plot_data) {
+ moduleServer(id, function(input, output, session) {
+ ns <- session$ns
+
+ rv <- reactiveValues(sourcedata = NULL, cm_init = TRUE)
+
+ observe({
+ if (is.null(sel_rows())) {
+ hide("box_1")
+ } else {
+ show("box_1")
+ }
+ })
+
+ observe({
+ req(sourcedata())
+ req(sel_rows())
+ req(isTRUE(rv$cm_init))
+ if ("cm" %in% names(sourcedata())) {
+ rv$sourcedata <- sourcedata()
+ }
+ src_d <- rv$sourcedata
+ if (is.null(rv$sourcedata)) {
+ src_d <- sourcedata()
+ }
+ if (!any(c("cm", "adcm") %in% names(src_d))) {
+ showModal(modalDialog(
+ title = "Profile: Concomitant Medication not loaded",
+ paste0(
+ "Upload CM/ADCM data to see overlaid AE-CM profile ",
+ "or click 'Close' to proceed with Adverse Events profile"
+ ),
+ fileInput(
+ ns("cm_data"),
+ label = "Import CM data (optional)",
+ accept = c(".csv", ".sas7bdat", ".xls", ".xpt", ".Rda"),
+ multiple = FALSE
+ ),
+ footer = tagList(actionButton(ns("closeCM"), "Close", class = "sidebar-btn"))
+ ))
+ }
+ }) %>%
+ bindEvent(sel_rows())
+
+ observe({
+ removeModal()
+ if (is.null(input$cm_data)) {
+ rv$cm_init <- FALSE
+ }
+ req(input$cm_data)
+ cm_data <- data_read(
+ ui_data_source = "Local",
+ ui_adam_data = input$cm_data
+ )$adam
+ rv$sourcedata <- append(sourcedata(), cm_data)
+ }) %>%
+ bindEvent(input$closeCM)
+
+ observe({
+ req(sel_rows())
+ req(datain())
+ datain <- list(AE = datain())
+ dom_names <- names(rv$sourcedata)
+ if (any(c("cm", "adcm") %in% dom_names)) {
+ datain[["CM"]] <- rv$sourcedata[[dom_names[endsWith(dom_names, "cm")][1]]]
+ }
+ withProgress(message = "Generating Interval Plot", value = 0, {
+ rv$prplot <- multi_interval(
+ datain = datain,
+ subjectid = plot_data()[sel_rows(), ][["USUBJID"]][1]
+ )
+ })
+ })
+
+ output$profile_plot_title <- renderUI({
+ req(rv$prplot)
+ HTML(rv$prplot$title)
+ })
+
+ output$profile_plot <- plotly::renderPlotly({
+ req(rv$prplot)
+ rv$prplot$ptly
+ })
+ })
+}
diff --git a/R/mod_report_selection.R b/R/mod_report_selection.R
new file mode 100644
index 0000000..902da9e
--- /dev/null
+++ b/R/mod_report_selection.R
@@ -0,0 +1,229 @@
+#' report_selection UI Function
+#'
+#' @description A shiny Module.
+#'
+#' @param id,input,output,session Internal parameters for {shiny}.
+#'
+#' @noRd
+#'
+#' @importFrom shiny NS tagList
+mod_report_selection_ui <- function(id) {
+ ns <- NS(id)
+ tagList(
+ fluidRow(
+ column(
+ width = 8,
+ box(
+ id = ns("box_1"),
+ title = tags$strong("Report Selection"),
+ maximizable = TRUE,
+ width = 12,
+ fluidRow(
+ column(
+ width = 6,
+ selectInput(ns("bdomain"),
+ "Report base domain",
+ choices = NULL,
+ width = "25vw"
+ ),
+ selectInput(ns("tarea"),
+ "Therapeutic Area",
+ choices = NULL,
+ width = "25vw"
+ ),
+ selectInput(ns("repType"),
+ "Report Type",
+ choices = NULL,
+ width = "25vw"
+ )
+ ),
+ column(
+ width = 6,
+ selectInput(ns("repName"),
+ "Report Name",
+ choices = NULL,
+ width = "25vw"
+ ),
+ selectInput(ns("repnum"),
+ "Report Number",
+ choices = NULL,
+ width = "25vw"
+ ),
+ selectInput(ns("repdesc"),
+ "Report Description",
+ choices = NULL,
+ width = "25vw"
+ )
+ )
+ )
+ )
+ ),
+ column(
+ width = 4,
+ box(
+ id = ns("box_2"),
+ title = tags$strong("Treatment & Population Selection"),
+ maximizable = TRUE,
+ width = 12,
+ fluidRow(
+ column(
+ width = 12,
+ selectInput(ns("trt_var"),
+ "Treatment Variable",
+ choices = NULL,
+ selected = NULL
+ ),
+ selectInput(ns("trt_sort"),
+ "Treatment Sort Variable",
+ choices = NULL,
+ selected = NULL
+ ),
+ selectInput(ns("popfilter"),
+ "Population Filter",
+ choices = NULL
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+}
+
+#' report_selection Server Functions
+#'
+#' @noRd
+mod_report_selection_server <- function(id, sourcedata, domain, data_attr) {
+ moduleServer(id, function(input, output, session) {
+ ns <- session$ns
+
+ observe({
+ req(sourcedata())
+ updateSelectInput(session,
+ "bdomain",
+ choices = domain(),
+ selected = domain()[1]
+ )
+ })
+
+ report_meta <- reactive({
+ req(input$bdomain)
+
+ print("loading report meta begin")
+ meta <- get_report_meta()
+ print("loading report meta success")
+ return(meta)
+ })
+
+ observe({
+ req(input$bdomain)
+ req(report_meta())
+
+ tempRepMeta <- report_meta() %>%
+ filter(DOMAIN %in% c(toupper(input$bdomain)))
+
+ updateSelectInput(session,
+ "tarea",
+ choices = pull(unique(tempRepMeta["TA"]))
+ )
+ }) %>%
+ bindEvent(input$bdomain)
+
+ observe({
+ req(input$tarea)
+
+ updateSelectInput(session,
+ "repType",
+ choices = unique(report_meta()["REPTYPE"][report_meta()["TA"] == input$tarea])
+ )
+ }) %>%
+ bindEvent(input$tarea)
+
+ observe({
+ req(input$repType)
+
+ meta <- report_meta()
+ choices <-
+ unique(meta["REPNAME"][meta["TA"] == input$tarea &
+ meta["REPTYPE"] == input$repType])
+
+ updateSelectInput(session,
+ "repName",
+ choices = choices
+ )
+ }) %>%
+ bindEvent(input$repType)
+
+ observe({
+ req(input$repName)
+
+ meta <- report_meta()
+ choices_num <- unique(meta["REPNO"][meta["REPNAME"] == input$repName])
+ choices_desc <- unique(meta["REPDESC"][meta["REPNAME"] == input$repName])
+
+ updateSelectInput(session,
+ "repnum",
+ choices = choices_num
+ )
+
+ updateSelectInput(session,
+ "repdesc",
+ choices = choices_desc
+ )
+ }) %>%
+ bindEvent(input$repName)
+
+ observe({
+ req(data_attr())
+ req(input$repName)
+
+ trtv <-
+ c(
+ "ARM", "ARMCD", "ACTARM", "ACTARMCD",
+ "COHORT", "TRTA", "TRTP", "TRTAN", "TRTPN"
+ )
+ # Get the treatment variable from the input dataset
+ trtvar <- data_attr()[[input$bdomain]] %>%
+ filter(VAR_NAMES %in% trtv |
+ str_detect(VAR_NAMES, "TRT[:digit:]+[AP]")) %>%
+ select(VAR_NAMES) %>%
+ pull()
+
+ # Get the Population variable from the input dataset
+ popvar <- data_attr()[[input$bdomain]] %>%
+ filter(str_detect(tolower(VAR_LABEL), "population")) %>%
+ mutate(pop = paste0(VAR_NAMES, " ~ ", VAR_LABEL)) %>%
+ select(pop) %>%
+ pull()
+
+ updateSelectInput(session,
+ "trt_var",
+ choices = trtvar,
+ selected = trtvar[1]
+ )
+
+ updateSelectInput(session,
+ "trt_sort",
+ choices = trtvar,
+ selected = trtvar[1]
+ )
+
+ updateSelectInput(session,
+ "popfilter",
+ choices = c("Overall Population", popvar)
+ )
+ })
+
+ return(list(
+ bdomain = reactive(input$bdomain),
+ tarea = reactive(input$tarea),
+ repType = reactive(input$repType),
+ repName = reactive(input$repName),
+ repnum = reactive(input$repnum),
+ repdesc = reactive(input$repdesc),
+ trt_var = reactive(input$trt_var),
+ trt_sort = reactive(input$trt_sort),
+ popfilter = reactive(input$popfilter)
+ ))
+ })
+}
diff --git a/R/mod_toutput.R b/R/mod_toutput.R
new file mode 100644
index 0000000..b02e490
--- /dev/null
+++ b/R/mod_toutput.R
@@ -0,0 +1,109 @@
+#' toutput UI Function
+#'
+#' @description A shiny Module.
+#'
+#' @param id,input,output,session Internal parameters for {shiny}.
+#'
+#' @noRd
+#'
+#' @importFrom shiny NS tagList
+mod_toutput_ui <- function(id) {
+ ns <- NS(id)
+ tagList(
+ box(
+ id = ns("box_1"),
+ title = tags$strong(htmlOutput(ns("t_title_UI"))),
+ maximizable = TRUE,
+ width = 12,
+ headerBorder = FALSE,
+ footer = htmlOutput(ns("t_footnote_UI")),
+ div(
+ shinycssloaders::withSpinner(uiOutput(ns("table_UI")), type = 5, color = "cadetblue"),
+ style = "overflow-x: scroll;"
+ )
+ )
+ )
+}
+
+#' toutput Server Functions
+#'
+#' @noRd
+mod_toutput_server <- function(id, repName, filters, popfilter, process_btn) {
+ moduleServer(id, function(input, output, session) {
+ ns <- session$ns
+
+ rv <- reactiveValues(
+ toutput = NULL
+ )
+
+ observe({
+ req(repName())
+ req(popfilter())
+ req(filters())
+ req(tolower(repName()) %in% c("adae_r001"))
+ req(filters()$ae_pre)
+ req(filters()$ae_filter)
+ req(filters()$ae_llt)
+ req(filters()$ae_hlt)
+ req(filters()$summary_by)
+ req(filters()$aeRiskYN)
+ if (filters()$aeRiskYN == "Y") {
+ req(filters()$treatment1)
+ req(filters()$treatment2)
+ req(filters()$statistics)
+ req(filters()$alpha)
+ }
+ req(filters()$ui_pctdisp)
+ req(filters()$cutoff)
+ req(filters()$sort_opt)
+ req(filters()$sort_by)
+ print("AE Summary table process start")
+ withProgress(message = "Generating AE Summary table", value = 0, {
+ rv$toutput <- try(
+ adae_r001(
+ datain = filters()$ae_pre,
+ population = str_trim(unlist(strsplit(unique(popfilter()), "~"))[1]),
+ AE_Filter = filters()$ae_filter,
+ riskyn = filters()$aeRiskYN,
+ summary_by = filters()$summary_by,
+ ctrlgrp = ifelse(filters()$aeRiskYN == "Y", filters()$treatment1, NA),
+ trtgrp = ifelse(filters()$aeRiskYN == "Y", filters()$treatment2, NA),
+ ui_lt = filters()$ae_llt,
+ ui_ht = filters()$ae_hlt,
+ ui_pctdisp = filters()$ui_pctdisp,
+ ui_statistics = filters()$statistics,
+ ui_alpha = filters()$alpha,
+ ui_cutoff = filters()$cutoff,
+ ui_sortopt = filters()$sort_opt,
+ ui_sortvar = filters()$sort_by
+ )
+ )
+ })
+ print("AE Summary table process end")
+ }) %>%
+ bindEvent(process_btn())
+
+ output$table_UI <- renderUI({
+ req(rv$toutput)
+ ft <- rv$toutput$tout %>%
+ border_inner(fp_border(color = "cadetblue")) %>%
+ fontsize(size = 12, part = "header") %>%
+ fontsize(size = 9, part = "body")
+ htmltools_value(ft)
+ })
+
+ output$t_title_UI <- renderText({
+ req(rv$toutput)
+ rpt_title <- str_replace_all(rv$toutput$title, "\n", "
")
+ return(HTML(rpt_title))
+ })
+
+ output$t_footnote_UI <- renderText({
+ req(rv$toutput)
+ rpt_ftnote <- str_replace_all(rv$toutput$footnote, "\n", "
")
+ return(HTML(rpt_ftnote))
+ })
+
+ return(reactive(rv$toutput))
+ })
+}
diff --git a/R/multi_interval.R b/R/multi_interval.R
new file mode 100644
index 0000000..d4deae9
--- /dev/null
+++ b/R/multi_interval.R
@@ -0,0 +1,116 @@
+#' Aligned Interval Plot for Adverse Events and Concomitant Medication
+#'
+#' @param datain Input list containing an element named `AE` (required) and an element named `CM`
+#' with the corresponding dataframes
+#' @param subjectid Participant ID (from the variable `USUBJID`)
+#'
+#' @return : a list containing 4 objects
+#' \itemize{
+#' \item ptly - Interactive plot output for display
+#' \item plot - Static plot output for saving externally
+#' \item rpt_data - Dataset used to create plot(s), for validation purpose
+#' \item title - Report title/header, for download purpose
+#' }
+#' @export
+#'
+#' @examples
+#' library(cvars)
+#' data(adae)
+#' data(cm)
+#' multi_interval(
+#' datain = list(AE = adae, CM = cm),
+#' subjectid = "01-717-1446"
+#' )$ptly
+multi_interval <- function(datain,
+ subjectid) {
+ # AE data is mandatory
+ if (!"AE" %in% names(datain)) {
+ return(empty_plot("No AE data available"))
+ }
+ # Get subject data for footer purposes
+ aedata <- datain[["AE"]] %>% filter(USUBJID == subjectid)
+ # Create AE plot - required
+ seriesc <- c(MILD = "tan2", MODERATE = "dodgerblue3", SEVERE = "deeppink4")
+ if ("ASEV" %in% names(aedata)) {
+ seriesv <- "ASEV"
+ } else if ("AESEV" %in% names(aedata)) {
+ seriesv <- "AESEV"
+ } else {
+ seriesv <- NA
+ seriesc <- "black"
+ }
+ ae_int <- interval_plot(
+ datain = datain[["AE"]],
+ startvar = "ASTDY",
+ endvar = "AENDY",
+ yvar = "AEDECOD",
+ seriesvar = seriesv,
+ subjectid = subjectid,
+ series_color = seriesc,
+ yaxislab = "Adverse Event"
+ )
+ # Plot title
+ title <- paste0("Events over Study Period for Participant: ", subjectid, "\n")
+ if ("AGE" %in% names(aedata)) title <- paste0(title, "; Age: ", unique(aedata$AGE))
+ if ("SEX" %in% names(aedata)) title <- paste0(title, "; Sex: ", unique(aedata$SEX))
+ if ("RACE" %in% names(aedata)) title <- paste0(title, "; Race: ", unique(aedata$RACE))
+ # If Cm domain present, add plot
+ if (("CM" %in% names(datain)) && (!is.null(datain$CM))) {
+ cm_int <- interval_plot(
+ datain = datain[["CM"]],
+ startvar = "CMSTDY",
+ endvar = "CMENDY",
+ yvar = "CMTRT",
+ seriesvar = "CMCLAS",
+ subjectid = subjectid,
+ series_color = NA,
+ yaxislab = "Drug/Med/Therapy"
+ )
+ # Identify Axis range for combined plot
+ if (nrow(cm_int$rpt_data) == 0 || nrow(ae_int$rpt_data) == 0) {
+ ptly_out <- plotly::subplot(ae_int$ptly, cm_int$ptly,
+ nrows = 2,
+ titleX = TRUE, titleY = TRUE
+ ) %>%
+ plotly::layout(height = 600, showlegend = TRUE)
+ plot_out <- cowplot::plot_grid(
+ ae_int$plot, cm_int$plot,
+ align = "v",
+ nrow = 2
+ )
+ } else {
+ rangeae <- layer_scales(ae_int$plot)$y$range$range
+ rangecm <- layer_scales(cm_int$plot)$y$range$range
+ xmin <- floor(min(rangeae, rangecm) / 5) * 5
+ xmax <- ceiling(max(rangeae, rangecm) / 5) * 5
+ sepby <- as.integer(seq(xmin, xmax, by = ceiling((xmax - xmin) / 10)))
+ # Combine and align the 2 plots - interactive
+ ptly_out <- plotly::subplot(ae_int$ptly, cm_int$ptly,
+ shareX = TRUE, nrows = 2,
+ titleX = TRUE, titleY = TRUE, margin = 0.005
+ ) %>%
+ plotly::layout(
+ xaxis = list(
+ range = c(xmin, xmax),
+ tickmode = "array",
+ tickvals = sepby,
+ ticktext = sepby
+ ),
+ height = 600,
+ legend = list(font = list(size = 9))
+ )
+ # Combine and align the 2 plots - static
+ plot_out <- cowplot::plot_grid(
+ ae_int$plot + scale_y_continuous(limits = c(xmin, xmax)),
+ cm_int$plot + scale_y_continuous(limits = c(xmin, xmax)),
+ align = "v",
+ nrow = 2
+ )
+ }
+ # Output data to save
+ rptdata <- bind_rows(ae_int$rpt_data, cm_int$rpt_data)
+ return(list(plot = plot_out, ptly = ptly_out, rpt_data = rptdata, title = title))
+ } else {
+ return(list(plot = ae_int$plot, ptly = ae_int$ptly, rpt_data = ae_int$rpt_data, title = title))
+ }
+}
diff --git a/R/risk_stat.R b/R/risk_stat.R
index 8481c56..32c848a 100644
--- a/R/risk_stat.R
+++ b/R/risk_stat.R
@@ -58,7 +58,7 @@ risk_stat <- function(datain,
sort_opt,
sort_var) {
if (nrow(datain) == 0) {
- return(NULL)
+ return(data.frame())
}
if (is.null(ctrlgrp) || is.null(trtgrp)) {
@@ -94,9 +94,11 @@ risk_stat <- function(datain,
}
## looping through all the treatment pairs
- for (t in trtgrp) {
+ for (treatment2 in trtgrp) {
treatment1 <- ctrlgrp
- treatment2 <- t
+ if (!(all(c(treatment1, treatment2) %in% unique(datain$TRTVAR)))) {
+ return(data.frame())
+ }
### Filtering based on selected treatment groups -----------------------------
data1 <- datain %>%
filter(TRTVAR %in% c(treatment1, treatment2))
@@ -128,10 +130,9 @@ risk_stat <- function(datain,
collapse = " "
)) %>%
filter(PCT_CTRLGRP > cutoff | PCT_TRTGRP > cutoff) # filter based on cutoff value
-
## check for data after cut off
if (nrow(mcatd) == 0) {
- return(NULL)
+ return(data.frame())
}
aeSummCutOff <- mcatd %>%
diff --git a/R/utils.R b/R/utils.R
index a6c71ad..ebbd193 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -173,3 +173,86 @@ var_start <- function(df, pattern) {
sort(names(df)[startsWith(names(df), pattern) & (!endsWith(names(df), "N"))])
}
}
+
+#' Empty plot with message
+#'
+#' @param message Required message to be displayed within plot area
+#' @param fontsize Set the font size of the message
+#'
+#' @return a list containing 2 objects
+#' \itemize{
+#' \item ptly - Interactive empty plot
+#' \item plot - Static empty plot
+#' }
+#' @export
+#'
+#' @examples
+#' library(cvars)
+#' empty_plot()
+empty_plot <- function(message = "No data available for these values",
+ fontsize = 8) {
+ g_plot <- ggplot() +
+ annotate("text",
+ x = 1, y = 1, size = fontsize,
+ label = message
+ ) +
+ theme_void()
+ fig <- plotly::ggplotly(g_plot, height = 200) %>%
+ plotly::layout(
+ xaxis = list(visible = FALSE), yaxis = list(visible = FALSE)
+ )
+ return(list(plot = g_plot, ptly = fig))
+}
+
+#' Report Metadata
+#'
+#' @return `data.frame` containing report metadata
+#' @noRd
+#'
+get_report_meta <- function() {
+ tibble::tribble(
+ ~TA,
+ ~DOMAIN,
+ ~REPNAME,
+ ~REPDESC,
+ ~REPNO,
+ ~REPTYPE,
+ "Any",
+ "ADAE",
+ "adae_r001",
+ "Summary of Adverse Events by System Organ Class and Preferred Term",
+ "2.1",
+ "Table",
+ "Any",
+ "ADAE",
+ "Forest Plot",
+ "Forest plot for adverse events",
+ "2.2",
+ "Figure",
+ "Any",
+ "ADAE",
+ "Volcano Plot",
+ "Volcano plot for adverse events",
+ "2.4",
+ "Figure",
+ "Any",
+ "ADAE",
+ "Event Analysis",
+ "Event analysis of MedRA query",
+ "2.5",
+ "Figure",
+ )
+}
+
+get_ae_term <- function() {
+ aeTerm <- c(
+ "Reported Term for the Adverse Event (AETERM)" = "AETERM",
+ "AE Lowest Level Term (AELLT)" = "AELLT",
+ "AE Dictionary-Derived Term (AEDECOD)" = "AEDECOD",
+ "AE High Level Term (AEHLT)" = "AEHLT",
+ "AE High Level Group Term (AEHLGT)" = "AEHLGT",
+ "Primary System Organ Class (AESOC)" = "AESOC",
+ "Body System or Organ Class (AEBODSYS)" = "AEBODSYS",
+ "FMQ Name (FMQ_NAM)" = "FMQ_NAM"
+ )
+}
diff --git a/R/volcano_plot.R b/R/volcano_plot.R
index 11e4922..84a7893 100644
--- a/R/volcano_plot.R
+++ b/R/volcano_plot.R
@@ -64,26 +64,8 @@ volcano_plot <- function(datain,
### Construction of volcano plot
# Check if getstats data is empty:
if (nrow(statistics_data) == 0) {
- p <- ggplot() +
- annotate(
- "text",
- x = 4,
- y = 25,
- size = 8,
- label = "No data selected for plot."
- ) +
- theme_bw() +
- theme(
- panel.grid.major = element_blank(),
- panel.grid.minor = element_blank(),
- axis.title.x = element_blank(),
- axis.text.x = element_blank(),
- axis.ticks.x = element_blank(),
- axis.title.y = element_blank(),
- axis.text.y = element_blank(),
- axis.ticks.y = element_blank()
- )
- return(list(plot = p, rpt_data = datain))
+ output <- empty_plot()
+ return(list(ptly = output$ptly, plot = output$plot, rpt_data = datain))
}
statistics_data <- statistics_data %>% filter(RISK != Inf)
@@ -180,37 +162,36 @@ volcano_plot <- function(datain,
}
text1 <- paste0(
- "<- Favors ", treatment1_label,
+ "<---- Favors ", treatment1_label,
" (N=", N1_Total, ")"
)
text2 <- paste0(
"Favors ", treatment2_label,
- " (N=", N2_Total, ") ->"
+ " (N=", N2_Total, ") ---->"
)
- lab1 <-
- paste(statistics, treatment1_label, "vs.", treatment2_label)
- lab2 <- paste(text1, text2)
+ lab2 <- paste0(text1, " ----- ", text2)
- label_fin <- unique(paste0(lab2, "\n", lab1))
+ label_fin <- unique(paste0(lab2, "\n", statistics))
output <-
plotly::ggplotly(
p,
tooltip = c("text"),
source = "plot_output",
- height = 800,
- width = 800
+ height = 600,
+ width = 1000
) %>%
plotly::layout(
legend = list(
- font = list(size = 8.5),
+ font = list(size = 8),
orientation = "h",
- x = 0.4,
- y = -0.2
+ x = 0.5,
+ y = -0.2,
+ xanchor = "center", yanchor = "top"
),
title = list(text = ""),
- xaxis = list(title = unique(paste0(lab2, "
", lab1))),
+ xaxis = list(title = unique(paste0(lab2, "
", statistics))),
yaxis = list(title = "")
)
@@ -240,14 +221,14 @@ volcano_plot <- function(datain,
ifelse(tolower(summary_by) == "patients", "participants", "events"),
". \n",
"Classifications of adverse events are based on the Medical Dictionary for Regulatory Activities (MedDRA v21.1). \n", # nolint
- "Dashed horizontal line represents p-value of 0.05 \n",
- "Dotted horizontal line represents FDR adjusted p-value of approximately 0.05 (when applicable) \n", # nolint
- "Dashed Vertical line represents risk value reference line \n",
- "Totals for the No. of Participants/Events at a higher level are not necessarily the sum of those at the lower levels since a participant may report two or more \n", # nolint
+ "Dashed horizontal line represents p-value of ", pvalcut, ".\n",
+ "Dotted horizontal line represents FDR adjusted p-value of approximately ", pvalcut, " (when applicable). \n", # nolint
+ "Dashed Vertical line represents risk value reference line. \n",
+ "Totals for the No. of Participants/Events at a higher level are not necessarily the sum of those at the lower levels since a participant may report two or more. \n", # nolint
ifelse(
tolower(summary_by) == "patients",
"The number of participants reporting at least 1 occurrence of the event specified.",
- "Event counts are the sum of individual occurrences within that category"
+ "Event counts are the sum of individual occurrences within that category."
)
)
diff --git a/README.Rmd b/README.Rmd
index b23b7f3..f21cae2 100644
--- a/README.Rmd
+++ b/README.Rmd
@@ -1,3 +1,42 @@
+<<<<<<< HEAD
+---
+title: "cvars"
+output: md_document
+date: '2023-07-26'
+---
+
+
+
+# Clinical Visual Analytics for Review and Submission
+
+
+ [![R-CMD-check](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/R-CMD-check.yaml)
+ [![test-coverage](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/test-coverage.yaml/badge.svg)](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/test-coverage.yaml)
+ [![lint](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/lint.yaml/badge.svg)](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/lint.yaml)
+ [![Style](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/styler.yaml/badge.svg)](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/styler.yaml)
+
+
+Clinical Visual Analytics for Review and Submission
+
+## Purpose
+
+Development of an open-source tool and package to enable generation of identified interactive plots for clinical review and direct inclusion in submission for regulatory agencies. The initial scope is to develop a package to generate interactive forest and volcano plots for adverse event and FDA Medical Queries (FMQs) analysis outputs for inclusion in submissions to the FDA. This work is a collaboration among the American Statistical Association (ASA), PHUSE, and FDA.
+
+### Dependencies
+
+The latest version of the package works with the latest versions of the packages
+stated in `DESCRIPTION`.
+
+If a previous version of the package should be used, it is recommended to use
+latest version of the dependencies at the point of time when the previous
+version of {cvars} was released.
+
+## Scope
+
+* Build a toolbox of re-usable functions and utilities to create Clinical Domain tables and figures.
+* Clinical Domain datasets which are used to create tables and figures should follow CDISC standards.
+
+=======
---
title: "cvars"
output: md_document
@@ -35,3 +74,4 @@ version of {cvars} was released.
* Build a toolbox of re-usable functions and utilities to create Clinical Domain tables and figures.
* Clinical Domain datasets which are used to create tables and figures should follow CDISC standards.
+>>>>>>> 0cd101109665f2699b442aa971069068a28e65d5
diff --git a/README.md b/README.md
index e4e25f2..3867840 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,44 @@
+<<<<<<< HEAD
+
+
+# Clinical Visual Analytics for Review and Submission
+
+
+
+[![R-CMD-check](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/R-CMD-check.yaml)
+[![test-coverage](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/test-coverage.yaml/badge.svg)](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/test-coverage.yaml)
+[![lint](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/lint.yaml/badge.svg)](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/lint.yaml)
+[![Style](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/styler.yaml/badge.svg)](https://github.com/pfizer-rd/spa-r-ae-summaries/actions/workflows/styler.yaml)
+
+
+Clinical Visual Analytics for Review and Submission
+
+## Purpose
+
+Development of an open-source tool and package to enable generation of
+identified interactive plots for clinical review and direct inclusion in
+submission for regulatory agencies. The initial scope is to develop a
+package to generate interactive forest and volcano plots for adverse
+event and FDA Medical Queries (FMQs) analysis outputs for inclusion in
+submissions to the FDA. This work is a collaboration among the American
+Statistical Association (ASA), PHUSE, and FDA.
+
+### Dependencies
+
+The latest version of the package works with the latest versions of the
+packages stated in `DESCRIPTION`.
+
+If a previous version of the package should be used, it is recommended
+to use latest version of the dependencies at the point of time when the
+previous version of {cvars} was released.
+
+## Scope
+
+- Build a toolbox of re-usable functions and utilities to create
+ Clinical Domain tables and figures.
+- Clinical Domain datasets which are used to create tables and figures
+ should follow CDISC standards.
+=======
# Clinical Visual Analytics for Review and Submission
@@ -37,3 +78,4 @@ previous version of {cvars} was released.
Clinical Domain tables and figures.
- Clinical Domain datasets which are used to create tables and figures
should follow CDISC standards.
+>>>>>>> 0cd101109665f2699b442aa971069068a28e65d5
diff --git a/data/cm.rda b/data/cm.rda
new file mode 100644
index 0000000..3c77195
Binary files /dev/null and b/data/cm.rda differ
diff --git a/inst/app/www/custom.css b/inst/app/www/custom.css
new file mode 100644
index 0000000..b6b8a1b
--- /dev/null
+++ b/inst/app/www/custom.css
@@ -0,0 +1,76 @@
+.content-wrapper {
+ background-color: #ffffff !important;
+}
+
+.brand-link {
+ display: flex !important;
+ font-size: 1.25rem;
+ line-height: 1.5;
+ padding: .8125rem .5rem;
+ transition: width .3s ease-in-out;
+ white-space: nowrap;
+ justify-content: center !important;
+ background-color: #051650 !important;
+ color: white !important;
+ font-family: math !important;
+ font-weight: bold !important;
+}
+
+.sidebar-btn {
+ color: #051650 !important;
+ background-color: #DAF5FF;
+ border: 2px solid #051650;
+ font-size: 14px;
+ font-weight: 600;
+ text-align: center;
+ margin-right: 1.5vw !important;
+ border-radius: 9px;
+ width: 125px !important;
+}
+
+.download-btn {
+ color: #fff !important;
+ background-color: #28a745;
+ border: 2px solid #051650;
+ font-size: 14px;
+ font-weight: 600;
+ text-align: center;
+ margin-right: 0.75vw !important;
+ border-radius: 9px;
+ width: 125px !important;
+}
+
+.fa-solid, .fas {
+ font-weight: 900;
+ color: #051650 !important;
+}
+
+#download_report_1-save_btn > i.fas.fa-download {
+ color: #fff !important;
+}
+
+.card {
+ box-shadow: 0 0 2px #051650, 0 3px 3px #051650;
+ margin-bottom: 1rem;
+}
+
+.card-header {
+ background-color: transparent;
+ padding: .75rem 1.25rem;
+ position: relative;
+ border-top-left-radius: .25rem;
+ border-top-right-radius: .25rem;
+}
+
+#collapse_save_down_1 > div, #collapse_load_data_1 > div {
+ padding: 0.1rem !important;
+}
+
+.d-block {
+ display: flex !important;
+ justify-content: center;
+}
+
+.accordion>.card {
+ overflow: overlay;
+}
diff --git a/inst/extdata/cm.xpt b/inst/extdata/cm.xpt
new file mode 100644
index 0000000..37bb289
Binary files /dev/null and b/inst/extdata/cm.xpt differ
diff --git a/man/cm.Rd b/man/cm.Rd
new file mode 100644
index 0000000..879c873
--- /dev/null
+++ b/man/cm.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/data.R
+\docType{data}
+\name{cm}
+\alias{cm}
+\title{CM}
+\format{
+Data frame with 7510 rows and 21 variables
+}
+\source{
+\url{https://github.com/phuse-org/aesummaries/tree/main/inst/extdata/cm.xpt},
+downloaded 2023-08-24
+}
+\usage{
+cm
+}
+\description{
+Concomitant Medications Dataset
+}
+\keyword{datasets}
diff --git a/man/cvars-package.Rd b/man/cvars-package.Rd
index 6da7a7d..1c84a6c 100644
--- a/man/cvars-package.Rd
+++ b/man/cvars-package.Rd
@@ -1,3 +1,47 @@
+<<<<<<< HEAD
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/cvars-package.R
+\docType{package}
+\name{cvars-package}
+\alias{cvars}
+\alias{cvars-package}
+\title{cvars: Clinical Visual Analytics for Review and Submission}
+\description{
+Development of an open-source tool and package to enable generation of identified interactive plots for clinical review and direct inclusion in submission for regulatory agencies. The initial scope is to develop a package to generate interactive forest and volcano plots for adverse event and FDA Medical Queries (FMQs) analysis outputs for inclusion in submissions to the FDA. This work is a collaboration among the American Statistical Association (ASA), PHUSE, and FDA.
+}
+\seealso{
+Useful links:
+\itemize{
+ \item \url{https://github.com/phuse-org/aesummaries/}
+ \item Report bugs at \url{https://github.com/phuse-org/aesummaries/issues/}
+}
+
+}
+\author{
+\strong{Maintainer}: Smriti Anand \email{xxx@xxx.com}
+
+Authors:
+\itemize{
+ \item Jayashree V
+ \item Sukalpo Saha
+ \item Vikram S
+ \item Jagadish Katam
+ \item Arjun Rubalingam
+ \item Amol Bandu Gorde
+ \item Gomathi S
+}
+
+Other contributors:
+\itemize{
+ \item Dhivya Kanagaraj [contributor]
+ \item Neetu Sangari [contributor]
+ \item Aishwarya LR [contributor]
+ \item Manali Jadhav [contributor]
+ \item Prakasam R [contributor]
+}
+
+}
+=======
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/cvars-package.R
\docType{package}
@@ -40,3 +84,4 @@ Other contributors:
}
}
+>>>>>>> 0cd101109665f2699b442aa971069068a28e65d5
diff --git a/man/empty_plot.Rd b/man/empty_plot.Rd
new file mode 100644
index 0000000..0209f2b
--- /dev/null
+++ b/man/empty_plot.Rd
@@ -0,0 +1,27 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{empty_plot}
+\alias{empty_plot}
+\title{Empty plot with message}
+\usage{
+empty_plot(message = "No data available for these values", fontsize = 8)
+}
+\arguments{
+\item{message}{Required message to be displayed within plot area}
+
+\item{fontsize}{Set the font size of the message}
+}
+\value{
+a list containing 2 objects
+\itemize{
+\item ptly - Interactive empty plot
+\item plot - Static empty plot
+}
+}
+\description{
+Empty plot with message
+}
+\examples{
+library(cvars)
+empty_plot()
+}
diff --git a/man/figures/lifecycle-archived.svg b/man/figures/lifecycle-archived.svg
new file mode 100644
index 0000000..48f72a6
--- /dev/null
+++ b/man/figures/lifecycle-archived.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/man/figures/lifecycle-defunct.svg b/man/figures/lifecycle-defunct.svg
new file mode 100644
index 0000000..01452e5
--- /dev/null
+++ b/man/figures/lifecycle-defunct.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/man/figures/lifecycle-deprecated.svg b/man/figures/lifecycle-deprecated.svg
new file mode 100644
index 0000000..4baaee0
--- /dev/null
+++ b/man/figures/lifecycle-deprecated.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/man/figures/lifecycle-experimental.svg b/man/figures/lifecycle-experimental.svg
new file mode 100644
index 0000000..d1d060e
--- /dev/null
+++ b/man/figures/lifecycle-experimental.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/man/figures/lifecycle-maturing.svg b/man/figures/lifecycle-maturing.svg
new file mode 100644
index 0000000..df71310
--- /dev/null
+++ b/man/figures/lifecycle-maturing.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/man/figures/lifecycle-questioning.svg b/man/figures/lifecycle-questioning.svg
new file mode 100644
index 0000000..08ee0c9
--- /dev/null
+++ b/man/figures/lifecycle-questioning.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/man/figures/lifecycle-stable.svg b/man/figures/lifecycle-stable.svg
new file mode 100644
index 0000000..e015dc8
--- /dev/null
+++ b/man/figures/lifecycle-stable.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/man/figures/lifecycle-superseded.svg b/man/figures/lifecycle-superseded.svg
new file mode 100644
index 0000000..75f24f5
--- /dev/null
+++ b/man/figures/lifecycle-superseded.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/man/interval_plot.Rd b/man/interval_plot.Rd
new file mode 100644
index 0000000..6ca88f6
--- /dev/null
+++ b/man/interval_plot.Rd
@@ -0,0 +1,62 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/event_interval.R
+\name{interval_plot}
+\alias{interval_plot}
+\title{Patient-Level Interval Plot}
+\usage{
+interval_plot(
+ datain,
+ startvar,
+ endvar,
+ yvar,
+ seriesvar,
+ subjectid,
+ series_color = NA,
+ xaxislab = "Start and End Study Day",
+ yaxislab = ""
+)
+}
+\arguments{
+\item{datain}{Input events/concomitant medication dataset}
+
+\item{startvar}{Event/Treatment Start Day Variable name (X axis)}
+
+\item{endvar}{Event/Treatment End Day Variable name (X axis)}
+
+\item{yvar}{Variable containing event terms or medications to be plotted in Y axis}
+
+\item{seriesvar}{Variable to stratify plot by color or NA to have no stratification}
+
+\item{subjectid}{Selected \code{USUBJID} variable value}
+
+\item{series_color}{List of colors to be assigned to levels in \code{seriesvar} or
+NA to use package defaults}
+
+\item{xaxislab}{Label for plot X axis}
+
+\item{yaxislab}{Label for plot Y axis}
+}
+\value{
+: a list containing 3 objects
+\itemize{
+\item ptly - Interactive plot output for display
+\item plot - Static plot output for saving externally
+\item rpt_data - Dataset used to create forest plot, for validation purpose
+}
+}
+\description{
+Patient-Level Interval Plot
+}
+\examples{
+data(adae)
+interval_plot(
+ datain = adae,
+ startvar = "ASTDY",
+ endvar = "AENDY",
+ yvar = "AEDECOD",
+ seriesvar = "AESEV",
+ subjectid = "01-701-1302",
+ series_color = NA,
+ yaxislab = "Reported Term for the Adverse Event"
+)$ptly
+}
diff --git a/man/multi_interval.Rd b/man/multi_interval.Rd
new file mode 100644
index 0000000..8577002
--- /dev/null
+++ b/man/multi_interval.Rd
@@ -0,0 +1,35 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/multi_interval.R
+\name{multi_interval}
+\alias{multi_interval}
+\title{Aligned Interval Plot for Adverse Events and Concomitant Medication}
+\usage{
+multi_interval(datain, subjectid)
+}
+\arguments{
+\item{datain}{Input list containing an element named \code{AE} (required) and an element named \code{CM}
+with the corresponding dataframes}
+
+\item{subjectid}{Participant ID (from the variable \code{USUBJID})}
+}
+\value{
+: a list containing 4 objects
+\itemize{
+\item ptly - Interactive plot output for display
+\item plot - Static plot output for saving externally
+\item rpt_data - Dataset used to create plot(s), for validation purpose
+\item title - Report title/header, for download purpose
+}
+}
+\description{
+Aligned Interval Plot for Adverse Events and Concomitant Medication
+}
+\examples{
+library(cvars)
+data(adae)
+data(cm)
+multi_interval(
+ datain = list(AE = adae, CM = cm),
+ subjectid = "01-717-1446"
+)$ptly
+}
diff --git a/renv.lock b/renv.lock
index e1637bd..9ec296d 100644
--- a/renv.lock
+++ b/renv.lock
@@ -1,3 +1,2198 @@
+<<<<<<< HEAD
+{
+ "R": {
+ "Version": "4.1.1",
+ "Repositories": [
+ {
+ "Name": "CRAN",
+ "URL": "https://cloud.r-project.org"
+ }
+ ]
+ },
+ "Packages": {
+ "BH": {
+ "Package": "BH",
+ "Version": "1.81.0-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "68122010f01c4dcfbe58ce7112f2433d"
+ },
+ "DT": {
+ "Package": "DT",
+ "Version": "0.23",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "crosstalk",
+ "htmltools",
+ "htmlwidgets",
+ "jquerylib",
+ "jsonlite",
+ "magrittr",
+ "promises"
+ ],
+ "Hash": "d8f1498dc47763ce4647c8d03214d30b"
+ },
+ "MASS": {
+ "Package": "MASS",
+ "Version": "7.3-54",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "methods",
+ "stats",
+ "utils"
+ ],
+ "Hash": "0e59129db205112e3963904db67fd0dc"
+ },
+ "Matrix": {
+ "Package": "Matrix",
+ "Version": "1.3-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "graphics",
+ "grid",
+ "lattice",
+ "methods",
+ "stats",
+ "utils"
+ ],
+ "Hash": "df57c82e79600601287edfdcef92c2d6"
+ },
+ "R6": {
+ "Package": "R6",
+ "Version": "2.5.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "470851b6d5d0ac559e9d01bb352b4021"
+ },
+ "RColorBrewer": {
+ "Package": "RColorBrewer",
+ "Version": "1.1-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "45f0398006e83a5b10b72a90663d8d8c"
+ },
+ "RCurl": {
+ "Package": "RCurl",
+ "Version": "1.98-1.12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "bitops",
+ "methods"
+ ],
+ "Hash": "1d6ed2d006d483f31c6d5531f3a39923"
+ },
+ "Rcpp": {
+ "Package": "Rcpp",
+ "Version": "1.0.10",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "methods",
+ "utils"
+ ],
+ "Hash": "e749cae40fa9ef469b6050959517453c"
+ },
+ "anytime": {
+ "Package": "anytime",
+ "Version": "0.3.9",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "BH",
+ "R",
+ "Rcpp"
+ ],
+ "Hash": "74a64813f17b492da9c6afda6b128e3d"
+ },
+ "askpass": {
+ "Package": "askpass",
+ "Version": "1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "sys"
+ ],
+ "Hash": "e8a22846fff485f0be3770c2da758713"
+ },
+ "attempt": {
+ "Package": "attempt",
+ "Version": "0.3.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "rlang"
+ ],
+ "Hash": "d7421bb5dfeb2676b9e4a5a60c2fcfd2"
+ },
+ "base64enc": {
+ "Package": "base64enc",
+ "Version": "0.1-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "543776ae6848fde2f48ff3816d0628bc"
+ },
+ "bit": {
+ "Package": "bit",
+ "Version": "4.0.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "f36715f14d94678eea9933af927bc15d"
+ },
+ "bit64": {
+ "Package": "bit64",
+ "Version": "4.0.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "bit",
+ "methods",
+ "stats",
+ "utils"
+ ],
+ "Hash": "9fe98599ca456d6552421db0d6772d8f"
+ },
+ "bitops": {
+ "Package": "bitops",
+ "Version": "1.0-7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b7d8d8ee39869c18d8846a184dd8a1af"
+ },
+ "brew": {
+ "Package": "brew",
+ "Version": "1.0-8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d69a786e85775b126bddbee185ae6084"
+ },
+ "brio": {
+ "Package": "brio",
+ "Version": "1.1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "976cf154dfb043c012d87cddd8bca363"
+ },
+ "bslib": {
+ "Package": "bslib",
+ "Version": "0.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "base64enc",
+ "cachem",
+ "grDevices",
+ "htmltools",
+ "jquerylib",
+ "jsonlite",
+ "memoise",
+ "mime",
+ "rlang",
+ "sass"
+ ],
+ "Hash": "1b117970533deb6d4e992c1b34e9d905"
+ },
+ "cachem": {
+ "Package": "cachem",
+ "Version": "1.0.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "fastmap",
+ "rlang"
+ ],
+ "Hash": "cda74447c42f529de601fe4d4050daef"
+ },
+ "callr": {
+ "Package": "callr",
+ "Version": "3.7.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "processx",
+ "utils"
+ ],
+ "Hash": "9b2191ede20fa29828139b9900922e51"
+ },
+ "cli": {
+ "Package": "cli",
+ "Version": "3.6.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "utils"
+ ],
+ "Hash": "89e6d8219950eac806ae0c489052048a"
+ },
+ "clipr": {
+ "Package": "clipr",
+ "Version": "0.8.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "utils"
+ ],
+ "Hash": "3f038e5ac7f41d4ac41ce658c85e3042"
+ },
+ "colorspace": {
+ "Package": "colorspace",
+ "Version": "2.0-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "methods",
+ "stats"
+ ],
+ "Hash": "bb4341986bc8b914f0f0acf2e4a3f2f7"
+ },
+ "commonmark": {
+ "Package": "commonmark",
+ "Version": "1.9.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d691c61bff84bd63c383874d2d0c3307"
+ },
+ "config": {
+ "Package": "config",
+ "Version": "0.3.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "yaml"
+ ],
+ "Hash": "31d77b09f63550cee9ecb5a08bf76e8f"
+ },
+ "cowplot": {
+ "Package": "cowplot",
+ "Version": "1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "ggplot2",
+ "grDevices",
+ "grid",
+ "gtable",
+ "methods",
+ "rlang",
+ "scales"
+ ],
+ "Hash": "b418e8423699d11c7f2087c2bfd07da2"
+ },
+ "cpp11": {
+ "Package": "cpp11",
+ "Version": "0.4.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f07821e9b0aada6c999d4692e22a2ea7"
+ },
+ "crayon": {
+ "Package": "crayon",
+ "Version": "1.5.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "grDevices",
+ "methods",
+ "utils"
+ ],
+ "Hash": "e8a1e41acf02548751f45c718d55aa6a"
+ },
+ "credentials": {
+ "Package": "credentials",
+ "Version": "1.3.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "askpass",
+ "curl",
+ "jsonlite",
+ "openssl",
+ "sys"
+ ],
+ "Hash": "93762d0a34d78e6a025efdbfb5c6bb41"
+ },
+ "crosstalk": {
+ "Package": "crosstalk",
+ "Version": "1.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "htmltools",
+ "jsonlite",
+ "lazyeval"
+ ],
+ "Hash": "6aa54f69598c32177e920eb3402e8293"
+ },
+ "crul": {
+ "Package": "crul",
+ "Version": "1.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "curl",
+ "httpcode",
+ "jsonlite",
+ "mime",
+ "urltools"
+ ],
+ "Hash": "1eb00a531331c91d970f3af74b75321f"
+ },
+ "curl": {
+ "Package": "curl",
+ "Version": "5.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "e4f97056611e8e6b8b852d13b7400cf1"
+ },
+ "data.table": {
+ "Package": "data.table",
+ "Version": "1.14.8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "b4c06e554f33344e044ccd7fdca750a9"
+ },
+ "desc": {
+ "Package": "desc",
+ "Version": "1.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "cli",
+ "rprojroot",
+ "utils"
+ ],
+ "Hash": "6b9602c7ebbe87101a9c8edb6e8b6d21"
+ },
+ "devtools": {
+ "Package": "devtools",
+ "Version": "2.4.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "desc",
+ "ellipsis",
+ "fs",
+ "lifecycle",
+ "memoise",
+ "miniUI",
+ "pkgbuild",
+ "pkgdown",
+ "pkgload",
+ "profvis",
+ "rcmdcheck",
+ "remotes",
+ "rlang",
+ "roxygen2",
+ "rversions",
+ "sessioninfo",
+ "stats",
+ "testthat",
+ "tools",
+ "urlchecker",
+ "usethis",
+ "utils",
+ "withr"
+ ],
+ "Hash": "ea5bc8b4a6a01e4f12d98b58329930bb"
+ },
+ "diffobj": {
+ "Package": "diffobj",
+ "Version": "0.3.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "crayon",
+ "methods",
+ "stats",
+ "tools",
+ "utils"
+ ],
+ "Hash": "bcaa8b95f8d7d01a5dedfd959ce88ab8"
+ },
+ "digest": {
+ "Package": "digest",
+ "Version": "0.6.31",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "utils"
+ ],
+ "Hash": "8b708f296afd9ae69f450f9640be8990"
+ },
+ "downlit": {
+ "Package": "downlit",
+ "Version": "0.4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "brio",
+ "desc",
+ "digest",
+ "evaluate",
+ "fansi",
+ "memoise",
+ "rlang",
+ "vctrs",
+ "withr",
+ "yaml"
+ ],
+ "Hash": "14fa1f248b60ed67e1f5418391a17b14"
+ },
+ "dplyr": {
+ "Package": "dplyr",
+ "Version": "1.1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "cli",
+ "generics",
+ "glue",
+ "lifecycle",
+ "magrittr",
+ "methods",
+ "pillar",
+ "rlang",
+ "tibble",
+ "tidyselect",
+ "utils",
+ "vctrs"
+ ],
+ "Hash": "dea6970ff715ca541c387de363ff405e"
+ },
+ "ellipsis": {
+ "Package": "ellipsis",
+ "Version": "0.3.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "rlang"
+ ],
+ "Hash": "bb0eec2fe32e88d9e2836c2f73ea2077"
+ },
+ "epitools": {
+ "Package": "epitools",
+ "Version": "0.5-10.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "b1eef914dc165a4974012e43efb58da0"
+ },
+ "evaluate": {
+ "Package": "evaluate",
+ "Version": "0.21",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "d59f3b464e8da1aef82dc04b588b8dfb"
+ },
+ "fansi": {
+ "Package": "fansi",
+ "Version": "1.0.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "utils"
+ ],
+ "Hash": "1d9e7ad3c8312a192dea7d3db0274fde"
+ },
+ "farver": {
+ "Package": "farver",
+ "Version": "2.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c98eb5133d9cb9e1622b8691487f11bb"
+ },
+ "fastmap": {
+ "Package": "fastmap",
+ "Version": "1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f7736a18de97dea803bde0a2daaafb27"
+ },
+ "flextable": {
+ "Package": "flextable",
+ "Version": "0.9.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "data.table",
+ "gdtools",
+ "grDevices",
+ "graphics",
+ "grid",
+ "htmltools",
+ "knitr",
+ "officer",
+ "ragg",
+ "rlang",
+ "rmarkdown",
+ "stats",
+ "utils",
+ "uuid",
+ "xml2"
+ ],
+ "Hash": "58659ef4f0801843693d59ff4bbc120f"
+ },
+ "fontBitstreamVera": {
+ "Package": "fontBitstreamVera",
+ "Version": "0.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "f6068021eff4aba735a9b2353516636c"
+ },
+ "fontLiberation": {
+ "Package": "fontLiberation",
+ "Version": "0.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "f918c5e723f86f409912104d5b7a71d6"
+ },
+ "fontawesome": {
+ "Package": "fontawesome",
+ "Version": "0.5.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "htmltools",
+ "rlang"
+ ],
+ "Hash": "1e22b8cabbad1eae951a75e9f8b52378"
+ },
+ "fontquiver": {
+ "Package": "fontquiver",
+ "Version": "0.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "fontBitstreamVera",
+ "fontLiberation"
+ ],
+ "Hash": "fc0f4226379e451057d55419fd31761e"
+ },
+ "forcats": {
+ "Package": "forcats",
+ "Version": "0.5.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "ellipsis",
+ "magrittr",
+ "rlang",
+ "tibble"
+ ],
+ "Hash": "81c3244cab67468aac4c60550832655d"
+ },
+ "fs": {
+ "Package": "fs",
+ "Version": "1.5.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "7c89603d81793f0d5486d91ab1fc6f1d"
+ },
+ "ftExtra": {
+ "Package": "ftExtra",
+ "Version": "0.6.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "dplyr",
+ "flextable",
+ "jsonlite",
+ "magrittr",
+ "purrr",
+ "rlang",
+ "rmarkdown",
+ "stringr",
+ "tibble",
+ "tidyr",
+ "tidyselect",
+ "vctrs",
+ "xfun",
+ "yaml"
+ ],
+ "Hash": "8e274d5609c55838b41d800d3ef75d7d"
+ },
+ "gdtools": {
+ "Package": "gdtools",
+ "Version": "0.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "Rcpp",
+ "curl",
+ "fontquiver",
+ "gfonts",
+ "htmltools",
+ "systemfonts",
+ "tools"
+ ],
+ "Hash": "98158453e15bbd2486fac8454f4b4409"
+ },
+ "generics": {
+ "Package": "generics",
+ "Version": "0.1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "15e9634c0fcd294799e9b2e929ed1b86"
+ },
+ "gert": {
+ "Package": "gert",
+ "Version": "1.9.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "askpass",
+ "credentials",
+ "openssl",
+ "rstudioapi",
+ "sys",
+ "zip"
+ ],
+ "Hash": "9122b3958e749badb5c939f498038b57"
+ },
+ "gfonts": {
+ "Package": "gfonts",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "crayon",
+ "crul",
+ "glue",
+ "htmltools",
+ "jsonlite",
+ "shiny",
+ "utils"
+ ],
+ "Hash": "a535d76cf92645364997a8751396d63b"
+ },
+ "ggplot2": {
+ "Package": "ggplot2",
+ "Version": "3.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "MASS",
+ "R",
+ "cli",
+ "glue",
+ "grDevices",
+ "grid",
+ "gtable",
+ "isoband",
+ "lifecycle",
+ "mgcv",
+ "rlang",
+ "scales",
+ "stats",
+ "tibble",
+ "vctrs",
+ "withr"
+ ],
+ "Hash": "d494daf77c4aa7f084dbbe6ca5dcaca7"
+ },
+ "ggstance": {
+ "Package": "ggstance",
+ "Version": "0.3.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "ggplot2",
+ "plyr",
+ "rlang",
+ "withr"
+ ],
+ "Hash": "ef69648fcaaffebac4007ac4b43322ed"
+ },
+ "gh": {
+ "Package": "gh",
+ "Version": "1.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "gitcreds",
+ "httr2",
+ "ini",
+ "jsonlite",
+ "rlang"
+ ],
+ "Hash": "03533b1c875028233598f848fda44c4c"
+ },
+ "gitcreds": {
+ "Package": "gitcreds",
+ "Version": "0.1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "ab08ac61f3e1be454ae21911eb8bc2fe"
+ },
+ "glue": {
+ "Package": "glue",
+ "Version": "1.6.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "4f2596dfb05dac67b9dc558e5c6fba2e"
+ },
+ "golem": {
+ "Package": "golem",
+ "Version": "0.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "attempt",
+ "config",
+ "here",
+ "htmltools",
+ "rlang",
+ "shiny",
+ "utils",
+ "yaml"
+ ],
+ "Hash": "dc12172dc35c6c80e18b430dc546fc24"
+ },
+ "gtable": {
+ "Package": "gtable",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grid"
+ ],
+ "Hash": "ac5c6baf7822ce8732b343f14c072c4d"
+ },
+ "haven": {
+ "Package": "haven",
+ "Version": "2.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "cpp11",
+ "forcats",
+ "hms",
+ "lifecycle",
+ "methods",
+ "readr",
+ "rlang",
+ "tibble",
+ "tidyselect",
+ "vctrs"
+ ],
+ "Hash": "e3058e4ac77f4fa686f68a1838d5b715"
+ },
+ "here": {
+ "Package": "here",
+ "Version": "1.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "rprojroot"
+ ],
+ "Hash": "24b224366f9c2e7534d2344d10d59211"
+ },
+ "highr": {
+ "Package": "highr",
+ "Version": "0.10",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "xfun"
+ ],
+ "Hash": "06230136b2d2b9ba5805e1963fa6e890"
+ },
+ "hms": {
+ "Package": "hms",
+ "Version": "1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "ellipsis",
+ "lifecycle",
+ "methods",
+ "pkgconfig",
+ "rlang",
+ "vctrs"
+ ],
+ "Hash": "5b8a2dd0fdbe2ab4f6081e6c7be6dfca"
+ },
+ "htmltools": {
+ "Package": "htmltools",
+ "Version": "0.5.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "base64enc",
+ "digest",
+ "ellipsis",
+ "fastmap",
+ "grDevices",
+ "rlang",
+ "utils"
+ ],
+ "Hash": "ba0240784ad50a62165058a27459304a"
+ },
+ "htmlwidgets": {
+ "Package": "htmlwidgets",
+ "Version": "1.6.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "grDevices",
+ "htmltools",
+ "jsonlite",
+ "knitr",
+ "rmarkdown",
+ "yaml"
+ ],
+ "Hash": "a865aa85bcb2697f47505bfd70422471"
+ },
+ "httpcode": {
+ "Package": "httpcode",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "13641a1c6d2cc98801b76764078e17ea"
+ },
+ "httpuv": {
+ "Package": "httpuv",
+ "Version": "1.6.9",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "Rcpp",
+ "later",
+ "promises",
+ "utils"
+ ],
+ "Hash": "1046aa31a57eae8b357267a56a0b6d8b"
+ },
+ "httr": {
+ "Package": "httr",
+ "Version": "1.4.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "curl",
+ "jsonlite",
+ "mime",
+ "openssl"
+ ],
+ "Hash": "7e5e3cbd2a7bc07880c94e22348fb661"
+ },
+ "httr2": {
+ "Package": "httr2",
+ "Version": "0.2.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "cli",
+ "curl",
+ "glue",
+ "magrittr",
+ "openssl",
+ "rappdirs",
+ "rlang",
+ "withr"
+ ],
+ "Hash": "193bb297368afbbb42dc85784a46b36e"
+ },
+ "ini": {
+ "Package": "ini",
+ "Version": "0.3.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6154ec2223172bce8162d4153cda21f7"
+ },
+ "isoband": {
+ "Package": "isoband",
+ "Version": "0.2.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "grid",
+ "utils"
+ ],
+ "Hash": "7ab57a6de7f48a8dc84910d1eca42883"
+ },
+ "jquerylib": {
+ "Package": "jquerylib",
+ "Version": "0.1.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "htmltools"
+ ],
+ "Hash": "5aab57a3bd297eee1c1d862735972182"
+ },
+ "jsonlite": {
+ "Package": "jsonlite",
+ "Version": "1.8.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "methods"
+ ],
+ "Hash": "a4269a09a9b865579b2635c77e572374"
+ },
+ "knitr": {
+ "Package": "knitr",
+ "Version": "1.43",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "evaluate",
+ "highr",
+ "methods",
+ "tools",
+ "xfun",
+ "yaml"
+ ],
+ "Hash": "9775eb076713f627c07ce41d8199d8f6"
+ },
+ "labeling": {
+ "Package": "labeling",
+ "Version": "0.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "graphics",
+ "stats"
+ ],
+ "Hash": "3d5108641f47470611a32d0bdf357a72"
+ },
+ "later": {
+ "Package": "later",
+ "Version": "1.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "Rcpp",
+ "rlang"
+ ],
+ "Hash": "7e7b457d7766bc47f2a5f21cc2984f8e"
+ },
+ "lattice": {
+ "Package": "lattice",
+ "Version": "0.20-44",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "grid",
+ "stats",
+ "utils"
+ ],
+ "Hash": "f36bf1a849d9106dc2af72e501f9de41"
+ },
+ "lazyeval": {
+ "Package": "lazyeval",
+ "Version": "0.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "d908914ae53b04d4c0c0fd72ecc35370"
+ },
+ "lifecycle": {
+ "Package": "lifecycle",
+ "Version": "1.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "rlang"
+ ],
+ "Hash": "001cecbeac1cff9301bdc3775ee46a86"
+ },
+ "magrittr": {
+ "Package": "magrittr",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "7ce2733a9826b3aeb1775d56fd305472"
+ },
+ "markdown": {
+ "Package": "markdown",
+ "Version": "1.1",
+ "Source": "Repository",
+ "Repository": "RSPM",
+ "Requirements": [
+ "R",
+ "mime",
+ "utils",
+ "xfun"
+ ],
+ "Hash": "61e4a10781dd00d7d81dd06ca9b94e95"
+ },
+ "memoise": {
+ "Package": "memoise",
+ "Version": "2.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "cachem",
+ "rlang"
+ ],
+ "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c"
+ },
+ "mgcv": {
+ "Package": "mgcv",
+ "Version": "1.8-35",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "Matrix",
+ "R",
+ "graphics",
+ "methods",
+ "nlme",
+ "splines",
+ "stats",
+ "utils"
+ ],
+ "Hash": "89fd8b2ad4a6cb4979b78cf2a77ab503"
+ },
+ "mime": {
+ "Package": "mime",
+ "Version": "0.12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "tools"
+ ],
+ "Hash": "18e9c28c1d3ca1560ce30658b22ce104"
+ },
+ "miniUI": {
+ "Package": "miniUI",
+ "Version": "0.1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "htmltools",
+ "shiny",
+ "utils"
+ ],
+ "Hash": "fec5f52652d60615fdb3957b3d74324a"
+ },
+ "munsell": {
+ "Package": "munsell",
+ "Version": "0.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "colorspace",
+ "methods"
+ ],
+ "Hash": "6dfe8bf774944bd5595785e3229d8771"
+ },
+ "nlme": {
+ "Package": "nlme",
+ "Version": "3.1-152",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "graphics",
+ "lattice",
+ "stats",
+ "utils"
+ ],
+ "Hash": "35de1ce639f20b5e10f7f46260730c65"
+ },
+ "officer": {
+ "Package": "officer",
+ "Version": "0.6.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "grDevices",
+ "graphics",
+ "openssl",
+ "ragg",
+ "stats",
+ "utils",
+ "uuid",
+ "xml2",
+ "zip"
+ ],
+ "Hash": "d570077027cfedcf743d86838ffbd885"
+ },
+ "openssl": {
+ "Package": "openssl",
+ "Version": "2.0.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "askpass"
+ ],
+ "Hash": "0f7cd2962e3044bb940cca4f4b5cecbe"
+ },
+ "pillar": {
+ "Package": "pillar",
+ "Version": "1.9.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "cli",
+ "fansi",
+ "glue",
+ "lifecycle",
+ "rlang",
+ "utf8",
+ "utils",
+ "vctrs"
+ ],
+ "Hash": "15da5a8412f317beeee6175fbc76f4bb"
+ },
+ "pkgbuild": {
+ "Package": "pkgbuild",
+ "Version": "1.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "callr",
+ "cli",
+ "crayon",
+ "desc",
+ "prettyunits",
+ "processx",
+ "rprojroot"
+ ],
+ "Hash": "beb25b32a957a22a5c301a9e441190b3"
+ },
+ "pkgconfig": {
+ "Package": "pkgconfig",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "utils"
+ ],
+ "Hash": "01f28d4278f15c76cddbea05899c5d6f"
+ },
+ "pkgdown": {
+ "Package": "pkgdown",
+ "Version": "2.0.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "bslib",
+ "callr",
+ "cli",
+ "desc",
+ "digest",
+ "downlit",
+ "fs",
+ "httr",
+ "jsonlite",
+ "magrittr",
+ "memoise",
+ "purrr",
+ "ragg",
+ "rlang",
+ "rmarkdown",
+ "tibble",
+ "whisker",
+ "withr",
+ "xml2",
+ "yaml"
+ ],
+ "Hash": "16fa15449c930bf3a7761d3c68f8abf9"
+ },
+ "pkgload": {
+ "Package": "pkgload",
+ "Version": "1.3.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "crayon",
+ "desc",
+ "fs",
+ "glue",
+ "methods",
+ "rlang",
+ "rprojroot",
+ "utils",
+ "withr"
+ ],
+ "Hash": "a7f498a1b2a4a6816148e498509f6e1d"
+ },
+ "plotly": {
+ "Package": "plotly",
+ "Version": "4.10.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "RColorBrewer",
+ "base64enc",
+ "crosstalk",
+ "data.table",
+ "digest",
+ "dplyr",
+ "ggplot2",
+ "htmltools",
+ "htmlwidgets",
+ "httr",
+ "jsonlite",
+ "lazyeval",
+ "magrittr",
+ "promises",
+ "purrr",
+ "rlang",
+ "scales",
+ "tibble",
+ "tidyr",
+ "tools",
+ "vctrs",
+ "viridisLite"
+ ],
+ "Hash": "fbb11e44d057996ca5fe40d959cacfb0"
+ },
+ "plyr": {
+ "Package": "plyr",
+ "Version": "1.8.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "Rcpp"
+ ],
+ "Hash": "9c17c6ee41639ebdc1d7266546d3b627"
+ },
+ "praise": {
+ "Package": "praise",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a555924add98c99d2f411e37e7d25e9f"
+ },
+ "prettyunits": {
+ "Package": "prettyunits",
+ "Version": "1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "95ef9167b75dde9d2ccc3c7528393e7e"
+ },
+ "processx": {
+ "Package": "processx",
+ "Version": "3.8.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "ps",
+ "utils"
+ ],
+ "Hash": "d75b4059d781336efba24021915902b4"
+ },
+ "profvis": {
+ "Package": "profvis",
+ "Version": "0.3.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "htmlwidgets",
+ "stringr"
+ ],
+ "Hash": "e9d21e79848e02e524bea6f5bd53e7e4"
+ },
+ "progress": {
+ "Package": "progress",
+ "Version": "1.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "crayon",
+ "hms",
+ "prettyunits"
+ ],
+ "Hash": "14dc9f7a3c91ebb14ec5bb9208a07061"
+ },
+ "promises": {
+ "Package": "promises",
+ "Version": "1.2.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "Rcpp",
+ "later",
+ "magrittr",
+ "rlang",
+ "stats"
+ ],
+ "Hash": "4ab2c43adb4d4699cf3690acd378d75d"
+ },
+ "ps": {
+ "Package": "ps",
+ "Version": "1.7.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "utils"
+ ],
+ "Hash": "709d852d33178db54b17c722e5b1e594"
+ },
+ "purrr": {
+ "Package": "purrr",
+ "Version": "1.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "lifecycle",
+ "magrittr",
+ "rlang",
+ "vctrs"
+ ],
+ "Hash": "d71c815267c640f17ddbf7f16144b4bb"
+ },
+ "ragg": {
+ "Package": "ragg",
+ "Version": "1.2.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "systemfonts",
+ "textshaping"
+ ],
+ "Hash": "690bc058ea2b1b8a407d3cfe3dce3ef9"
+ },
+ "rappdirs": {
+ "Package": "rappdirs",
+ "Version": "0.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "5e3c5dc0b071b21fa128676560dbe94d"
+ },
+ "rcmdcheck": {
+ "Package": "rcmdcheck",
+ "Version": "1.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "callr",
+ "cli",
+ "curl",
+ "desc",
+ "digest",
+ "pkgbuild",
+ "prettyunits",
+ "rprojroot",
+ "sessioninfo",
+ "utils",
+ "withr",
+ "xopen"
+ ],
+ "Hash": "8f25ebe2ec38b1f2aef3b0d2ef76f6c4"
+ },
+ "readr": {
+ "Package": "readr",
+ "Version": "2.1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "cli",
+ "clipr",
+ "cpp11",
+ "crayon",
+ "hms",
+ "lifecycle",
+ "methods",
+ "rlang",
+ "tibble",
+ "tzdb",
+ "utils",
+ "vroom"
+ ],
+ "Hash": "9c59de1357dc209868b5feb5c9f0fe2f"
+ },
+ "rematch2": {
+ "Package": "rematch2",
+ "Version": "2.1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "tibble"
+ ],
+ "Hash": "76c9e04c712a05848ae7a23d2f170a40"
+ },
+ "remotes": {
+ "Package": "remotes",
+ "Version": "2.4.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods",
+ "stats",
+ "tools",
+ "utils"
+ ],
+ "Hash": "63d15047eb239f95160112bcadc4fcb9"
+ },
+ "renv": {
+ "Package": "renv",
+ "Version": "0.17.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "utils"
+ ],
+ "Hash": "4543b8cd233ae25c6aba8548be9e747e"
+ },
+ "rlang": {
+ "Package": "rlang",
+ "Version": "1.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "utils"
+ ],
+ "Hash": "dc079ccd156cde8647360f473c1fa718"
+ },
+ "rmarkdown": {
+ "Package": "rmarkdown",
+ "Version": "2.23",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "bslib",
+ "evaluate",
+ "fontawesome",
+ "htmltools",
+ "jquerylib",
+ "jsonlite",
+ "knitr",
+ "methods",
+ "stringr",
+ "tinytex",
+ "tools",
+ "utils",
+ "xfun",
+ "yaml"
+ ],
+ "Hash": "79f14e53725f28900d936f692bfdd69f"
+ },
+ "roxygen2": {
+ "Package": "roxygen2",
+ "Version": "7.2.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "brew",
+ "cli",
+ "commonmark",
+ "cpp11",
+ "desc",
+ "knitr",
+ "methods",
+ "pkgload",
+ "purrr",
+ "rlang",
+ "stringi",
+ "stringr",
+ "utils",
+ "withr",
+ "xml2"
+ ],
+ "Hash": "7b153c746193b143c14baa072bae4e27"
+ },
+ "rprojroot": {
+ "Package": "rprojroot",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "1de7ab598047a87bba48434ba35d497d"
+ },
+ "rstudioapi": {
+ "Package": "rstudioapi",
+ "Version": "0.15.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "5564500e25cffad9e22244ced1379887"
+ },
+ "rversions": {
+ "Package": "rversions",
+ "Version": "2.1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "curl",
+ "utils",
+ "xml2"
+ ],
+ "Hash": "a9881dfed103e83f9de151dc17002cd1"
+ },
+ "sass": {
+ "Package": "sass",
+ "Version": "0.4.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R6",
+ "fs",
+ "htmltools",
+ "rappdirs",
+ "rlang"
+ ],
+ "Hash": "2bb4371a4c80115518261866eab6ab11"
+ },
+ "scales": {
+ "Package": "scales",
+ "Version": "1.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "RColorBrewer",
+ "farver",
+ "labeling",
+ "lifecycle",
+ "munsell",
+ "rlang",
+ "viridisLite"
+ ],
+ "Hash": "6e8750cdd13477aa440d453da93d5cac"
+ },
+ "sessioninfo": {
+ "Package": "sessioninfo",
+ "Version": "1.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "tools",
+ "utils"
+ ],
+ "Hash": "3f9796a8d0a0e8c6eb49a4b029359d1f"
+ },
+ "shiny": {
+ "Package": "shiny",
+ "Version": "1.7.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "bslib",
+ "cachem",
+ "commonmark",
+ "crayon",
+ "ellipsis",
+ "fastmap",
+ "fontawesome",
+ "glue",
+ "grDevices",
+ "htmltools",
+ "httpuv",
+ "jsonlite",
+ "later",
+ "lifecycle",
+ "methods",
+ "mime",
+ "promises",
+ "rlang",
+ "sourcetools",
+ "tools",
+ "utils",
+ "withr",
+ "xtable"
+ ],
+ "Hash": "f7f201522eedbc95f10ef323b100ff29"
+ },
+ "shinyWidgets": {
+ "Package": "shinyWidgets",
+ "Version": "0.7.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "anytime",
+ "bslib",
+ "grDevices",
+ "htmltools",
+ "jsonlite",
+ "rlang",
+ "sass",
+ "shiny"
+ ],
+ "Hash": "fd889b32caa37b8ed9b1e9e7ef1564bc"
+ },
+ "shinycssloaders": {
+ "Package": "shinycssloaders",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "digest",
+ "glue",
+ "grDevices",
+ "shiny"
+ ],
+ "Hash": "f39bb3c44a9b496723ec7e86f9a771d8"
+ },
+ "shinyjs": {
+ "Package": "shinyjs",
+ "Version": "2.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "digest",
+ "jsonlite",
+ "shiny"
+ ],
+ "Hash": "802e4786b353a4bb27116957558548d5"
+ },
+ "sourcetools": {
+ "Package": "sourcetools",
+ "Version": "0.1.7-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "5f5a7629f956619d519205ec475fe647"
+ },
+ "stringi": {
+ "Package": "stringi",
+ "Version": "1.7.12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "stats",
+ "tools",
+ "utils"
+ ],
+ "Hash": "ca8bd84263c77310739d2cf64d84d7c9"
+ },
+ "stringr": {
+ "Package": "stringr",
+ "Version": "1.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "lifecycle",
+ "magrittr",
+ "rlang",
+ "stringi",
+ "vctrs"
+ ],
+ "Hash": "671a4d384ae9d32fc47a14e98bfa3dc8"
+ },
+ "sys": {
+ "Package": "sys",
+ "Version": "3.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "34c16f1ef796057bfa06d3f4ff818a5d"
+ },
+ "systemfonts": {
+ "Package": "systemfonts",
+ "Version": "1.0.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cpp11"
+ ],
+ "Hash": "90b28393209827327de889f49935140a"
+ },
+ "testthat": {
+ "Package": "testthat",
+ "Version": "3.1.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "R6",
+ "brio",
+ "callr",
+ "cli",
+ "desc",
+ "digest",
+ "ellipsis",
+ "evaluate",
+ "jsonlite",
+ "lifecycle",
+ "magrittr",
+ "methods",
+ "pkgload",
+ "praise",
+ "processx",
+ "ps",
+ "rlang",
+ "utils",
+ "waldo",
+ "withr"
+ ],
+ "Hash": "7eb5fd202a61d2fb78af5869b6c08998"
+ },
+ "textshaping": {
+ "Package": "textshaping",
+ "Version": "0.3.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cpp11",
+ "systemfonts"
+ ],
+ "Hash": "1ab6223d3670fac7143202cb6a2d43d5"
+ },
+ "tibble": {
+ "Package": "tibble",
+ "Version": "3.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "fansi",
+ "lifecycle",
+ "magrittr",
+ "methods",
+ "pillar",
+ "pkgconfig",
+ "rlang",
+ "utils",
+ "vctrs"
+ ],
+ "Hash": "a84e2cc86d07289b3b6f5069df7a004c"
+ },
+ "tidyr": {
+ "Package": "tidyr",
+ "Version": "1.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "cpp11",
+ "dplyr",
+ "glue",
+ "lifecycle",
+ "magrittr",
+ "purrr",
+ "rlang",
+ "stringr",
+ "tibble",
+ "tidyselect",
+ "utils",
+ "vctrs"
+ ],
+ "Hash": "e47debdc7ce599b070c8e78e8ac0cfcf"
+ },
+ "tidyselect": {
+ "Package": "tidyselect",
+ "Version": "1.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "lifecycle",
+ "rlang",
+ "vctrs",
+ "withr"
+ ],
+ "Hash": "79540e5fcd9e0435af547d885f184fd5"
+ },
+ "tinytex": {
+ "Package": "tinytex",
+ "Version": "0.45",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "xfun"
+ ],
+ "Hash": "e4e357f28c2edff493936b6cb30c3d65"
+ },
+ "triebeard": {
+ "Package": "triebeard",
+ "Version": "0.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "Rcpp"
+ ],
+ "Hash": "642507a148b0dd9b5620177e0a044413"
+ },
+ "tzdb": {
+ "Package": "tzdb",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cpp11"
+ ],
+ "Hash": "b2e1cbce7c903eaf23ec05c58e59fb5e"
+ },
+ "urlchecker": {
+ "Package": "urlchecker",
+ "Version": "1.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "curl",
+ "tools",
+ "xml2"
+ ],
+ "Hash": "409328b8e1253c8d729a7836fe7f7a16"
+ },
+ "urltools": {
+ "Package": "urltools",
+ "Version": "1.7.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "Rcpp",
+ "methods",
+ "triebeard"
+ ],
+ "Hash": "e86a704261a105f4703f653e05defa3e"
+ },
+ "usethis": {
+ "Package": "usethis",
+ "Version": "2.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "clipr",
+ "crayon",
+ "curl",
+ "desc",
+ "fs",
+ "gert",
+ "gh",
+ "glue",
+ "jsonlite",
+ "lifecycle",
+ "purrr",
+ "rappdirs",
+ "rlang",
+ "rprojroot",
+ "rstudioapi",
+ "stats",
+ "utils",
+ "whisker",
+ "withr",
+ "yaml"
+ ],
+ "Hash": "60e51f0b94d0324dc19e44110098fa9f"
+ },
+ "utf8": {
+ "Package": "utf8",
+ "Version": "1.2.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "1fe17157424bb09c48a8b3b550c753bc"
+ },
+ "uuid": {
+ "Package": "uuid",
+ "Version": "1.1-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "f1cb46c157d080b729159d407be83496"
+ },
+ "vctrs": {
+ "Package": "vctrs",
+ "Version": "0.6.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "cli",
+ "glue",
+ "lifecycle",
+ "rlang"
+ ],
+ "Hash": "06eceb3a5d716fd0654cc23ca3d71a99"
+ },
+ "viridisLite": {
+ "Package": "viridisLite",
+ "Version": "0.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R"
+ ],
+ "Hash": "55e157e2aa88161bdb0754218470d204"
+ },
+ "vroom": {
+ "Package": "vroom",
+ "Version": "1.5.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "bit64",
+ "cli",
+ "cpp11",
+ "crayon",
+ "glue",
+ "hms",
+ "lifecycle",
+ "methods",
+ "progress",
+ "rlang",
+ "stats",
+ "tibble",
+ "tidyselect",
+ "tzdb",
+ "vctrs",
+ "withr"
+ ],
+ "Hash": "976507b5a105bc3bdf6a5a5f29e0684f"
+ },
+ "waldo": {
+ "Package": "waldo",
+ "Version": "0.5.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "cli",
+ "diffobj",
+ "fansi",
+ "glue",
+ "methods",
+ "rematch2",
+ "rlang",
+ "tibble"
+ ],
+ "Hash": "2c993415154cdb94649d99ae138ff5e5"
+ },
+ "whisker": {
+ "Package": "whisker",
+ "Version": "0.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c6abfa47a46d281a7d5159d0a8891e88"
+ },
+ "withr": {
+ "Package": "withr",
+ "Version": "2.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "grDevices",
+ "graphics",
+ "stats"
+ ],
+ "Hash": "c0e49a9760983e81e55cdd9be92e7182"
+ },
+ "xfun": {
+ "Package": "xfun",
+ "Version": "0.39",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "stats",
+ "tools"
+ ],
+ "Hash": "8f56e9acb54fb525e66464d57ab58bcb"
+ },
+ "xml2": {
+ "Package": "xml2",
+ "Version": "1.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "methods"
+ ],
+ "Hash": "40682ed6a969ea5abfd351eb67833adc"
+ },
+ "xopen": {
+ "Package": "xopen",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "processx"
+ ],
+ "Hash": "6c85f015dee9cc7710ddd20f86881f58"
+ },
+ "xtable": {
+ "Package": "xtable",
+ "Version": "1.8-4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Requirements": [
+ "R",
+ "stats",
+ "utils"
+ ],
+ "Hash": "b8acdf8af494d9ec19ccb2481a9b11c2"
+ },
+ "yaml": {
+ "Package": "yaml",
+ "Version": "2.3.7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0d0056cc5383fbc240ccd0cb584bf436"
+ },
+ "zip": {
+ "Package": "zip",
+ "Version": "2.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d98c94dacb7e0efcf83b0a133a705504"
+ }
+ }
+}
+=======
{
"R": {
"Version": "4.1.1",
@@ -2205,3 +4400,4 @@
}
}
}
+>>>>>>> 0cd101109665f2699b442aa971069068a28e65d5
diff --git a/tests/testthat/test-adae_r001.R b/tests/testthat/test-adae_r001.R
index 1a0a01d..2819f93 100644
--- a/tests/testthat/test-adae_r001.R
+++ b/tests/testthat/test-adae_r001.R
@@ -33,7 +33,7 @@ lt_dat <- risk_stat(
test_that("Test Case 1: Risk table works with expected inputs", {
ae_out <- adae_r001(
datain = ae_pre,
- population = "Overall",
+ population = "Overall Population",
AE_Filter = "Any Event",
riskyn = "Y",
ctrlgrp = "Placebo",
@@ -72,7 +72,7 @@ test_that("Test Case 1: Risk table works with expected inputs", {
ae_out$title,
paste0(
"Participants With Any Adverse Events by Higher Term and Lower ",
- "Term \nOverall population"
+ "Term \nPopulation: Overall Population"
)
)
expect_equal(
@@ -87,7 +87,7 @@ test_that("Test Case 1: Risk table works with expected inputs", {
test_that("Test Case 2: No Risk table works with expected inputs", {
ae_out2 <- adae_r001(
datain = ae_pre,
- population = "Overall",
+ population = "Overall Population",
AE_Filter = NULL,
riskyn = "N",
ui_lt = "AEDECOD",
@@ -119,7 +119,7 @@ test_that("Test Case 2: No Risk table works with expected inputs", {
# Check title and footnote
expect_equal(
ae_out2$title,
- "Participants With Adverse Events by Higher Term and Lower Term \nOverall population"
+ "Participants With Adverse Events by Higher Term and Lower Term \nPopulation: Overall Population" # nolint
)
expect_equal(
ae_out2$footnote,
@@ -130,7 +130,7 @@ test_that("Test Case 2: No Risk table works with expected inputs", {
test_that("Test Case 3: Sorting performed correctly", {
ae_out3 <- adae_r001(
datain = ae_pre,
- population = "Overall",
+ population = "Overall Population",
AE_Filter = NULL,
riskyn = "N",
ui_lt = "AEDECOD",
@@ -169,7 +169,7 @@ test_that("Test Case 3: Sorting performed correctly", {
test_that("Test Case 4: Percentage Denominator variation", {
ae_out4 <- adae_r001(
datain = ae_pre,
- population = "Overall",
+ population = "Overall Population",
AE_Filter = NULL,
riskyn = "N",
ui_lt = "AEDECOD",
diff --git a/tests/testthat/test-ae_pre_processor.R b/tests/testthat/test-ae_pre_processor.R
index df4a97f..b1f71aa 100644
--- a/tests/testthat/test-ae_pre_processor.R
+++ b/tests/testthat/test-ae_pre_processor.R
@@ -1,9 +1,7 @@
# testcase 1:
-
-test_that("Test Case 1", {
- data(adae)
- data(FMQ_Consolidated_List)
-
+data(adae)
+data(FMQ_Consolidated_List)
+test_that("Test Case 1: With standard inputs", {
actual <- ae_pre_processor(
datain = adae,
aeSubset = "AOCCPFL=='Y'",
@@ -23,29 +21,9 @@ test_that("Test Case 1", {
aeTrtTot = "N",
aeSubGrpTot = "N"
)
-
- # expected
- # mentry
-
- mdsin <- mentry(
- datain = adae,
- ui_aSubset = "AOCCPFL=='Y'",
- ui_dSubset = "!is.na(ASTDT)",
- ui_byvar = "AEBODSYS",
- ui_subgrpvar = NA,
- ui_trtvar = "TRTA",
- ui_trtsort = "TRTAN",
- ui_trttotalyn = "N",
- ui_sgtotalyn = "N",
- ui_bign = "N",
- ui_addGrpMiss = "N",
- ui_pop_fil = "SAFFL"
- )
-
- df <- mdsin$dsin
date_formats <- c("%d%b%Y", "%Y-%m-%d")
- expected <- df %>%
+ expected <- adae %>%
mutate(
AESTDT = as.Date(ASTDT, tryFormats = date_formats, optional = FALSE),
AEENDT = as.Date(AENDT, tryFormats = date_formats, optional = FALSE),
@@ -54,89 +32,39 @@ test_that("Test Case 1", {
) %>%
tidyr::drop_na(RFSTDTC) %>%
mutate(
- AEDECOD = ifelse(!is.na(AESTDT) & is.na(AEDECOD), "Not yet coded", AEDECOD),
- AESTDT = ifelse(is.na(AESTDT) & !is.na(AEDECOD), RFSTDTC, AESTDT),
+ AEDECOD = if_else(!is.na(AESTDT) & is.na(AEDECOD), "Not yet coded", AEDECOD),
+ AESTDT = if_else(is.na(AESTDT) & !is.na(AEDECOD), RFSTDTC, AESTDT),
AESEV = toupper(AESEV)
)
- expect_equal(actual$dsin, expected)
-})
-
-# testcase 2:
-
-test_that("Test Case 2", {
- data(adae)
- data(FMQ_Consolidated_List)
-
- actual <- ae_pre_processor(
- datain = adae,
- aeSubset = "AOCCPFL=='Y'",
- aeDenomSubset = "!is.na(ASTDT)",
- ae_filter = "Treatment emergent",
- aeObsPeriod = "Other",
- aeObsResidual = 5,
- trtvar = "TRTA",
- trtsort = "TRTAN",
- pop_fil = "SAFFL",
- fmq_data = FMQ_Consolidated_List,
- aeEventVar = "AEDECOD",
- aeByVar = "AEBODSYS",
- aeSubGrpVar = NA,
- aeBigN = "N",
- aeGrpVarMiss = "N",
- aeTrtTot = "Y",
- aeSubGrpTot = "N"
- )
-
- # expected
- # mentry
mdsin <- mentry(
- datain = adae,
+ datain = expected,
ui_aSubset = "AOCCPFL=='Y'",
ui_dSubset = "!is.na(ASTDT)",
ui_byvar = "AEBODSYS",
ui_subgrpvar = NA,
ui_trtvar = "TRTA",
ui_trtsort = "TRTAN",
- ui_trttotalyn = "Y",
+ ui_trttotalyn = "N",
ui_sgtotalyn = "N",
ui_bign = "N",
ui_addGrpMiss = "N",
ui_pop_fil = "SAFFL"
)
-
- df <- mdsin$dsin
- date_formats <- c("%d%b%Y", "%Y-%m-%d")
-
- expected <- df %>%
- mutate(
- AESTDT = as.Date(ASTDT, tryFormats = date_formats, optional = FALSE),
- AEENDT = as.Date(AENDT, tryFormats = date_formats, optional = FALSE),
- RFSTDTC = as.Date(TRTSDT, tryFormats = date_formats, optional = FALSE),
- RFENDTC = as.Date(TRTEDT, tryFormats = date_formats, optional = FALSE)
- ) %>%
- tidyr::drop_na(RFSTDTC) %>%
- mutate(
- AEDECOD = ifelse(!is.na(AESTDT) & is.na(AEDECOD), "Not yet coded", AEDECOD),
- AESTDT = ifelse(is.na(AESTDT) & !is.na(AEDECOD), RFSTDTC, AESTDT),
- AESEV = toupper(AESEV)
- ) %>%
- filter(TRTEMFL == "Y") %>%
- filter((AESTDT > RFSTDTC) & (AESTDT < (RFENDTC + 5)))
-
- expect_equal(actual$dsin, expected)
+ expect_named(actual, c("dsin", "dout", "bigN"))
+ expect_equal(actual$dsin, mdsin$dsin)
+ expect_equal(actual$dout, mdsin$dout)
+ expect_true(is.na(actual$bigN))
})
-# test case 3:
-test_that("Test Case 3", {
- data(adae)
- data(FMQ_Consolidated_List)
+# testcase 2:
+test_that("Test Case 2: Varying inputs", {
actual <- ae_pre_processor(
datain = adae,
- aeSubset = "AOCC02FL=='Y'",
+ aeSubset = "AOCCPFL=='Y'",
aeDenomSubset = "!is.na(ASTDT)",
- ae_filter = "Recovering/Resolving",
+ ae_filter = "Treatment emergent",
aeObsPeriod = "Other",
aeObsResidual = 5,
trtvar = "TRTA",
@@ -151,134 +79,74 @@ test_that("Test Case 3", {
aeTrtTot = "Y",
aeSubGrpTot = "N"
)
-
- # expected
- # mentry
- mdsin <- mentry(
- datain = adae,
- ui_aSubset = "AOCC02FL=='Y'",
- ui_dSubset = "!is.na(ASTDT)",
- ui_byvar = "AEBODSYS",
- ui_subgrpvar = NA,
- ui_trtvar = "TRTA",
- ui_trtsort = "TRTAN",
- ui_trttotalyn = "Y",
- ui_sgtotalyn = "N",
- ui_bign = "N",
- ui_addGrpMiss = "N",
- ui_pop_fil = "SAFFL"
- )
-
- df <- mdsin$dsin
- date_formats <- c("%d%b%Y", "%Y-%m-%d")
-
- expected <- df %>%
- mutate(
- AESTDT = as.Date(ASTDT, tryFormats = date_formats, optional = FALSE),
- AEENDT = as.Date(AENDT, tryFormats = date_formats, optional = FALSE),
- RFSTDTC = as.Date(TRTSDT, tryFormats = date_formats, optional = FALSE),
- RFENDTC = as.Date(TRTEDT, tryFormats = date_formats, optional = FALSE)
- ) %>%
- tidyr::drop_na(RFSTDTC) %>%
- mutate(
- AEDECOD = ifelse(!is.na(AESTDT) & is.na(AEDECOD), "Not yet coded", AEDECOD),
- AESTDT = ifelse(is.na(AESTDT) & !is.na(AEDECOD), RFSTDTC, AESTDT),
- AESEV = toupper(AESEV)
- ) %>%
- filter((AESTDT > RFSTDTC) & (AESTDT < (RFENDTC + 5))) %>%
- filter(AEOUT == toupper("Recovering/Resolving"))
-
- expect_equal(actual$dsin, expected)
+ expect_named(actual, c("dsin", "dout", "bigN"))
+ expect_true(is.na(actual$bigN))
+ # AE filter applied:
+ expect_equal(unique(actual$dsin$TRTEMFL), "Y")
+ # Analysis Subset applied:
+ expect_equal(unique(actual$dsin$AOCCPFL), "Y")
+ # Denom Subset:
+ expect_false(any(is.na(actual$dout$ASTDT)))
+ # Observation Period:
+ expect_true(all(actual$dsin$AESTDT > actual$dsin$RFSTDTC))
+ expect_true(all(actual$dsin$AESTDT < (actual$dsin$RFENDTC + 5)))
+ # All required variables created in if():
+ expect_true(all(c("AESTDT", "AEENDT", "RFSTDTC", "RFENDTC", "AESEV") %in% names(actual$dout)))
+ # There are no non-coded terms in default adae:
+ expect_false("Not yet coded" %in% unique(actual$dsin$AEDECOD))
+ # Treatment
+ expect_is(actual$dsin$TRTVAR, "factor")
+ # Total Treatment:
+ expect_true("Total" %in% unique(actual$dsin$TRTVAR))
+ # FMQ is not given as eventvar:
+ expect_false("FMQ_NAM" %in% names(actual$dout))
})
-# test case 4:
-test_that("Test Case 4", {
- data(adae)
- data(FMQ_Consolidated_List)
-
- input <- adae %>% mutate(
- AESTDT = as.character(ASTDT),
- AEENDT = as.character(AENDT),
- RFSTDTC = as.character(TRTSDT),
- RFENDTC = as.character(TRTEDT)
- )
-
+# test case 3:
+test_that("Test Case 3: FMQ created from Consolidated List", {
actual <- ae_pre_processor(
- datain = input,
- aeSubset = "AOCC02FL=='Y'",
+ datain = adae,
+ aeSubset = "USUBJID != ''",
aeDenomSubset = "!is.na(ASTDT)",
- ae_filter = "Recovering/Resolving",
- aeObsPeriod = "Other",
- aeObsResidual = 5,
+ ae_filter = c("Mild", "Recovered/Resolved"),
+ aeObsPeriod = "Overall Duration",
trtvar = "TRTA",
trtsort = "TRTAN",
pop_fil = "SAFFL",
fmq_data = FMQ_Consolidated_List,
aeEventVar = "AEDECOD",
- aeByVar = "AEBODSYS",
+ aeByVar = "FMQ_NAM",
aeSubGrpVar = NA,
- aeBigN = "N",
+ aeBigN = "Y",
aeGrpVarMiss = "N",
- aeTrtTot = "Y",
+ aeTrtTot = "N",
aeSubGrpTot = "N"
)
-
- # expected
- # mentry
- mdsin <- mentry(
- datain = input,
- ui_aSubset = "AOCC02FL=='Y'",
- ui_dSubset = "!is.na(ASTDT)",
- ui_byvar = "AEBODSYS",
- ui_subgrpvar = NA,
- ui_trtvar = "TRTA",
- ui_trtsort = "TRTAN",
- ui_trttotalyn = "Y",
- ui_sgtotalyn = "N",
- ui_bign = "N",
- ui_addGrpMiss = "N",
- ui_pop_fil = "SAFFL"
- )
-
- df <- mdsin$dsin
- date_formats <- c("%d%b%Y", "%Y-%m-%d")
-
- expected <- df %>%
- mutate(
- AESTDT = as.Date(AESTDT, tryFormats = date_formats, optional = FALSE),
- AEENDT = as.Date(AEENDT, tryFormats = date_formats, optional = FALSE),
- RFSTDTC = as.Date(RFSTDTC, tryFormats = date_formats, optional = FALSE),
- RFENDTC = as.Date(RFENDTC, tryFormats = date_formats, optional = FALSE)
- ) %>%
- tidyr::drop_na(RFSTDTC) %>%
- mutate(
- AEDECOD = ifelse(!is.na(AESTDT) & is.na(AEDECOD), "Not yet coded", AEDECOD),
- AESTDT = ifelse(is.na(AESTDT) & !is.na(AEDECOD), RFSTDTC, AESTDT),
- AESEV = toupper(AESEV)
- ) %>%
- filter((AESTDT > RFSTDTC) & (AESTDT < (RFENDTC + 5))) %>%
- filter(AEOUT == toupper("Recovering/Resolving"))
-
- expect_equal(actual$dsin, expected)
+ expect_named(actual, c("dsin", "dout", "bigN"))
+ expect_is(actual$bigN, "data.frame")
+ # AE filter applied:
+ expect_equal(toupper(unique(actual$dsin$AESEV)), "MILD")
+ expect_equal(toupper(unique(actual$dsin$AEOUT)), "RECOVERED/RESOLVED")
+ # FMQ is given as BYVAR
+ expect_true("FMQ_NAM" %in% names(actual$dout))
+ # Using PT = "Rash" as example:
+ Fmq_rash <- FMQ_Consolidated_List %>%
+ filter(PT == "Rash") %>%
+ mutate(FMQ_NAM = paste0(FMQ, "/", FMQCAT))
+ expectedfmq <- paste(unique(Fmq_rash$FMQ_NAM), collapse = "~~")
+ actualfmq <- actual$dout %>%
+ filter(AEDECOD == "RASH") %>%
+ distinct(FMQ_NAM) %>%
+ pull()
+ expect_equal(actualfmq, expectedfmq)
})
-
-# test case 5
-test_that("Test Case 5", {
- data(adae)
- data(FMQ_Consolidated_List)
-
- input <- adae %>% mutate(
- AESTDT = as.character(ASTDT),
- AEENDT = as.character(AENDT),
- RFSTDTC = as.character(TRTSDT),
- RFENDTC = as.character(TRTEDT)
- )
-
+# test case 4
+test_that("Test Case 4: Dates Converted As Expected:", {
actual <- ae_pre_processor(
- datain = input,
- aeSubset = "AOCC02FL=='Y'",
+ datain = adae,
+ aeSubset = "USUBJID != ''",
aeDenomSubset = "!is.na(ASTDT)",
- ae_filter = "Mild",
+ ae_filter = "Serious",
aeObsPeriod = "Other",
aeObsResidual = 5,
trtvar = "TRTA",
@@ -293,42 +161,12 @@ test_that("Test Case 5", {
aeTrtTot = "Y",
aeSubGrpTot = "N"
)
-
- # expected
- # mentry
- mdsin <- mentry(
- datain = input,
- ui_aSubset = "AOCC02FL=='Y'",
- ui_dSubset = "!is.na(ASTDT)",
- ui_byvar = "AEBODSYS",
- ui_subgrpvar = NA,
- ui_trtvar = "TRTA",
- ui_trtsort = "TRTAN",
- ui_trttotalyn = "Y",
- ui_sgtotalyn = "N",
- ui_bign = "N",
- ui_addGrpMiss = "N",
- ui_pop_fil = "SAFFL"
- )
-
- df <- mdsin$dsin
- date_formats <- c("%d%b%Y", "%Y-%m-%d")
-
- expected <- df %>%
- mutate(
- AESTDT = as.Date(AESTDT, tryFormats = date_formats, optional = FALSE),
- AEENDT = as.Date(AEENDT, tryFormats = date_formats, optional = FALSE),
- RFSTDTC = as.Date(RFSTDTC, tryFormats = date_formats, optional = FALSE),
- RFENDTC = as.Date(RFENDTC, tryFormats = date_formats, optional = FALSE)
- ) %>%
- tidyr::drop_na(RFSTDTC) %>%
- mutate(
- AEDECOD = ifelse(!is.na(AESTDT) & is.na(AEDECOD), "Not yet coded", AEDECOD),
- AESTDT = ifelse(is.na(AESTDT) & !is.na(AEDECOD), RFSTDTC, AESTDT),
- AESEV = toupper(AESEV)
- ) %>%
- filter((AESTDT > RFSTDTC) & (AESTDT < (RFENDTC + 5))) %>%
- filter(AESEV == toupper("Mild"))
-
- expect_equal(actual$dsin, expected)
+ expect_named(actual, c("dsin", "dout", "bigN"))
+ # AE filter applied:
+ expect_equal(unique(actual$dsin$AESER), "Y")
+ # expected class to be 'Date'
+ expect_is(actual$dsin$AESTDT, "Date")
+ expect_is(actual$dsin$AEENDT, "Date")
+ expect_is(actual$dsin$RFSTDTC, "Date")
+ expect_is(actual$dsin$RFENDTC, "Date")
})
diff --git a/tests/testthat/test-event_analysis.R b/tests/testthat/test-event_analysis.R
index b503ca4..99b7225 100644
--- a/tests/testthat/test-event_analysis.R
+++ b/tests/testthat/test-event_analysis.R
@@ -22,8 +22,8 @@ test_that("Test Case 1: Event Analysis works with expected inputs", {
function(x) ptly_data[[x]][["legendgroup"]]
)))
- expect_equal(length(goutput), 5)
- expect_equal(names(goutput), c("ptly", "plot", "rpt_data", "title", "footnote"))
+ expect_equal(length(goutput), 6)
+ expect_equal(names(goutput), c("ptly", "plot", "rpt_data", "rpt_data1", "title", "footnote"))
expect_true(nrow(goutput$rpt_data) > 0)
expect_type(goutput$ptly, "list")
expect_equal(legendgroups, sort(unique(goutput[["rpt_data"]][["DPTVAL"]])))
@@ -33,13 +33,13 @@ test_that("Test Case 1: Event Analysis works with expected inputs", {
goutput$footnote,
paste0(
"* N is the total number of events. \nClassifications of adverse events ",
- "are based on the Medical Dictionary for Regulatory\n Activities (MedDRA",
+ "are based on the Medical Dictionary for Regulatory Activities (MedDRA",
" v21.1). \nFMQ classification is based on FDA FMQ consolidated list. ",
"\nDashed Horizontal line represents incidence percentage reference line. ",
"\nTotals for the No. of Participants/Events at a higher level are not ",
- "necessarily the sum of\n those at the lower levels since a participant ",
- "may report two or more \nPT - Preferred Term ; FMQ - FDA MedDRA Queries ",
- "\nEvent counts are the sum of individual occurrences within that category"
+ "necessarily the sum of those at the lower levels since a participant ",
+ "may report two or more. \nPT - Preferred Term ; FMQ - FDA MedDRA Queries ",
+ "\nEvent counts are the sum of individual occurrences within that category."
)
)
})
@@ -67,8 +67,8 @@ test_that("Test Case 2: Event Analysis works with expected inputs", {
function(x) ptly_data[[x]][["legendgroup"]]
)))
- expect_equal(length(goutput), 5)
- expect_equal(names(goutput), c("ptly", "plot", "rpt_data", "title", "footnote"))
+ expect_equal(length(goutput), 6)
+ expect_equal(names(goutput), c("ptly", "plot", "rpt_data", "rpt_data1", "title", "footnote"))
expect_true(nrow(goutput$rpt_data) > 0)
expect_type(goutput$ptly, "list")
expect_equal(legendgroups, sort(unique(goutput[["rpt_data"]][["DPTVAL"]])))
@@ -78,13 +78,13 @@ test_that("Test Case 2: Event Analysis works with expected inputs", {
goutput$footnote,
paste0(
"* N is the total number of events. \nClassifications of adverse events ",
- "are based on the Medical Dictionary for Regulatory\n Activities (MedDRA",
+ "are based on the Medical Dictionary for Regulatory Activities (MedDRA",
" v21.1). \nFMQ classification is based on FDA FMQ consolidated list. ",
"\nDashed Horizontal line represents incidence percentage reference line. ",
"\nTotals for the No. of Participants/Events at a higher level are not ",
- "necessarily the sum of\n those at the lower levels since a participant ",
- "may report two or more \nPT - Preferred Term ; FMQ - FDA MedDRA Queries ",
- "\nEvent counts are the sum of individual occurrences within that category"
+ "necessarily the sum of those at the lower levels since a participant ",
+ "may report two or more. \nPT - Preferred Term ; FMQ - FDA MedDRA Queries ",
+ "\nEvent counts are the sum of individual occurrences within that category."
)
)
})
diff --git a/tests/testthat/test-event_interval.R b/tests/testthat/test-event_interval.R
new file mode 100644
index 0000000..03e2c62
--- /dev/null
+++ b/tests/testthat/test-event_interval.R
@@ -0,0 +1,95 @@
+data(adae)
+
+test_that("interval plot works with expected inputs", {
+ out <- interval_plot(
+ datain = adae,
+ startvar = "ASTDY",
+ endvar = "AENDY",
+ yvar = "AETERM",
+ seriesvar = "AESEV",
+ subjectid = "01-701-1302",
+ series_color = NA,
+ yaxislab = "Reported Term for the Adverse Event"
+ )
+
+ complete_stat <- out$rpt_data %>%
+ filter(Status == "Complete")
+
+ expect_true(nrow(out$rpt_data) > 0)
+ expect_equal(unique(out$rpt_data$USUBJID), "01-701-1302")
+ expect_true(all(!is.na(complete_stat$ASTDY)))
+ expect_true(all(!is.na(complete_stat$AENDY)))
+})
+
+test_that("interval plot works with expected inputs and different subject", {
+ out <- interval_plot(
+ datain = adae,
+ startvar = "ASTDY",
+ endvar = "AENDY",
+ yvar = "AETERM",
+ seriesvar = "AESEV",
+ subjectid = "01-701-1275",
+ series_color = NA,
+ yaxislab = "Reported Term for the Adverse Event"
+ )
+
+ complete_stat <- out$rpt_data %>%
+ filter(Status == "Complete")
+
+ expect_true(nrow(out$rpt_data) > 0)
+ expect_equal(unique(out$rpt_data$USUBJID), "01-701-1275")
+ expect_true(all(!is.na(complete_stat$ASTDY)))
+ expect_true(all(!is.na(complete_stat$AENDY)))
+})
+
+test_that("interval plot works with non default inputs", {
+ out <- interval_plot(
+ datain = adae,
+ startvar = "ASTDY",
+ endvar = "AENDY",
+ yvar = "AEDECOD",
+ seriesvar = "AESEV",
+ subjectid = "01-703-1335",
+ series_color = NA,
+ yaxislab = "Reported Term for the Adverse Event"
+ )
+
+ complete_stat <- out$rpt_data %>%
+ filter(Status == "Complete")
+
+ expect_true(nrow(out$rpt_data) > 0)
+ expect_equal(unique(out$rpt_data$USUBJID), "01-703-1335")
+ expect_true("AEDECOD" %in% names(out$rpt_data))
+ expect_true(all(!is.na(complete_stat$ASTDY)))
+ expect_true(all(!is.na(complete_stat$AENDY)))
+})
+
+test_that("interval plot returns empty plot when subject not present", {
+ out <- interval_plot(
+ datain = adae,
+ startvar = "ASTDY",
+ endvar = "AENDY",
+ yvar = "AETERM",
+ seriesvar = "AESEV",
+ subjectid = "01-701-13021",
+ series_color = NA,
+ yaxislab = "Reported Term for the Adverse Event"
+ )
+
+ expect_equal(nrow(out$rpt_data), 0)
+})
+
+test_that("interval plot works when seriesvar is NA or not present", {
+ out <- interval_plot(
+ datain = adae,
+ startvar = "ASTDY",
+ endvar = "AENDY",
+ yvar = "AETERM",
+ seriesvar = "AESEV1",
+ subjectid = "01-701-1302",
+ series_color = NA,
+ yaxislab = "Reported Term for the Adverse Event"
+ )
+
+ expect_equal(unique(out$rpt_data$TOTAL), "All")
+})
diff --git a/tests/testthat/test-forest_plot.R b/tests/testthat/test-forest_plot.R
index e1be2c8..71dbbb3 100644
--- a/tests/testthat/test-forest_plot.R
+++ b/tests/testthat/test-forest_plot.R
@@ -62,9 +62,9 @@ test_that("Forest Plot Works with standard inputs", {
paste0(
"* N is the total number of participants. \nClassifications of adverse ",
"events are based on the Medical Dictionary for Regulatory Activities (MedDRA v21.1",
- "). \nDashed Vertical line represents risk value reference line \nTotals for the ",
+ "). \nDashed Vertical line represents risk value reference line. \nTotals for the ",
"No. of Participants/Events at a higher level are not necessarily the sum of those ",
- "at the lower levels since a participant may report two or more \nThe number of ",
+ "at the lower levels since a participant may report two or more. \nThe number of ",
"participants reporting at least 1 occurrence of the event specified."
)
)
@@ -111,10 +111,28 @@ test_that("Forest plot arguments reflect correctly", {
paste0(
"* N is the total number of events. \nClassifications of adverse events are ",
"based on the Medical Dictionary for Regulatory Activities (MedDRA v21.1). ",
- "\nDashed Vertical line represents risk value reference line \nTotals for ",
+ "\nDashed Vertical line represents risk value reference line. \nTotals for ",
"the No. of Participants/Events at a higher level are not necessarily the ",
- "sum of those at the lower levels since a participant may report two or more",
- " \nEvent counts are the sum of individual occurrences within that category"
+ "sum of those at the lower levels since a participant may report two or more.",
+ " \nEvent counts are the sum of individual occurrences within that category."
)
)
})
+## Test with empty data
+test_that("Forest Plot works as expected with empty `risk_stat()` output", {
+ risk_stat_null <- tibble()
+ fp_null <- forest_plot(
+ datain = risk_stat_null,
+ AE_Filter = "Any",
+ review_by = c("AEBODSYS", "AEDECOD"),
+ summary_by = "Patients",
+ statistics = "Risk Ratio",
+ xref = 1,
+ pvalcut = 0.05,
+ trtbign = "Y",
+ scale_trans = "identity"
+ )
+ expect_equal(length(fp_null), 3)
+ expect_equal(names(fp_null), c("ptly", "plot", "rpt_data"))
+ expect_identical(risk_stat_null, fp_null$rpt_data)
+})
diff --git a/tests/testthat/test-multi_interval.R b/tests/testthat/test-multi_interval.R
new file mode 100644
index 0000000..65912b6
--- /dev/null
+++ b/tests/testthat/test-multi_interval.R
@@ -0,0 +1,40 @@
+data(adae)
+data(cm)
+
+test_that("multi_interval works with expected inputs", {
+ out <- multi_interval(
+ datain = list(AE = adae, CM = cm),
+ subjectid = "01-701-1302"
+ )
+
+ expect_true(nrow(out$rpt_data) > 0)
+ expect_equal(unique(out$rpt_data$USUBJID), "01-701-1302")
+ expect_equal(out$title, "Events over Study Period for Participant: 01-701-1302\n; Age: 61; Sex: M; Race: WHITE") # nolint
+ expect_true(all(c("CMSTDY", "CMENDY", "CMTRT", "CMCLAS") %in% names(out$rpt_data)))
+ expect_true(out[["ptly"]][["x"]][["subplot"]])
+})
+
+test_that("multi_interval works with expected inputs for subject with no CM data", {
+ out <- multi_interval(
+ datain = list(AE = adae, CM = cm),
+ subjectid = "01-703-1299"
+ )
+
+ expect_true(nrow(out$rpt_data) > 0)
+ expect_equal(unique(out$rpt_data$USUBJID), "01-703-1299")
+ expect_equal(out$title, "Events over Study Period for Participant: 01-703-1299\n; Age: 81; Sex: F; Race: WHITE") # nolint
+ expect_equal(out[["ptly"]][["x"]][["data"]][[4]][["text"]], "No data for this participant/period")
+ expect_true(out[["ptly"]][["x"]][["subplot"]])
+ expect_true(all(is.na(out$rpt_data$CMDECOD)))
+})
+
+test_that("multi_interval returns empty plot for subject if AE data set is not present", {
+ out <- multi_interval(
+ datain = list(CM = cm),
+ subjectid = "01-701-1302"
+ )
+
+ expect_null(nrow(out$rpt_data))
+ expect_null(out[["ptly"]][["x"]][["subplot"]])
+ expect_equal(out[["ptly"]][["x"]][["data"]][[1]][["text"]], "No AE data available")
+})
diff --git a/tests/testthat/test-volcano_plot.R b/tests/testthat/test-volcano_plot.R
index 7c1360d..c133a04 100644
--- a/tests/testthat/test-volcano_plot.R
+++ b/tests/testthat/test-volcano_plot.R
@@ -44,7 +44,7 @@ test_that("Test Case 1: volcano_plot works with expected inputs", {
expect_equal(legendgroups, sort(unique(vout[["rpt_data"]][["BYVAR1"]])))
expect_identical(vout$plot$data, vout$rpt_data)
expect_equal(vout$title, "Volcano plot for Risk Difference of Safety Adverse Events")
- expect_equal(vout$footnote, "* N is the total number of participants. \nClassifications of adverse events are based on the Medical Dictionary for Regulatory Activities (MedDRA v21.1). \nDashed horizontal line represents p-value of 0.05 \nDotted horizontal line represents FDR adjusted p-value of approximately 0.05 (when applicable) \nDashed Vertical line represents risk value reference line \nTotals for the No. of Participants/Events at a higher level are not necessarily the sum of those at the lower levels since a participant may report two or more \nThe number of participants reporting at least 1 occurrence of the event specified.") # nolint
+ expect_equal(vout$footnote, "* N is the total number of participants. \nClassifications of adverse events are based on the Medical Dictionary for Regulatory Activities (MedDRA v21.1). \nDashed horizontal line represents p-value of 0.05.\nDotted horizontal line represents FDR adjusted p-value of approximately 0.05 (when applicable). \nDashed Vertical line represents risk value reference line. \nTotals for the No. of Participants/Events at a higher level are not necessarily the sum of those at the lower levels since a participant may report two or more. \nThe number of participants reporting at least 1 occurrence of the event specified.") # nolint
})
@@ -66,8 +66,8 @@ test_that("Test Case 2: volcano_plot returns pre processed AE data with
pvalcut = 0.05
)
- expect_equal(length(vout), 2)
- expect_equal(names(vout), c("plot", "rpt_data"))
+ expect_equal(length(vout), 3)
+ expect_equal(names(vout), c("ptly", "plot", "rpt_data"))
expect_identical(ae_pre, vout$rpt_data)
expect_identical(ae_pre$dsin, vout$rpt_data$dsin)
})
diff --git a/vignettes/CVARS.Rmd b/vignettes/CVARS.Rmd
index 717e992..98c5529 100644
--- a/vignettes/CVARS.Rmd
+++ b/vignettes/CVARS.Rmd
@@ -1,6 +1,11 @@
---
-title: "Clinical Visual Analytics for Review and Submission(CVARS)"
+title: "Clinical Visual Analytics for Review and Submission (CVARS)"
date: "`r Sys.Date()`"
+<<<<<<< HEAD
+output:
+ rmarkdown::html_vignette:
+ toc: true
+=======
author:
- Clinical Tables & Figures
- CVARS
@@ -15,8 +20,9 @@ html_document:
includes:
in_header: "header.html"
+>>>>>>> 0cd101109665f2699b442aa971069068a28e65d5
vignette: >
- %\VignetteIndexEntry{Clinical Visual Analytics for Review and Submission(CVARS)}
+ %\VignetteIndexEntry{Clinical Visual Analytics for Review and Submission (CVARS)}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
@@ -25,12 +31,6 @@ vignette: >
knitr::opts_chunk$set(echo = TRUE)
```
-# **Table of Contents**
-
-| |
-|-----|
-| |
-
## **1. Overview**
CVARS application helps to explore data visually and makes it easier to identify interesting data patterns.
@@ -42,7 +42,7 @@ By uploading data locally or can use default CDISC data, user can explore releva
knitr::include_graphics("cvars1look.png")
```
-This is the look and feel of the CVARS application initially when one loads the app. Now that the app is ready to use, the user needs to feed in the data for which the report and graphs are visualized. There are 5 tabs in the main window: `Report Inputs` to give inputs for reports, `Files & Lot` to show the list of available datasets for the selected study, `Data Check` to view the reported values for the selected variable, `Graph Output` to display any graph generated, and `Table Output` to display any table generated.
+This is the look and feel of the CVARS application initially when one loads the app. Now that the app is ready to use, the user needs to feed in the data for which the report and graphs are visualized. There are 4 tabs in the main window: `Report Inputs` to give inputs for reports, `Data Check` to view the reported values for the selected variable, `Graph Output` to display any graph generated, and `Table Output` to display any table generated.
| |
|-----|
@@ -51,7 +51,7 @@ This is the look and feel of the CVARS application initially when one loads the
### 1.1 Data Import
-Data can be uploaded from *Local* location. The file can only be of ".csv", ".sas7bdat", ".xpt" and ".Rda" format and must follow the naming convention of "adXX" where "XX" is the domain code. For example, "adae.sas7bdat" and "adae.xpt" are valid whereas "adae_s1.sas7bdat" or "adae2.sas7bdat" are not valid. In the *Data Source* panel, you can see the following options: Default, and Local.
+Data can be uploaded from *Local* location. The file can only be of ".csv", ".sas7bdat", ".xpt" and ".Rda" format and must follow the naming convention of "adXX" where "XX" is the domain code. For example, "adae.sas7bdat" and "adae.xpt" are valid whereas "adae_s1.sas7bdat" or "adae2.sas7bdat" are not valid. In the *Data Source* panel, you can see the following options: Default and Local.
| |
|-----|
@@ -103,20 +103,8 @@ Data import, Report Selection and Treatment variable Selection
This section presents detailed the steps for creating Volcano Plot using CVARS application which is a graph report. The required input `ADaM` data for this is an `ADAE` dataset.
-
-
-Upon loading the CVARS application, please select the `Data Source`and load the `ADAE` data.
-
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("adaeenter.png")
-```
-
Upon loading/selecting `ADAE` data and clicking the Report Inputs tab, report inputs can be added.
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("adae_report_input.png")
-```
-
- Report Type as `Figure` and Report Name as `Volcano Plot` for the graph
```{r, echo=FALSE, out.width="100%", fig.align='center'}
@@ -133,17 +121,17 @@ knitr::include_graphics("volcano_plot_new_1.png")
- To subset entire data based on population flags, select `Population Filter`. eg. Overall, Safety (SAFFL).
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_02.PNG")
+```{r, echo=FALSE, out.width="70%", fig.align='center'}
+knitr::include_graphics("adaebox_treatment.png")
```
-
+
**Processing Data:**
- Add or Edit the default `Analysis Subset Condition` and `Denominator Subset Condition` to filter input data (for calculating categorical counts alone or for entire data respectively)
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_03.PNG")
+knitr::include_graphics("event_analysis_03.png")
```
- Select `Adverse Event Filter(s)` - To filter input data
@@ -166,7 +154,7 @@ knitr::include_graphics("event_analysis_03.PNG")
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("volcano_plot_02.PNG")
+knitr::include_graphics("volcano_plot_02.png")
```
**Graph Output:**
@@ -175,7 +163,7 @@ knitr::include_graphics("volcano_plot_02.PNG")
```{r, echo=FALSE, out.width="70%", fig.align='center'}
-knitr::include_graphics("volcano_plot_03.PNG")
+knitr::include_graphics("volcano_plot_03.png")
```
@@ -209,8 +197,8 @@ knitr::include_graphics("forestplot_new_1.png")
- Select appropriate `Treatment Sort Variable` which will give the order for sorting Treatment variable
- To subset entire data based on available population flags, select `Population Filter`. eg. Overall, Safety (SAFFL) etc
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("adae_treatment.png")
+```{r, echo=FALSE, out.width="70%", fig.align='center'}
+knitr::include_graphics("adaebox_treatment.png")
```
**Data Pre-processing/Preparation**
@@ -294,25 +282,13 @@ knitr::include_graphics("forest_output.png")
This document details the steps for creating Event Analysis Plot using A&R application which is a graph report. The required input ADaM data for this is an ADAE dataset.
-#### 2.2.1 Report Inputs in App
-
-Upon loading the CVARS application, please select the `Data Source` and load the data.
-
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("cvars1look.png")
-```
-
-
-Upon loading/selecting `ADAE` data and clicking Report Inputs tab, report inputs can be added.
-
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("adae_report_input.png")
-```
+#### 2.2.1 Report Inputs in App
+Upon loading/selecting `ADAE` data
- Report Type as `Figure` and Report Name as `Event Analysis` for the graph
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_new_1.png")
+knitr::include_graphics("event_analysis_reportname.png")
```
@@ -330,10 +306,10 @@ knitr::include_graphics("event_analysis_new_1.png")
- To subset entire data based on population flags, select `Population Filter`. eg. Overall, Safety (SAFFL).
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_02.PNG")
+```{r, echo=FALSE, out.width="70%", fig.align='center'}
+knitr::include_graphics("adaebox_treatment.png")
```
-
+
| |
|-----|
| |
@@ -343,7 +319,7 @@ knitr::include_graphics("event_analysis_02.PNG")
- Add or Edit the default `Analysis Subset Condition` and `Denominator Subset Condition` to filter input data (for calculating categorical counts alone or for entire data respectively)
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_03.PNG")
+knitr::include_graphics("event_analysis_03.png")
```
- Select `Adverse Event Filter(s)` - To filter input data
@@ -357,7 +333,7 @@ knitr::include_graphics("event_analysis_03.PNG")
- Select `Reference Line (%)` - Reference lines show how the data in a chart compares to a reference value. This is free text column where you can enter any number as reference value.
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_04.PNG")
+knitr::include_graphics("event_analysis_04.png")
```
| |
@@ -515,7 +491,28 @@ After selecting a format and Table/Figure, click the 'Save' button and you will
|-----|
| |
-## **4. Usage Notes and Common Errors**
+## **4. Listings and Patient Profile (For Adverse Events figures only)**
+
+The 3 Adverse Events Figure reports - Forest Plot, Volcano Plot and Event Analysis - have an added feature of being able to view the listing and relevant patient information from the main plot.
+Clicking on a point or bar of interest in any of the 3 plots will result in creation of a listing of all participants in the data with the selected Event Classification and Treatment group with relevant info such as Outcomes, Severity, Event Start and End Dates etc. This is displayed as a table below the plot.
+
+```{r, echo=FALSE, out.width="60%", fig.align='center'}
+knitr::include_graphics("listing_1.png")
+```
+
+Further, clicking on any one of the rows in the listing results in creation of a figure (interval plot) for each participant which illustrates the start, end date and interval during which the selected patient experienced any adverse events.
+Additionally, if `CM` or `ADCM` data is loaded in the app, the above-mentioned graph overlays another figure displaying similar intervals for when the participant was on concomitant medications. This figure is displayed below the listing.
+
+```{r, echo=FALSE, out.width="60%", fig.align='center'}
+knitr::include_graphics("profile_1.png")
+```
+
+
+| |
+|-----|
+| |
+
+## **5. Usage Notes and Common Errors**
- When subset conditions, population or adverse event filters are selected, check that there is any data within those filters. If not, reports may fail or display a message that there is no data.
@@ -527,9 +524,9 @@ After selecting a format and Table/Figure, click the 'Save' button and you will
|-----|
| |
-## **5. App Development Details**
+## **6. App Development Details**
-R version 4.1.0 Packages: cowplot : 1.1.1; data.table : 1.14.2; DT : 0.26; epitools : 0.5-10.1; flextable : 0.8.2; ftExtra : 0.4.0; ggstance : 0.3.5; haven : 2.5.1; htmltools : 0.5.3; officer : 0.4.4; plotly : 4.10.0; RCurl : 1.98-1.8; readxl : 1.4.1; scales : 1.2.1; shiny : 1.7.2; shinycssloaders : 1.0.0; shinydashboard : 0.7.2; shinyjs : 2.1.0; shinyWidgets : 0.7.4; tidyverse : 1.3.2; tools : 4.1.0
+R version 4.1.0 Packages: cowplot : 1.1.1; data.table : 1.14.2; DT : 0.26; epitools : 0.5-10.1; flextable : 0.8.2; ftExtra : 0.4.0; ggstance : 0.3.5; haven : 2.5.1; htmltools : 0.5.3; officer : 0.4.4; plotly : 4.10.0; RCurl : 1.98-1.8; readxl : 1.4.1; scales : 1.2.1; shiny : 1.7.2; shinycssloaders : 1.0.0; bs4dash : 2.3.0; shinyjs : 2.1.0; shinyWidgets : 0.7.4; tidyverse : 1.3.2; tools : 4.1.0
| |
|-----|
diff --git a/vignettes/adae_r001_new_1.png b/vignettes/adae_r001_new_1.png
index cfa7a40..2023324 100644
Binary files a/vignettes/adae_r001_new_1.png and b/vignettes/adae_r001_new_1.png differ
diff --git a/vignettes/adae_report_input.png b/vignettes/adae_report_input.png
index 6f5956a..7782d85 100644
Binary files a/vignettes/adae_report_input.png and b/vignettes/adae_report_input.png differ
diff --git a/vignettes/adae_riskstat.png b/vignettes/adae_riskstat.png
index 889d869..6868162 100644
Binary files a/vignettes/adae_riskstat.png and b/vignettes/adae_riskstat.png differ
diff --git a/vignettes/adae_treatment.png b/vignettes/adae_treatment.png
index bb11d92..f638b6b 100644
Binary files a/vignettes/adae_treatment.png and b/vignettes/adae_treatment.png differ
diff --git a/vignettes/adaebox_treatment.png b/vignettes/adaebox_treatment.png
index 3b8fe30..1635c49 100644
Binary files a/vignettes/adaebox_treatment.png and b/vignettes/adaebox_treatment.png differ
diff --git a/vignettes/adaeenter.png b/vignettes/adaeenter.png
deleted file mode 100644
index b9f3bc8..0000000
Binary files a/vignettes/adaeenter.png and /dev/null differ
diff --git a/vignettes/adaenorisk_output.png b/vignettes/adaenorisk_output.png
index cfd26af..af98df1 100644
Binary files a/vignettes/adaenorisk_output.png and b/vignettes/adaenorisk_output.png differ
diff --git a/vignettes/adaer001_ment.png b/vignettes/adaer001_ment.png
index 126aeaa..1de2828 100644
Binary files a/vignettes/adaer001_ment.png and b/vignettes/adaer001_ment.png differ
diff --git a/vignettes/adaer001_reportname.png b/vignettes/adaer001_reportname.png
index 1ebf978..9e1b8f2 100644
Binary files a/vignettes/adaer001_reportname.png and b/vignettes/adaer001_reportname.png differ
diff --git a/vignettes/adaer001_sort.png b/vignettes/adaer001_sort.png
index 2ca81f4..f830e8a 100644
Binary files a/vignettes/adaer001_sort.png and b/vignettes/adaer001_sort.png differ
diff --git a/vignettes/adaereadpic.png b/vignettes/adaereadpic.png
index c6c4642..6678276 100644
Binary files a/vignettes/adaereadpic.png and b/vignettes/adaereadpic.png differ
diff --git a/vignettes/adaerisk_output.png b/vignettes/adaerisk_output.png
index fbf327e..5795bb9 100644
Binary files a/vignettes/adaerisk_output.png and b/vignettes/adaerisk_output.png differ
diff --git a/vignettes/adaerisk_trt.png b/vignettes/adaerisk_trt.png
index 32f20e3..65914cf 100644
Binary files a/vignettes/adaerisk_trt.png and b/vignettes/adaerisk_trt.png differ
diff --git a/vignettes/ae_filterperiod.png b/vignettes/ae_filterperiod.png
index 7a0e936..ca0c861 100644
Binary files a/vignettes/ae_filterperiod.png and b/vignettes/ae_filterperiod.png differ
diff --git a/vignettes/ae_summaryterm.png b/vignettes/ae_summaryterm.png
index 554f073..820ac0d 100644
Binary files a/vignettes/ae_summaryterm.png and b/vignettes/ae_summaryterm.png differ
diff --git a/vignettes/cvars1look.png b/vignettes/cvars1look.png
index 159177a..5141af5 100644
Binary files a/vignettes/cvars1look.png and b/vignettes/cvars1look.png differ
diff --git a/vignettes/event_analysis.Rmd b/vignettes/event_analysis.Rmd
index f5a24ba..6160e8c 100644
--- a/vignettes/event_analysis.Rmd
+++ b/vignettes/event_analysis.Rmd
@@ -22,23 +22,11 @@ This document details the steps for creating Event Analysis Plot using CVARS app
### 1.1 Report Inputs in App
-Upon loading the CVARS application, please select the `Data Source` and load the data.
-
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("cvars1look.png")
-```
-
-
-Upon loading/selecting `ADAE` data and clicking Report Inputs tab, report inputs can be added.
-
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("adae_report_input.png")
-```
-
+Upon loading/selecting `ADAE` data
- Report Type as `Figure` and Report Name as `Event Analysis` for the graph
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_new_1.png")
+knitr::include_graphics("event_analysis_reportname.png")
```
@@ -56,8 +44,8 @@ knitr::include_graphics("event_analysis_new_1.png")
- To subset entire data based on population flags, select `Population Filter`. eg. Overall, Safety (SAFFL).
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_02.PNG")
+```{r, echo=FALSE, out.width="70%", fig.align='center'}
+knitr::include_graphics("adaebox_treatment.png")
```
| |
@@ -69,7 +57,7 @@ knitr::include_graphics("event_analysis_02.PNG")
- Add or Edit the default `Analysis Subset Condition` and `Denominator Subset Condition` to filter input data (for calculating categorical counts alone or for entire data respectively)
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_03.PNG")
+knitr::include_graphics("event_analysis_03.png")
```
- Select `Adverse Event Filter(s)` - To filter input data
@@ -83,7 +71,7 @@ knitr::include_graphics("event_analysis_03.PNG")
- Select `Reference Line (%)` - Reference lines show how the data in a chart compares to a reference value. This is free text column where you can enter any number as reference value.
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_04.PNG")
+knitr::include_graphics("event_analysis_04.png")
```
| |
diff --git a/vignettes/event_analysis_02.PNG b/vignettes/event_analysis_02.PNG
deleted file mode 100644
index fdfa8d8..0000000
Binary files a/vignettes/event_analysis_02.PNG and /dev/null differ
diff --git a/vignettes/event_analysis_03.PNG b/vignettes/event_analysis_03.PNG
index cbdb9a7..d1b8274 100644
Binary files a/vignettes/event_analysis_03.PNG and b/vignettes/event_analysis_03.PNG differ
diff --git a/vignettes/event_analysis_04.PNG b/vignettes/event_analysis_04.PNG
index 003c783..24b0b42 100644
Binary files a/vignettes/event_analysis_04.PNG and b/vignettes/event_analysis_04.PNG differ
diff --git a/vignettes/event_analysis_new_1.png b/vignettes/event_analysis_new_1.png
deleted file mode 100644
index a9dca06..0000000
Binary files a/vignettes/event_analysis_new_1.png and /dev/null differ
diff --git a/vignettes/event_analysis_new_2.png b/vignettes/event_analysis_new_2.png
index 86b7b0c..fa3a4bc 100644
Binary files a/vignettes/event_analysis_new_2.png and b/vignettes/event_analysis_new_2.png differ
diff --git a/vignettes/event_analysis_new_3.png b/vignettes/event_analysis_new_3.png
index d1efa7e..095c53b 100644
Binary files a/vignettes/event_analysis_new_3.png and b/vignettes/event_analysis_new_3.png differ
diff --git a/vignettes/event_analysis_reportname.png b/vignettes/event_analysis_reportname.png
new file mode 100644
index 0000000..a4177a6
Binary files /dev/null and b/vignettes/event_analysis_reportname.png differ
diff --git a/vignettes/forest_graphdisp.png b/vignettes/forest_graphdisp.png
index bf63409..095b313 100644
Binary files a/vignettes/forest_graphdisp.png and b/vignettes/forest_graphdisp.png differ
diff --git a/vignettes/forest_output.png b/vignettes/forest_output.png
index 93164ed..ca068cb 100644
Binary files a/vignettes/forest_output.png and b/vignettes/forest_output.png differ
diff --git a/vignettes/forest_plot.Rmd b/vignettes/forest_plot.Rmd
index 634f903..8373322 100644
--- a/vignettes/forest_plot.Rmd
+++ b/vignettes/forest_plot.Rmd
@@ -35,8 +35,8 @@ knitr::include_graphics("forestplot_new_1.png")
- Select appropriate `Treatment Sort Variable` which will give the order for sorting Treatment variable
- To subset entire data based on available population flags, select `Population Filter`. eg. Overall, Safety (SAFFL) etc
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("adae_treatment.png")
+```{r, echo=FALSE, out.width="70%", fig.align='center'}
+knitr::include_graphics("adaebox_treatment.png")
```
**Data Pre-processing/Preparation**
diff --git a/vignettes/forest_riskstat.png b/vignettes/forest_riskstat.png
index 25d5487..d6c5228 100644
Binary files a/vignettes/forest_riskstat.png and b/vignettes/forest_riskstat.png differ
diff --git a/vignettes/forest_trtgroup.png b/vignettes/forest_trtgroup.png
index 5967686..2a4b819 100644
Binary files a/vignettes/forest_trtgroup.png and b/vignettes/forest_trtgroup.png differ
diff --git a/vignettes/forestplot_new_1.png b/vignettes/forestplot_new_1.png
index d5ebc46..242cfc7 100644
Binary files a/vignettes/forestplot_new_1.png and b/vignettes/forestplot_new_1.png differ
diff --git a/vignettes/listing_1.png b/vignettes/listing_1.png
new file mode 100644
index 0000000..c54d32e
Binary files /dev/null and b/vignettes/listing_1.png differ
diff --git a/vignettes/profile_1.png b/vignettes/profile_1.png
new file mode 100644
index 0000000..af80285
Binary files /dev/null and b/vignettes/profile_1.png differ
diff --git a/vignettes/volcano_1.PNG b/vignettes/volcano_1.PNG
deleted file mode 100644
index f1500e7..0000000
Binary files a/vignettes/volcano_1.PNG and /dev/null differ
diff --git a/vignettes/volcano_2.PNG b/vignettes/volcano_2.PNG
deleted file mode 100644
index 1f3854d..0000000
Binary files a/vignettes/volcano_2.PNG and /dev/null differ
diff --git a/vignettes/volcano_3.PNG b/vignettes/volcano_3.PNG
deleted file mode 100644
index 65ebda2..0000000
Binary files a/vignettes/volcano_3.PNG and /dev/null differ
diff --git a/vignettes/volcano_4.PNG b/vignettes/volcano_4.PNG
deleted file mode 100644
index 64368e8..0000000
Binary files a/vignettes/volcano_4.PNG and /dev/null differ
diff --git a/vignettes/volcano_5.PNG b/vignettes/volcano_5.PNG
deleted file mode 100644
index 43b8b46..0000000
Binary files a/vignettes/volcano_5.PNG and /dev/null differ
diff --git a/vignettes/volcano_plot.Rmd b/vignettes/volcano_plot.Rmd
index df9c6b1..3e2895c 100644
--- a/vignettes/volcano_plot.Rmd
+++ b/vignettes/volcano_plot.Rmd
@@ -22,18 +22,8 @@ This document details the steps for creating Volcano Plot using CVARS applicatio
### 1.1 Report Inputs in App
-Upon loading the CVARS application, please select the `Data Source`and load the `ADAE` data.
-
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("adaeenter.png")
-```
-
Upon loading/selecting `ADAE` data and clicking the Report Inputs tab, report inputs can be added.
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("adae_report_input.png")
-```
-
- Report Type as `Figure` and Report Name as `Volcano Plot` for the graph
```{r, echo=FALSE, out.width="100%", fig.align='center'}
@@ -50,8 +40,8 @@ knitr::include_graphics("volcano_plot_new_1.png")
- To subset entire data based on population flags, select `Population Filter`. eg. Overall, Safety (SAFFL).
-```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_02.PNG")
+```{r, echo=FALSE, out.width="70%", fig.align='center'}
+knitr::include_graphics("adaebox_treatment.png")
```
@@ -60,7 +50,7 @@ knitr::include_graphics("event_analysis_02.PNG")
- Add or Edit the default `Analysis Subset Condition` and `Denominator Subset Condition` to filter input data (for calculating categorical counts alone or for entire data respectively)
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("event_analysis_03.PNG")
+knitr::include_graphics("event_analysis_03.png")
```
- Select `Adverse Event Filter(s)` - To filter input data
@@ -83,7 +73,7 @@ knitr::include_graphics("event_analysis_03.PNG")
```{r, echo=FALSE, out.width="100%", fig.align='center'}
-knitr::include_graphics("volcano_plot_02.PNG")
+knitr::include_graphics("volcano_plot_02.png")
```
**Graph Output:**
@@ -92,5 +82,5 @@ knitr::include_graphics("volcano_plot_02.PNG")
```{r, echo=FALSE, out.width="70%", fig.align='center'}
-knitr::include_graphics("volcano_plot_03.PNG")
+knitr::include_graphics("volcano_plot_03.png")
```
diff --git a/vignettes/volcano_plot_01.PNG b/vignettes/volcano_plot_01.PNG
index 5fc6c90..6e71987 100644
Binary files a/vignettes/volcano_plot_01.PNG and b/vignettes/volcano_plot_01.PNG differ
diff --git a/vignettes/volcano_plot_02.PNG b/vignettes/volcano_plot_02.PNG
index 39c7b8e..3637765 100644
Binary files a/vignettes/volcano_plot_02.PNG and b/vignettes/volcano_plot_02.PNG differ
diff --git a/vignettes/volcano_plot_03.PNG b/vignettes/volcano_plot_03.PNG
index 96cc5dd..77d005e 100644
Binary files a/vignettes/volcano_plot_03.PNG and b/vignettes/volcano_plot_03.PNG differ
diff --git a/vignettes/volcano_plot_new_1.png b/vignettes/volcano_plot_new_1.png
index fd8e089..1806f74 100644
Binary files a/vignettes/volcano_plot_new_1.png and b/vignettes/volcano_plot_new_1.png differ