Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement/run app via package installation #123

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ export(anonymize_pk_data)
export(apply_filters)
export(as_factor_preserve_label)
export(calculate_summary_stats)
export(check_slope_rule_overlap)
export(compress_range)
export(create_conc)
export(create_dose)
export(filter_breaks)
export(filter_slopes)
export(flexible_violinboxplot)
export(format_data)
export(general_lineplot)
Expand Down Expand Up @@ -71,6 +74,7 @@ importFrom(logger,log_info)
importFrom(logger,log_trace)
importFrom(logger,log_warn)
importFrom(plotly,event_data)
importFrom(plotly,ggplotly)
importFrom(plotly,plotlyOutput)
importFrom(plotly,plotly_build)
importFrom(plotly,renderPlotly)
Expand Down
40 changes: 35 additions & 5 deletions R/run_app.R
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#' Run the Shiny app
#'
#' List of functions imported for the shiny application.
#' When adding new imports, please keep the alphabetical order, at lest for packages.
#' @param ... Arguments passed to `shiny::runApp()`
#'
#' List of packages imported for the shiny application.
#' When adding new imports, please keep the alphabetical order, at lest for packages.
#' @import shiny
#' @importFrom dplyr mutate filter select group_by summarise pull arrange ungroup
#' @importFrom dplyr rename_with across case_when left_join rename
#' @importFrom DT DTOutput renderDataTable datatable formatStyle styleEqual
#' @importFrom ggplot2 ggplot geom_errorbar geom_point geom_line labs aes facet_wrap
#' @importFrom htmlwidgets JS
#' @importFrom PKNCA PKNCAconc PKNCAdose PKNCAdata pk.nca PKNCA.options pknca_units_table
#' @importFrom plotly plotlyOutput renderPlotly plotly_build event_data
#' @importFrom plotly plotlyOutput renderPlotly plotly_build event_data ggplotly
#' @importFrom reactable reactable reactableOutput renderReactable colDef reactableTheme
#' @importFrom reactable getReactableState
#' @importFrom reactable.extras text_extra dropdown_extra
Expand All @@ -23,7 +24,36 @@
#' @importFrom tools file_ext
#' @importFrom utils read.csv write.csv
#' @importFrom zip zipr
#'
#' @export
run_app <- function() {
shiny::runApp(system.file("shiny", package = "aNCA"))
run_app <- function(...) {
# Load all packages mentioned in the NAMESPACE
require("aNCA")
require("dplyr")
require("DT")
require("forcats")
require("ggplot2")
require("grid")
require("haven")
require("htmlwidgets")
require("logger")
require("nestcolor")
require("PKNCA")
require("plotly")
require("reactable.extras")
require("reactable")
require("rio")
require("rmarkdown")
require("shiny")
require("shinyBS")
require("shinyFiles")
require("shinyjqui")
require("shinyWidgets")
require("stats")
require("tern")
require("tidyr")
require("tools")
require("utils")
require("zip")
shiny::runApp(system.file("shiny", package = "aNCA"), ...)
}
13 changes: 8 additions & 5 deletions R/utils-slope_selector.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
#' columns modified in accordance to the provided slope filters.
#' @importFrom dplyr filter group_by mutate
#'
.filter_slopes <- function(data, slopes, profiles) {
#' @export
filter_slopes <- function(data, slopes, profiles) {
if (is.null(data) || is.null(data$conc) || is.null(data$conc$data))
stop("Please provide valid data.")

Expand All @@ -39,7 +40,7 @@
# Go over all rules and check if there is no overlap - if there is, edit accordingly
slopes <- purrr::reduce(
split(slopes, seq_len(nrow(slopes))),
.f = ~ .check_slope_rule_overlap(.x, .y, .keep = TRUE)
.f = ~ check_slope_rule_overlap(.x, .y, .keep = TRUE)
)
}

Expand Down Expand Up @@ -84,7 +85,9 @@
#' that the user wants to remove rule if new range already exists in the dataset.
#' If TRUE, in that case full range will be kept.
#' @returns Data frame with full ruleset, adjusted for new rules.
.check_slope_rule_overlap <- function(existing, new, .keep = FALSE) {
#'
#' @export
check_slope_rule_overlap <- function(existing, new, .keep = FALSE) {
# check if any rule already exists for specific patient and profile #
existing_index <- which(
existing$TYPE == new$TYPE &
Expand All @@ -106,11 +109,11 @@

if (is_diff || .keep) {
existing$IXrange[existing_index] <- unique(c(existing_range, new_range)) %>%
.compress_range()
compress_range()

} else if (is_inter) {
existing$IXrange[existing_index] <- setdiff(existing_range, new_range) %>%
.compress_range()
compress_range()
}

dplyr::filter(existing, !is.na(IXrange))
Expand Down
7 changes: 4 additions & 3 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@
#' @examples
#' \dontrun{
#' # Basic usage
#' .compress_range(c(1, 2, 3, 4)) # "1:4"
#' .compress_range(c(15, 1, 11, 4, 5, 10, 2, 12, 3)) # "1:5,10:12,15"
#' compress_range(c(1, 2, 3, 4)) # "1:4"
#' compress_range(c(15, 1, 11, 4, 5, 10, 2, 12, 3)) # "1:5,10:12,15"
#' }
#'
.compress_range <- function(range_vector) {
#' @export
compress_range <- function(range_vector) {
if (!is(range_vector, "numeric")) range_vector <- suppressWarnings(as.numeric(range_vector))
if (any(is.na(range_vector))) stop("Error: only numeric values allowed")
if (length(range_vector) == 0) return(NA_integer_)
Expand Down
File renamed without changes.
10 changes: 5 additions & 5 deletions inst/shiny/modules/slope_selector.R
Original file line number Diff line number Diff line change
Expand Up @@ -348,12 +348,12 @@ slope_selector_server <- function(

# Observe input$nca
observeEvent(profiles_per_patient(), {
mydata(.filter_slopes(mydata(), manual_slopes(), profiles_per_patient()))
mydata(filter_slopes(mydata(), manual_slopes(), profiles_per_patient()))
})

#' saves and implements provided ruleset
observeEvent(input$save_ruleset, {
mydata(.filter_slopes(mydata(), manual_slopes(), profiles_per_patient()))
mydata(filter_slopes(mydata(), manual_slopes(), profiles_per_patient()))
rv$trigger <- rv$trigger + 1
})

Expand All @@ -362,7 +362,7 @@ slope_selector_server <- function(
#' and exclusions before applying them to the actual dataset.
plot_data <- reactive({
req(mydata(), manual_slopes(), profiles_per_patient())
.filter_slopes(mydata(), manual_slopes(), profiles_per_patient())
filter_slopes(mydata(), manual_slopes(), profiles_per_patient())
}) %>%
shiny::debounce(750)

Expand Down Expand Up @@ -402,7 +402,7 @@ slope_selector_server <- function(
)

# Check if there is any overlap with existing rules, adda new or edit accordingly
new_manual_slopes <- .check_slope_rule_overlap(manual_slopes(), new_slope_rule)
new_manual_slopes <- check_slope_rule_overlap(manual_slopes(), new_slope_rule)

manual_slopes(new_manual_slopes)

Expand All @@ -429,7 +429,7 @@ slope_selector_server <- function(
select(TYPE, USUBJID, DOSNO, IX, REASON) %>%
mutate(PATIENT = as.character(USUBJID), PROFILE = as.character(DOSNO)) %>%
group_by(TYPE, PATIENT, PROFILE, REASON) %>%
summarise(IXrange = .compress_range(IX), .groups = "keep") %>%
summarise(IXrange = compress_range(IX), .groups = "keep") %>%
select(TYPE, PATIENT, PROFILE, IXrange, REASON) %>%
na.omit()

Expand Down
2 changes: 1 addition & 1 deletion inst/shiny/modules/tab_tlg.R
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ tab_tlg_server <- function(id, data) {

# Make available the CSV file with the TLG list and available links to NEST
tlg_order <- reactiveVal(
read.csv(system.file("www/data/TLG_order_details.csv", package = "aNCA")) %>%
read.csv(system.file("data/TLG_order_details.csv", package = "aNCA")) %>%
mutate(PKid = paste0("<a href='", Catalog_Link, "' target='_blank'>", PKid, "</a>"))
)

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions man/dot-compress_range.Rd → man/compress_range.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions man/dot-filter_slopes.Rd → man/filter_slopes.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 8 additions & 3 deletions man/run_app.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 15 additions & 15 deletions tests/testthat/test-utils-slope_selector.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ PROFILES_FIXTURE <- list(
"4" = list(1)
)

describe(".filter_slopes", {
describe("filter_slopes", {
it("should handle slope selection", {
selection <- data.frame(
TYPE = rep("Selection", 2),
Expand All @@ -31,7 +31,7 @@ describe(".filter_slopes", {
REASON = "Test selection"
)

res <- .filter_slopes(DATA_FIXTURE, selection, PROFILES_FIXTURE)
res <- filter_slopes(DATA_FIXTURE, selection, PROFILES_FIXTURE)
expect_true(all(res$is.included.hl[c(1:3, 6:8)]))
expect_true(all(res$REASON[c(1:3, 6:8)] == "Test selection"))
})
Expand All @@ -45,19 +45,19 @@ describe(".filter_slopes", {
REASON = "Test exclusion"
)

res <- .filter_slopes(DATA_FIXTURE, exclusion, PROFILES_FIXTURE)
res <- filter_slopes(DATA_FIXTURE, exclusion, PROFILES_FIXTURE)
expect_true(all(res$is.excluded.hl[c(5, 6, 14, 15)]))
expect_true(all(res$REASON[c(5, 6, 14, 15)] == "Test exclusion"))
})

it("should throw an error for invalid data", {
expect_error(.filter_slopes(NULL, NULL, PROFILES_FIXTURE), "Please provide valid data.")
expect_error(.filter_slopes(list(), NULL, PROFILES_FIXTURE), "Please provide valid data.")
expect_error(filter_slopes(NULL, NULL, PROFILES_FIXTURE), "Please provide valid data.")
expect_error(filter_slopes(list(), NULL, PROFILES_FIXTURE), "Please provide valid data.")
expect_error(
.filter_slopes(list(conc = list()), NULL, PROFILES_FIXTURE), "Please provide valid data."
filter_slopes(list(conc = list()), NULL, PROFILES_FIXTURE), "Please provide valid data."
)
expect_error(
.filter_slopes(list(conc = list()), NULL, PROFILES_FIXTURE), "Please provide valid data."
filter_slopes(list(conc = list()), NULL, PROFILES_FIXTURE), "Please provide valid data."
)
})
})
Expand All @@ -69,7 +69,7 @@ EXISTING_FIXTURE <- data.frame(
IXrange = "3:6"
)

describe(".check_slope_rule_overlap", {
describe("check_slope_rule_overlap", {
it("should add new row if no overlap is detected", {
# different type #
NEW <- data.frame(
Expand All @@ -78,7 +78,7 @@ describe(".check_slope_rule_overlap", {
PROFILE = 1,
IXrange = "1:3"
)
expect_equal(nrow(.check_slope_rule_overlap(EXISTING_FIXTURE, NEW)), 2)
expect_equal(nrow(check_slope_rule_overlap(EXISTING_FIXTURE, NEW)), 2)

# different patient #
NEW <- data.frame(
Expand All @@ -87,7 +87,7 @@ describe(".check_slope_rule_overlap", {
PROFILE = 1,
IXrange = "1:3"
)
expect_equal(nrow(.check_slope_rule_overlap(EXISTING_FIXTURE, NEW)), 2)
expect_equal(nrow(check_slope_rule_overlap(EXISTING_FIXTURE, NEW)), 2)

# different profile #
NEW <- data.frame(
Expand All @@ -96,7 +96,7 @@ describe(".check_slope_rule_overlap", {
PROFILE = 2,
IXrange = "1:3"
)
expect_equal(nrow(.check_slope_rule_overlap(EXISTING_FIXTURE, NEW)), 2)
expect_equal(nrow(check_slope_rule_overlap(EXISTING_FIXTURE, NEW)), 2)
})

it("should remove overlapping points if no new points are detected", {
Expand All @@ -106,15 +106,15 @@ describe(".check_slope_rule_overlap", {
PROFILE = 1,
IXrange = "4:5"
)
expect_equal(.check_slope_rule_overlap(EXISTING_FIXTURE, NEW)$IXrange, "3,6")
expect_equal(check_slope_rule_overlap(EXISTING_FIXTURE, NEW)$IXrange, "3,6")

NEW <- data.frame(
TYPE = "Exclusion",
PATIENT = 1,
PROFILE = 1,
IXrange = "3:4"
)
expect_equal(.check_slope_rule_overlap(EXISTING_FIXTURE, NEW)$IXrange, "5:6")
expect_equal(check_slope_rule_overlap(EXISTING_FIXTURE, NEW)$IXrange, "5:6")
})

it("should add new points of partial overlap is detected", {
Expand All @@ -124,7 +124,7 @@ describe(".check_slope_rule_overlap", {
PROFILE = 1,
IXrange = "4:9"
)
expect_equal(.check_slope_rule_overlap(EXISTING_FIXTURE, NEW)$IXrange, "3:9")
expect_equal(check_slope_rule_overlap(EXISTING_FIXTURE, NEW)$IXrange, "3:9")
})

it("should remove full row if full range of rule is removed", {
Expand All @@ -134,6 +134,6 @@ describe(".check_slope_rule_overlap", {
PROFILE = 1,
IXrange = "3:6"
)
expect_equal(nrow(.check_slope_rule_overlap(EXISTING_FIXTURE, NEW)), 0)
expect_equal(nrow(check_slope_rule_overlap(EXISTING_FIXTURE, NEW)), 0)
})
})
Loading
Loading