From 25756817263a4b576f5951721ad0a6abde9a644d Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Mon, 15 Dec 2025 13:12:50 +0100 Subject: [PATCH 01/25] feat: settings upload v1 not working because settings file wrong --- inst/shiny/app.R | 3 +- inst/shiny/modules/tab_data.R | 7 +-- inst/shiny/modules/tab_data/data_upload.R | 55 ++++++++++++++++++++--- inst/shiny/modules/tab_nca.R | 4 +- inst/shiny/modules/tab_nca/setup.R | 2 +- 5 files changed, 57 insertions(+), 14 deletions(-) diff --git a/inst/shiny/app.R b/inst/shiny/app.R index 2ef02386a..1c26d4bc4 100644 --- a/inst/shiny/app.R +++ b/inst/shiny/app.R @@ -152,7 +152,8 @@ server <- function(input, output, session) { tab_nca_outputs <- tab_nca_server( "nca", tab_data_outputs$pknca_data, - tab_data_outputs$extra_group_vars + tab_data_outputs$extra_group_vars, + tab_data_outputs$settings_override ) # TLG diff --git a/inst/shiny/modules/tab_data.R b/inst/shiny/modules/tab_data.R index 008558c68..f054ad787 100644 --- a/inst/shiny/modules/tab_data.R +++ b/inst/shiny/modules/tab_data.R @@ -120,12 +120,12 @@ tab_data_server <- function(id) { updateTabsetPanel(session, "data_navset", selected = step_labels[idx - 1]) }) #' Load raw ADNCA data - adnca_raw <- data_upload_server("raw_data") + uploaded_data <- data_upload_server("raw_data") # Call the column mapping module column_mapping <- data_mapping_server( id = "column_mapping", - adnca_data = adnca_raw, + adnca_data = uploaded_data$adnca_raw, trigger = trigger_mapping_submit ) #' Reactive value for the processed dataset @@ -223,7 +223,8 @@ tab_data_server <- function(id) { list( pknca_data = pknca_data, - extra_group_vars = extra_group_vars + extra_group_vars = extra_group_vars, + settings_override = uploaded_data$settings_override ) }) } diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index 7a9ceda07..75d10c0b8 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -41,7 +41,8 @@ data_upload_server <- function(id) { #' Display file loading error if any issues arise file_loading_error <- reactiveVal(NULL) - + settings_override <- reactiveVal(NULL) # Store loaded settings + output$file_loading_message <- renderUI({ if (is.null(file_loading_error())) { p("") @@ -71,22 +72,59 @@ data_upload_server <- function(id) { filenames <- input$data_upload$name } - # Iterate over files: Read and classify + # Iterate over files: Try reading as Data, then as Settings read_results <- purrr::map2(paths, filenames, function(path, name) { tryCatch({ # Attempt to read data <- read_pk(path) list(status = "success", data = data, name = name, type = "data") - }, error = function(e) { + }, error = function(e_pk) { # If read_pk fails - # TODO: @Jana, check if settings file is loaded and then create settings override (719) - list(status = "error", message = e$message, name = name) + # check if settings file is loaded and then create settings override + tryCatch({ + obj <- readRDS(path) + + # Check for settings + is_settings <- is.list(obj) && "settings" %in% names(obj) + + final_settings <- if (is_settings) obj else NULL + + if (!is.null(final_settings)) { + list(status = "success", type = "settings", content = final_settings, name = name) + } else { + # Not a settings file either, return original PK error + stop(e_pk$message) + } + }, error = function(e_rds) { + # Return the original read_pk error to the user + list(status = "error", msg = e_pk$message, name = name) + }) }) }) # Process results successful_loads <- purrr::keep(read_results, ~ .x$status == "success") errors <- purrr::keep(read_results, ~ .x$status == "error") + + # Extract and apply settings if any found + found_settings <- purrr::keep(successful_loads, ~ .x$type == "settings") + + if (length(found_settings) > 1) { + # Error: Too many settings files + msg <- "Error: Multiple settings files detected. Please upload only one settings file." + prev_msgs <- if (length(errors) > 0) paste(purrr::map_chr(errors, ~ paste0(.x$name, ": ", .x$msg)), collapse = "
") else "" + file_loading_error(paste(c(prev_msgs, msg), collapse = "
")) + + # Do not apply any settings if ambiguous + settings_override(NULL) + + } else if (length(found_settings) == 1) { + # Success: Single settings file + latest <- found_settings[[1]] + settings_override(latest$content) + log_success("Settings successfully loaded from ", latest$name) + showNotification(paste("Settings successfully loaded."), type = "message") + } # Handle Errors if (length(successful_loads) == 0) { @@ -105,7 +143,7 @@ data_upload_server <- function(id) { if (length(errors) > 0) { error_msgs <- purrr::map_chr(errors, ~ paste0(.x$name, ": ", .x$msg)) file_loading_error(paste(error_msgs, collapse = "
")) - log_warning("Some files failed to load: ", paste(error_msgs, collapse = "; ")) + log_warn("Some files failed to load: ", paste(error_msgs, collapse = "; ")) } else { log_success("All user data loaded successfully.") } @@ -141,6 +179,9 @@ data_upload_server <- function(id) { style = list(fontSize = "0.75em") ) - raw_data + list( + adnca_raw = raw_data, + settings_override = settings_override + ) }) } diff --git a/inst/shiny/modules/tab_nca.R b/inst/shiny/modules/tab_nca.R index cbd861e8a..fcd5feb1c 100644 --- a/inst/shiny/modules/tab_nca.R +++ b/inst/shiny/modules/tab_nca.R @@ -62,7 +62,7 @@ tab_nca_ui <- function(id) { ) } -tab_nca_server <- function(id, pknca_data, extra_group_vars) { +tab_nca_server <- function(id, pknca_data, extra_group_vars, settings_override) { moduleServer(id, function(input, output, session) { ns <- session$ns @@ -74,7 +74,7 @@ tab_nca_server <- function(id, pknca_data, extra_group_vars) { adnca_data <- reactive(pknca_data()$conc$data) # #' NCA Setup module - nca_setup <- setup_server("nca_setup", adnca_data, pknca_data) + nca_setup <- setup_server("nca_setup", adnca_data, pknca_data, settings_override) processed_pknca_data <- nca_setup$processed_pknca_data settings <- nca_setup$settings diff --git a/inst/shiny/modules/tab_nca/setup.R b/inst/shiny/modules/tab_nca/setup.R index ecaa904a9..482b41355 100644 --- a/inst/shiny/modules/tab_nca/setup.R +++ b/inst/shiny/modules/tab_nca/setup.R @@ -52,7 +52,7 @@ setup_ui <- function(id) { ) } -setup_server <- function(id, data, adnca_data) { +setup_server <- function(id, data, adnca_data, settings_override) { moduleServer(id, function(input, output, session) { imported_settings <- reactive({ From a4e82f17269d08f2bbc36bdee12245b4c9c65386 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Wed, 24 Dec 2025 14:10:52 +0100 Subject: [PATCH 02/25] feat: settings override --- inst/shiny/modules/tab_nca/setup.R | 29 ++++++++++++------- .../tab_nca/setup/parameter_selection.R | 2 +- inst/shiny/modules/tab_nca/setup/settings.R | 4 +-- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/inst/shiny/modules/tab_nca/setup.R b/inst/shiny/modules/tab_nca/setup.R index 994b9a4da..112046876 100644 --- a/inst/shiny/modules/tab_nca/setup.R +++ b/inst/shiny/modules/tab_nca/setup.R @@ -56,20 +56,27 @@ setup_server <- function(id, data, adnca_data, settings_override) { moduleServer(id, function(input, output, session) { imported_settings <- reactive({ - req(input$settings_upload) - readRDS(input$settings_upload$datapath) + req(settings_override()) + settings_override()$settings + }) + + imported_slopes <- reactive({ + req(settings_override()) + settings_override()$slope_rules + }) + + imported_params <- reactive({ + req(imported_settings()) + imported_settings()$parameter_selections }) - settings_override <- reactive(imported_settings()$settings) - manual_slopes_override <- reactive(imported_settings()$slope_rules) - parameters_override <- reactive(imported_settings()$settings$parameter_selections) # Gather all settings from the appropriate module settings <- settings_server( "nca_settings", data, adnca_data, - settings_override + imported_settings ) # Create processed data object with applied settings. @@ -99,7 +106,7 @@ setup_server <- function(id, data, adnca_data, settings_override) { parameters_output <- parameter_selection_server( "nca_setup_parameter", base_pknca_data, - parameters_override + imported_params ) final_settings <- reactive({ @@ -145,9 +152,9 @@ setup_server <- function(id, data, adnca_data, settings_override) { session$userData$ratio_table <- reactive(ratio_table()) # Automatically update the units table when settings are uploaded. - observeEvent(settings_override(), { - req(settings_override()$units) - session$userData$units_table(settings_override()$units) + observeEvent(imported_settings(), { + req(imported_settings()$units) + session$userData$units_table(imported_settings()$units) }) # Parameter unit changes option: Opens a modal message with a units table to edit @@ -183,7 +190,7 @@ setup_server <- function(id, data, adnca_data, settings_override) { slope_rules <- slope_selector_server( "slope_selector", slopes_pknca_data, - manual_slopes_override + imported_slopes ) # Handle downloading and uploading settings diff --git a/inst/shiny/modules/tab_nca/setup/parameter_selection.R b/inst/shiny/modules/tab_nca/setup/parameter_selection.R index d34f7b3f5..57dd231d7 100644 --- a/inst/shiny/modules/tab_nca/setup/parameter_selection.R +++ b/inst/shiny/modules/tab_nca/setup/parameter_selection.R @@ -259,7 +259,7 @@ parameter_selection_server <- function(id, processed_pknca_data, parameter_overr study_type_names <- unique(study_types_df()$type) if (length(study_type_names) == 0) return(list()) - +browser() # Convert from wide to long, filter for selected rows, # and then split the result into a list by study_type. df %>% diff --git a/inst/shiny/modules/tab_nca/setup/settings.R b/inst/shiny/modules/tab_nca/setup/settings.R index 360f66e58..ae24f7184 100644 --- a/inst/shiny/modules/tab_nca/setup/settings.R +++ b/inst/shiny/modules/tab_nca/setup/settings.R @@ -136,9 +136,9 @@ settings_server <- function(id, data, adnca_data, settings_override) { conc_data <- reactive(adnca_data()$conc$data) # File Upload Handling - observeEvent(settings_override(), { + observeEvent(c(settings_override(), data()), { settings <- settings_override() - +browser() log_debug_list("User settings override:", settings) not_compatible <- c() From 1d44c0f0b7d05d313fc240c3343337504ab426a7 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Wed, 24 Dec 2025 14:17:29 +0100 Subject: [PATCH 03/25] temp: param selection settings working --- inst/shiny/modules/tab_nca/setup/parameter_selection.R | 1 - inst/shiny/modules/tab_nca/setup/settings.R | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/inst/shiny/modules/tab_nca/setup/parameter_selection.R b/inst/shiny/modules/tab_nca/setup/parameter_selection.R index 57dd231d7..97ba4e706 100644 --- a/inst/shiny/modules/tab_nca/setup/parameter_selection.R +++ b/inst/shiny/modules/tab_nca/setup/parameter_selection.R @@ -259,7 +259,6 @@ parameter_selection_server <- function(id, processed_pknca_data, parameter_overr study_type_names <- unique(study_types_df()$type) if (length(study_type_names) == 0) return(list()) -browser() # Convert from wide to long, filter for selected rows, # and then split the result into a list by study_type. df %>% diff --git a/inst/shiny/modules/tab_nca/setup/settings.R b/inst/shiny/modules/tab_nca/setup/settings.R index ae24f7184..4d17c25dd 100644 --- a/inst/shiny/modules/tab_nca/setup/settings.R +++ b/inst/shiny/modules/tab_nca/setup/settings.R @@ -138,7 +138,7 @@ settings_server <- function(id, data, adnca_data, settings_override) { # File Upload Handling observeEvent(c(settings_override(), data()), { settings <- settings_override() -browser() + log_debug_list("User settings override:", settings) not_compatible <- c() From dadce3e0fb35aea3101dd40f6837f7a53db9fce9 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Mon, 29 Dec 2025 12:47:48 +0100 Subject: [PATCH 04/25] fix: settings upload works in data tab --- inst/shiny/modules/tab_nca/setup/settings.R | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/inst/shiny/modules/tab_nca/setup/settings.R b/inst/shiny/modules/tab_nca/setup/settings.R index 4d17c25dd..a0393fcbb 100644 --- a/inst/shiny/modules/tab_nca/setup/settings.R +++ b/inst/shiny/modules/tab_nca/setup/settings.R @@ -136,7 +136,9 @@ settings_server <- function(id, data, adnca_data, settings_override) { conc_data <- reactive(adnca_data()$conc$data) # File Upload Handling - observeEvent(c(settings_override(), data()), { + observeEvent(c(data(), settings_override()), priority = 0, { + req(data()) + settings <- settings_override() log_debug_list("User settings override:", settings) @@ -230,7 +232,7 @@ settings_server <- function(id, data, adnca_data, settings_override) { # Choose data to be analyzed - observeEvent(data(), priority = -1, { + observeEvent(data(), priority = 1, { req(data()) choices <- unique(data()$PARAM) %>% From bda831dff7be479251a5901fc0d1752a197304de Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Wed, 31 Dec 2025 14:36:40 +0100 Subject: [PATCH 05/25] lint --- inst/shiny/modules/tab_data/data_upload.R | 20 +++++++++++--------- inst/shiny/modules/tab_nca/setup.R | 4 ++-- inst/shiny/modules/tab_nca/setup/settings.R | 2 +- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index efb11a6ec..958b5e461 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -42,7 +42,7 @@ data_upload_server <- function(id) { #' Display file loading error if any issues arise file_loading_error <- reactiveVal(NULL) settings_override <- reactiveVal(NULL) # Store loaded settings - + output$file_loading_message <- renderUI({ if (is.null(file_loading_error())) { p("") @@ -85,9 +85,9 @@ data_upload_server <- function(id) { obj <- readRDS(path) # Check for settings is_settings <- is.list(obj) && "settings" %in% names(obj) - + final_settings <- if (is_settings) obj else NULL - + if (!is.null(final_settings)) { list(status = "success", type = "settings", content = final_settings, name = name) } else { @@ -105,21 +105,23 @@ data_upload_server <- function(id) { successful_loads <- purrr::keep(read_results, ~ .x$status == "success") errors <- purrr::keep(read_results, \(x) x$status == "error") %>% purrr::map(\(x) paste0(x$name, ": ", x$message)) - + # Extract and apply settings if any found found_settings <- purrr::keep(successful_loads, ~ .x$type == "settings") - + if (length(found_settings) > 1) { # Error: Too many settings files msg <- "Error: Multiple settings files detected. Please upload only one settings file." - prev_msgs <- if (length(errors) > 0){ + prev_msgs <- if (length(errors) > 0) { paste(purrr::map_chr(errors, ~ paste0(.x$name, ": ", .x$msg)), collapse = "
") - } else "" + } else { + "" + } file_loading_error(paste(c(prev_msgs, msg), collapse = "
")) - + # Do not apply any settings if ambiguous settings_override(NULL) - + } else if (length(found_settings) == 1) { # Success: Single settings file latest <- found_settings[[1]] diff --git a/inst/shiny/modules/tab_nca/setup.R b/inst/shiny/modules/tab_nca/setup.R index 112046876..b248e40cc 100644 --- a/inst/shiny/modules/tab_nca/setup.R +++ b/inst/shiny/modules/tab_nca/setup.R @@ -59,12 +59,12 @@ setup_server <- function(id, data, adnca_data, settings_override) { req(settings_override()) settings_override()$settings }) - + imported_slopes <- reactive({ req(settings_override()) settings_override()$slope_rules }) - + imported_params <- reactive({ req(imported_settings()) imported_settings()$parameter_selections diff --git a/inst/shiny/modules/tab_nca/setup/settings.R b/inst/shiny/modules/tab_nca/setup/settings.R index a0393fcbb..9ee18ff38 100644 --- a/inst/shiny/modules/tab_nca/setup/settings.R +++ b/inst/shiny/modules/tab_nca/setup/settings.R @@ -138,7 +138,7 @@ settings_server <- function(id, data, adnca_data, settings_override) { # File Upload Handling observeEvent(c(data(), settings_override()), priority = 0, { req(data()) - + settings <- settings_override() log_debug_list("User settings override:", settings) From 87795928abd1646dd02b13722051855abd167c1e Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Tue, 6 Jan 2026 17:05:10 +0100 Subject: [PATCH 06/25] fix: update slope selector settings --- .../modules/tab_nca/setup/slope_selector.R | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/inst/shiny/modules/tab_nca/setup/slope_selector.R b/inst/shiny/modules/tab_nca/setup/slope_selector.R index 540b7ab6e..621e301f9 100644 --- a/inst/shiny/modules/tab_nca/setup/slope_selector.R +++ b/inst/shiny/modules/tab_nca/setup/slope_selector.R @@ -340,25 +340,19 @@ slope_selector_server <- function( # nolint }) #' If any settings are uploaded by the user, overwrite current rules - observeEvent(manual_slopes_override(), { - req(manual_slopes_override()) + observeEvent(list(manual_slopes_override(), plot_data()), { + req(manual_slopes_override(), plot_data()) if (nrow(manual_slopes_override()) == 0) return(NULL) log_debug_list("Manual slopes override:", manual_slopes_override()) - override_valid <- apply(manual_slopes_override(), 1, function(r) { - dplyr::filter( - plot_data()$conc$data, - PCSPEC == r["PCSPEC"], - USUBJID == r["USUBJID"], - PARAM == r["PARAM"], - ATPTREF == r["ATPTREF"], - DOSNOA == r["DOSNOA"] - ) %>% - NROW() != 0 - }) %>% - all() + allowed_keys <- c("PCSPEC", "USUBJID", "PARAM", "ATPTREF", "DOSNOA") + use_keys <- intersect(allowed_keys, names(manual_slopes_override())) + + override_valid <- manual_slopes_override() %>% + dplyr::semi_join(plot_data()$conc$data, by = use_keys) %>% + nrow() == nrow(manual_slopes_override()) if (!override_valid) { msg <- "Manual slopes not compatible with current data, leaving as default." From e6ef26c6f265a9eee06bee77323e1a089abd351c Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Tue, 6 Jan 2026 17:28:45 +0100 Subject: [PATCH 07/25] fix: settings within if null statement --- inst/shiny/modules/tab_nca/setup.R | 3 - inst/shiny/modules/tab_nca/setup/settings.R | 99 +++++++++++---------- 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/inst/shiny/modules/tab_nca/setup.R b/inst/shiny/modules/tab_nca/setup.R index b248e40cc..4c2b9fde8 100644 --- a/inst/shiny/modules/tab_nca/setup.R +++ b/inst/shiny/modules/tab_nca/setup.R @@ -56,17 +56,14 @@ setup_server <- function(id, data, adnca_data, settings_override) { moduleServer(id, function(input, output, session) { imported_settings <- reactive({ - req(settings_override()) settings_override()$settings }) imported_slopes <- reactive({ - req(settings_override()) settings_override()$slope_rules }) imported_params <- reactive({ - req(imported_settings()) imported_settings()$parameter_selections }) diff --git a/inst/shiny/modules/tab_nca/setup/settings.R b/inst/shiny/modules/tab_nca/setup/settings.R index 73ed7a6f4..fc35d312c 100644 --- a/inst/shiny/modules/tab_nca/setup/settings.R +++ b/inst/shiny/modules/tab_nca/setup/settings.R @@ -163,6 +163,55 @@ settings_server <- function(id, data, adnca_data, settings_override) { if (!all(settings$pcspec %in% data()$PCSPEC)) { not_compatible <- c(not_compatible, "Dose Specimen") } + + # Additional settings (PCSPEC and ATPTREF handled later) + updateSelectInput(session, inputId = "method", selected = settings$method) + + if (!is.null(settings$bioavailability)) + updateSelectInput(session, inputId = "bioavailability", selected = settings$bioavailability) + + # Data imputation # + update_switch("should_impute_c0", value = settings$data_imputation$impute_c0) + + # Partial AUCs # + auc_data(settings$partial_aucs) + refresh_reactable(refresh_reactable() + 1) + + # Flags # + .update_rule_input( + session, + "R2ADJ", + settings$flags$R2ADJ$is.checked, + settings$flags$R2ADJ$threshold + ) + + .update_rule_input( + session, + "R2", + settings$flags$R2$is.checked, + settings$flags$R2$threshold + ) + + .update_rule_input( + session, + "AUCPEO", + settings$flags$AUCPEO$is.checked, + settings$flags$AUCPEO$threshold + ) + + .update_rule_input( + session, + "AUCPEP", + settings$flags$AUCPEP$is.checked, + settings$flags$AUCPEP$threshold + ) + + .update_rule_input( + session, + "LAMZSPN", + settings$flags$LAMZSPN$is.checked, + settings$flags$LAMZSPN$threshold + ) } if (length(not_compatible) > 0) { @@ -173,60 +222,12 @@ settings_server <- function(id, data, adnca_data, settings_override) { } updatePickerInput(session, "select_analyte", choices = choices, selected = selected) - - # Additional settings (PCSPEC and ATPTREF handled later) - updateSelectInput(session, inputId = "method", selected = settings$method) - - if (!is.null(settings$bioavailability)) - updateSelectInput(session, inputId = "bioavailability", selected = settings$bioavailability) - - # Data imputation # - update_switch("should_impute_c0", value = settings$data_imputation$impute_c0) - - # Partial AUCs # - auc_data(settings$partial_aucs) - refresh_reactable(refresh_reactable() + 1) - - # Flags # - .update_rule_input( - session, - "R2ADJ", - settings$flags$R2ADJ$is.checked, - settings$flags$R2ADJ$threshold - ) - - .update_rule_input( - session, - "R2", - settings$flags$R2$is.checked, - settings$flags$R2$threshold - ) - - .update_rule_input( - session, - "AUCPEO", - settings$flags$AUCPEO$is.checked, - settings$flags$AUCPEO$threshold - ) - - .update_rule_input( - session, - "AUCPEP", - settings$flags$AUCPEP$is.checked, - settings$flags$AUCPEP$threshold - ) - - .update_rule_input( - session, - "LAMZSPN", - settings$flags$LAMZSPN$is.checked, - settings$flags$LAMZSPN$threshold - ) }) # Update Downstream Inputs (Profile & Specimen) observeEvent(input$select_analyte, { req(data()) + settings <- settings_override() # Filter data based on Analyte From faf9e232837fb3b7cf08024f9f8175ad5b344e59 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Tue, 6 Jan 2026 17:31:38 +0100 Subject: [PATCH 08/25] remove test settings file --- tests/testthat/data/settings.rds | Bin 744 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/testthat/data/settings.rds diff --git a/tests/testthat/data/settings.rds b/tests/testthat/data/settings.rds deleted file mode 100644 index 3ea3f54d997109ced5e431f215981e494ade5eac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 744 zcmVZZvH z8eew(_&So%ozkl--For1j0&3-p%C+?VI)jafhXQ>A;nZ)Xq#$XJl}uk-<6+$zqx4Q zHBB~)uN}~~ku&^|pDfGnii>*IaN6bqF)=}@r+^h4`3th)f+ynvE|?G`F{KkfP?RYt zwe9#wASYnbkV=TGWva?hY05GE;8(DC9+@U`CbHhf+B|@L1IX+sIa%h(){+-?Ltz$r8V+WFBxbWoBg@R zu+$NCk7buo=+1~lmlSvVbHUIR;$BJ-gRZO2PCj-IW18{@>akO1x9IjjCM*sJ1+txZ zJi*ZE+94LR7@Xgll2|Gx6io>w;s)TnlT8+_I*$wFYdw)&lOURRN{FWwP;^-mX++8# z?a14*6$;EI98>J&f|M7gYK*lwK0JK%<^;24BxN{qtLg{l{_FjwNG@jb_sHM4?H-NX z{t-lNJQ^RKo*YBo&o5jUi`K9=cvsHIVZS#z8x%5)Osh|vtia8zVadJO@L)e$ Date: Tue, 6 Jan 2026 17:44:10 +0100 Subject: [PATCH 09/25] lint --- inst/shiny/modules/tab_nca/setup/settings.R | 114 +++++++++--------- .../modules/tab_nca/setup/slope_selector.R | 2 +- 2 files changed, 56 insertions(+), 60 deletions(-) diff --git a/inst/shiny/modules/tab_nca/setup/settings.R b/inst/shiny/modules/tab_nca/setup/settings.R index fc35d312c..3f49ce772 100644 --- a/inst/shiny/modules/tab_nca/setup/settings.R +++ b/inst/shiny/modules/tab_nca/setup/settings.R @@ -135,27 +135,26 @@ settings_server <- function(id, data, adnca_data, settings_override) { conc_data <- reactive(adnca_data()$conc$data) - # File Upload Handling observeEvent(c(data(), settings_override()), { req(data()) # Initialize Analyte + Global Validation choices <- unique(data()$PARAM) %>% na.omit() settings <- settings_override() - + # Defaults selected <- choices not_compatible <- c() - + # if settings exist, update analyte picker input and check compatibility if (!is.null(settings)) { - + if (all(settings$analyte %in% choices)) { selected <- settings$analyte } else { not_compatible <- c(not_compatible, "Analyte") } - + # We check raw data here just to see if the settings exist if (!all(settings$profile %in% data()$ATPTREF)) { not_compatible <- c(not_compatible, "Profile") @@ -163,20 +162,21 @@ settings_server <- function(id, data, adnca_data, settings_override) { if (!all(settings$pcspec %in% data()$PCSPEC)) { not_compatible <- c(not_compatible, "Dose Specimen") } - + # Additional settings (PCSPEC and ATPTREF handled later) updateSelectInput(session, inputId = "method", selected = settings$method) - + if (!is.null(settings$bioavailability)) - updateSelectInput(session, inputId = "bioavailability", selected = settings$bioavailability) - + updateSelectInput(session, inputId = "bioavailability", + selected = settings$bioavailability) + # Data imputation # update_switch("should_impute_c0", value = settings$data_imputation$impute_c0) - + # Partial AUCs # auc_data(settings$partial_aucs) refresh_reactable(refresh_reactable() + 1) - + # Flags # .update_rule_input( session, @@ -184,28 +184,28 @@ settings_server <- function(id, data, adnca_data, settings_override) { settings$flags$R2ADJ$is.checked, settings$flags$R2ADJ$threshold ) - + .update_rule_input( session, "R2", settings$flags$R2$is.checked, settings$flags$R2$threshold ) - + .update_rule_input( session, "AUCPEO", settings$flags$AUCPEO$is.checked, settings$flags$AUCPEO$threshold ) - + .update_rule_input( session, "AUCPEP", settings$flags$AUCPEP$is.checked, settings$flags$AUCPEP$threshold ) - + .update_rule_input( session, "LAMZSPN", @@ -213,56 +213,69 @@ settings_server <- function(id, data, adnca_data, settings_override) { settings$flags$LAMZSPN$threshold ) } - + if (length(not_compatible) > 0) { - msg <- paste0(paste0(not_compatible, collapse = ", "), + msg <- paste0(paste0(not_compatible, collapse = ", "), " settings not found in data. Reverting to defaults.") log_warn(msg) showNotification(msg, type = "warning", duration = 10) } - + updatePickerInput(session, "select_analyte", choices = choices, selected = selected) }) - + # Update Downstream Inputs (Profile & Specimen) observeEvent(input$select_analyte, { req(data()) settings <- settings_override() - + # Filter data based on Analyte filtered_data <- data() %>% filter(PARAM %in% input$select_analyte, !is.na(PCSPEC), !is.na(ATPTREF)) - + profile_choices <- sort(unique(filtered_data$ATPTREF)) pcspec_choices <- unique(filtered_data$PCSPEC) - + # PROFILE current_profile <- isolate(input$select_profile) - - if (!is.null(settings) && all(settings$profile %in% profile_choices)) { - target_profile <- settings$profile - } else if (length(intersect(current_profile, profile_choices)) > 0) { - target_profile <- current_profile # Keep current if valid - } else { - target_profile <- profile_choices[1] # Default - } - # SPECIMEN current_pcspec <- isolate(input$select_pcspec) - - if (!is.null(settings) && all(settings$pcspec %in% pcspec_choices)) { - target_pcspec <- settings$pcspec - } else if (length(intersect(current_pcspec, pcspec_choices)) > 0) { - target_pcspec <- current_pcspec # Keep current if valid + + if (!is.null(settings)) { + if (all(settings$profile %in% profile_choices)) { + target_profile <- settings$profile + } + if (all(settings$pcspec %in% pcspec_choices)) { + target_pcspec <- settings$pcspec + } } else { - # Smart Default (Plasma/Serum) - plasma_serum <- grep("^plasma$|^serum$", pcspec_choices, value = TRUE, ignore.case = TRUE) - target_pcspec <- if(length(plasma_serum) > 0) plasma_serum else pcspec_choices + if (length(intersect(current_profile, profile_choices)) > 0) { + target_profile <- current_profile # Keep current if valid + } else { + target_profile <- profile_choices[1] + } + if (length(intersect(current_pcspec, pcspec_choices)) > 0) { + target_pcspec <- current_pcspec # Keep current if valid + } else { + # Smart Default (Plasma/Serum) + plasma_serum <- grep("^plasma$|^serum$", pcspec_choices, value = TRUE, ignore.case = TRUE) + target_pcspec <- if (length(plasma_serum) > 0) plasma_serum else pcspec_choices + } } - - updatePickerInput(session, "select_profile", choices = profile_choices, selected = target_profile) - updatePickerInput(session, "select_pcspec", choices = pcspec_choices, selected = target_pcspec) + + updatePickerInput( + session, + "select_profile", + choices = profile_choices, + selected = target_profile + ) + updatePickerInput( + session, + "select_pcspec", + choices = pcspec_choices, + selected = target_pcspec + ) }) # Include keyboard limits for the settings GUI display @@ -273,23 +286,6 @@ settings_server <- function(id, data, adnca_data, settings_override) { limit_input_value(input, session, "AUCPEP_threshold", max = 100, min = 0, lab = "AUCPEP") limit_input_value(input, session, "LAMZSPN_threshold", min = 0, lab = "LAMZSPN") - - # Choose data to be analyzed - observeEvent(data(), priority = 1, { - req(data()) - - choices <- unique(data()$PARAM) %>% - na.omit() - - updatePickerInput( - session, - inputId = "select_analyte", - choices = choices, - selected = choices - ) - - }) - # Reactive value to store the AUC data table auc_data <- reactiveVal( tibble(start_auc = rep(NA_real_, 2), end_auc = rep(NA_real_, 2)) diff --git a/inst/shiny/modules/tab_nca/setup/slope_selector.R b/inst/shiny/modules/tab_nca/setup/slope_selector.R index 621e301f9..bca69c777 100644 --- a/inst/shiny/modules/tab_nca/setup/slope_selector.R +++ b/inst/shiny/modules/tab_nca/setup/slope_selector.R @@ -349,7 +349,7 @@ slope_selector_server <- function( # nolint allowed_keys <- c("PCSPEC", "USUBJID", "PARAM", "ATPTREF", "DOSNOA") use_keys <- intersect(allowed_keys, names(manual_slopes_override())) - + override_valid <- manual_slopes_override() %>% dplyr::semi_join(plot_data()$conc$data, by = use_keys) %>% nrow() == nrow(manual_slopes_override()) From 1118307ba56c3de7ec900dba4df7bc1b4155dd35 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Wed, 14 Jan 2026 11:29:29 +0100 Subject: [PATCH 10/25] fix: issue w type mismatch in slope selector --- inst/shiny/modules/tab_nca/setup/slope_selector.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/inst/shiny/modules/tab_nca/setup/slope_selector.R b/inst/shiny/modules/tab_nca/setup/slope_selector.R index bca69c777..deb07985c 100644 --- a/inst/shiny/modules/tab_nca/setup/slope_selector.R +++ b/inst/shiny/modules/tab_nca/setup/slope_selector.R @@ -351,7 +351,9 @@ slope_selector_server <- function( # nolint use_keys <- intersect(allowed_keys, names(manual_slopes_override())) override_valid <- manual_slopes_override() %>% - dplyr::semi_join(plot_data()$conc$data, by = use_keys) %>% + mutate(across(all_of(use_keys), as.character)) %>% # mutate incase of type issues + semi_join(plot_data()$conc$data %>% + mutate(across(all_of(use_keys), as.character)), by = use_keys) %>% nrow() == nrow(manual_slopes_override()) if (!override_valid) { From 1c1a4f3c6ab6d02d3c5c37a30bba7c6f2bde7aab Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Thu, 15 Jan 2026 11:50:07 +0100 Subject: [PATCH 11/25] rm settings upload button in nca tab --- inst/shiny/modules/tab_nca/setup.R | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/inst/shiny/modules/tab_nca/setup.R b/inst/shiny/modules/tab_nca/setup.R index 2a42c1f4a..6b8c78e12 100644 --- a/inst/shiny/modules/tab_nca/setup.R +++ b/inst/shiny/modules/tab_nca/setup.R @@ -21,20 +21,9 @@ setup_ui <- function(id) { nav_panel( "Settings", fluidRow( - column(6, - fileInput( - ns("settings_upload"), - width = "100%", - label = "Upload settings", - buttonLabel = list(icon("folder"), "Browse"), - accept = ".rds" - ) - ), - column(6, - downloadButton( - ns("settings_download"), - label = "Download settings" - ) + downloadButton( + ns("settings_download"), + label = "Download settings" ) ), fluidRow(units_table_ui(ns("units_table"))), From e22b4d1ac609ac673273de3581c092a01358dc33 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Thu, 15 Jan 2026 11:56:58 +0100 Subject: [PATCH 12/25] refactor: update widget text to specify settings upload --- inst/shiny/modules/tab_data/data_upload.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index 958b5e461..691ea45b5 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -15,7 +15,7 @@ data_upload_ui <- function(id) { div( class = "upload-container", id = ns("upload_container"), - p("Upload your PK dataset."), + p("Upload your PK dataset and Settings file (optional)."), fileInput( ns("data_upload"), width = "50%", From 463220d8e51bf66c583520c76d23debafd521311 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Thu, 15 Jan 2026 12:10:31 +0100 Subject: [PATCH 13/25] lint --- inst/shiny/modules/tab_nca/setup/slope_selector.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/shiny/modules/tab_nca/setup/slope_selector.R b/inst/shiny/modules/tab_nca/setup/slope_selector.R index deb07985c..6557ee932 100644 --- a/inst/shiny/modules/tab_nca/setup/slope_selector.R +++ b/inst/shiny/modules/tab_nca/setup/slope_selector.R @@ -352,7 +352,7 @@ slope_selector_server <- function( # nolint override_valid <- manual_slopes_override() %>% mutate(across(all_of(use_keys), as.character)) %>% # mutate incase of type issues - semi_join(plot_data()$conc$data %>% + semi_join(plot_data()$conc$data %>% mutate(across(all_of(use_keys), as.character)), by = use_keys) %>% nrow() == nrow(manual_slopes_override()) From f2a861a0c9162e6a3d53f0bcda0b0c126f9da1a6 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Thu, 15 Jan 2026 15:45:55 +0100 Subject: [PATCH 14/25] style: use anaonymous functions in purrr --- inst/shiny/modules/tab_data/data_upload.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index 691ea45b5..748b32272 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -102,12 +102,12 @@ data_upload_server <- function(id) { }) # Process results - successful_loads <- purrr::keep(read_results, ~ .x$status == "success") + successful_loads <- purrr::keep(read_results, \(x) x$status == "success") errors <- purrr::keep(read_results, \(x) x$status == "error") %>% purrr::map(\(x) paste0(x$name, ": ", x$message)) # Extract and apply settings if any found - found_settings <- purrr::keep(successful_loads, ~ .x$type == "settings") + found_settings <- purrr::keep(successful_loads, \(x) x$type == "settings") if (length(found_settings) > 1) { # Error: Too many settings files From dc77c8b063407ffbd9c160e330635cec2afec197 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Mon, 19 Jan 2026 09:32:24 +0100 Subject: [PATCH 15/25] refactor: anonymous functinos --- inst/shiny/modules/tab_data/data_upload.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index 748b32272..e6aeb520c 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -113,7 +113,7 @@ data_upload_server <- function(id) { # Error: Too many settings files msg <- "Error: Multiple settings files detected. Please upload only one settings file." prev_msgs <- if (length(errors) > 0) { - paste(purrr::map_chr(errors, ~ paste0(.x$name, ": ", .x$msg)), collapse = "
") + paste(purrr::map_chr(errors, \(x) paste0(x$name, ": ", x$msg)), collapse = "
") } else { "" } @@ -132,7 +132,7 @@ data_upload_server <- function(id) { loaded_data <- DUMMY_DATA - found_data <- purrr::keep(successful_loads, ~ .x$type == "data") + found_data <- purrr::keep(successful_loads, \(x) x$type == "data") # Handle Errors if (length(found_data) > 0) { tryCatch({ From bc408ebae767f9bec0e0078122aee9ee00063a4d Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Mon, 19 Jan 2026 09:50:22 +0100 Subject: [PATCH 16/25] refactor: settings upload handling refactor --- inst/shiny/modules/tab_data/data_upload.R | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index e6aeb520c..db4b28df7 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -82,21 +82,22 @@ data_upload_server <- function(id) { # If read_pk fails # check if settings file is loaded and then create settings override tryCatch({ + # check if error aligns with what we expect for setttings file + if (conditionMessage(e_pk) != "Invalid data format. Data frame was expected, but received list.") { + return(list(status = "error", msg = conditionMessage(e_pk), name = name)) + } + obj <- readRDS(path) # Check for settings is_settings <- is.list(obj) && "settings" %in% names(obj) - final_settings <- if (is_settings) obj else NULL - - if (!is.null(final_settings)) { - list(status = "success", type = "settings", content = final_settings, name = name) - } else { - # Not a settings file either, return original PK error - stop(e_pk$message) + if (!is_settings) { + stop(conditionMessage(e_pk)) } + + list(status = "success", type = "settings", content = obj, name = name) }, error = function(e_rds) { - # Return the original read_pk error to the user - list(status = "error", msg = e_pk$message, name = name) + list(status = "error", msg = conditionMessage(e_pk), name = name) }) }) }) @@ -104,7 +105,7 @@ data_upload_server <- function(id) { # Process results successful_loads <- purrr::keep(read_results, \(x) x$status == "success") errors <- purrr::keep(read_results, \(x) x$status == "error") %>% - purrr::map(\(x) paste0(x$name, ": ", x$message)) + purrr::map(\(x) paste0(x$name, ": ", x$msg)) # Extract and apply settings if any found found_settings <- purrr::keep(successful_loads, \(x) x$type == "settings") From 72857d76fe8ff177b624899b0a9a855840ac5ae6 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Mon, 19 Jan 2026 09:52:43 +0100 Subject: [PATCH 17/25] refactor: settings file error messages --- inst/shiny/modules/tab_data/data_upload.R | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index db4b28df7..d6558c547 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -112,14 +112,7 @@ data_upload_server <- function(id) { if (length(found_settings) > 1) { # Error: Too many settings files - msg <- "Error: Multiple settings files detected. Please upload only one settings file." - prev_msgs <- if (length(errors) > 0) { - paste(purrr::map_chr(errors, \(x) paste0(x$name, ": ", x$msg)), collapse = "
") - } else { - "" - } - file_loading_error(paste(c(prev_msgs, msg), collapse = "
")) - + errors <- append(errors, "Error: Multiple settings files detected. Please upload only one settings file.") # Do not apply any settings if ambiguous settings_override(NULL) From ed4d82226062a9b26a9934430b0ba6c130cf27ac Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Mon, 19 Jan 2026 09:53:57 +0100 Subject: [PATCH 18/25] lint --- inst/shiny/modules/tab_data/data_upload.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index d6558c547..ed7597876 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -83,10 +83,11 @@ data_upload_server <- function(id) { # check if settings file is loaded and then create settings override tryCatch({ # check if error aligns with what we expect for setttings file - if (conditionMessage(e_pk) != "Invalid data format. Data frame was expected, but received list.") { + if (conditionMessage(e_pk) != "Invalid data format. + Data frame was expected, but received list.") { return(list(status = "error", msg = conditionMessage(e_pk), name = name)) } - + obj <- readRDS(path) # Check for settings is_settings <- is.list(obj) && "settings" %in% names(obj) @@ -112,7 +113,8 @@ data_upload_server <- function(id) { if (length(found_settings) > 1) { # Error: Too many settings files - errors <- append(errors, "Error: Multiple settings files detected. Please upload only one settings file.") + errors <- append(errors, "Error: Multiple settings files detected. + Please upload only one settings file.") # Do not apply any settings if ambiguous settings_override(NULL) From 89085900e05a7bfee065d942b1a36667c6ce6df8 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Fri, 23 Jan 2026 13:52:28 +0100 Subject: [PATCH 19/25] fix: slope rules export for both settinsg downloads --- inst/shiny/modules/tab_nca.R | 9 +++---- inst/shiny/modules/tab_nca/setup.R | 2 +- .../modules/tab_nca/setup/slope_selector.R | 24 ++++++++++--------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/inst/shiny/modules/tab_nca.R b/inst/shiny/modules/tab_nca.R index 025b37b9d..59130d999 100644 --- a/inst/shiny/modules/tab_nca.R +++ b/inst/shiny/modules/tab_nca.R @@ -81,9 +81,10 @@ tab_nca_server <- function(id, pknca_data, extra_group_vars, settings_override) ratio_table <- nca_setup$ratio_table slope_rules <- nca_setup$slope_rules + session$userData$settings <- list( settings = settings, - slope_rules = slope_rules$manual_slopes + slope_rules = slope_rules ) # This will be saved in the results zip folder reactable_server("manual_slopes", slope_rules$manual_slopes) @@ -127,9 +128,9 @@ tab_nca_server <- function(id, pknca_data, extra_group_vars, settings_override) res <- withCallingHandlers({ processed_pknca_data %>% filter_slopes( - slope_rules$manual_slopes(), - slope_rules$profiles_per_subject(), - slope_rules$slopes_groups(), + slope_rules()$manual_slopes, + slope_rules()$profiles_per_subject, + slope_rules()$slopes_groups, check_reasons = TRUE ) %>% # Perform PKNCA parameter calculations diff --git a/inst/shiny/modules/tab_nca/setup.R b/inst/shiny/modules/tab_nca/setup.R index 97e528c78..b8a4d4949 100644 --- a/inst/shiny/modules/tab_nca/setup.R +++ b/inst/shiny/modules/tab_nca/setup.R @@ -187,7 +187,7 @@ setup_server <- function(id, data, adnca_data, extra_group_vars, settings_overri paste0(session$userData$project_name(), "_settings_", Sys.Date(), ".rds") }, content = function(con) { - saveRDS(list(settings = final_settings(), slope_rules = slope_rules$manual_slopes()), con) + saveRDS(list(settings = final_settings(), slope_rules = slope_rules()), con) } ) diff --git a/inst/shiny/modules/tab_nca/setup/slope_selector.R b/inst/shiny/modules/tab_nca/setup/slope_selector.R index 6557ee932..784730d7c 100644 --- a/inst/shiny/modules/tab_nca/setup/slope_selector.R +++ b/inst/shiny/modules/tab_nca/setup/slope_selector.R @@ -343,18 +343,18 @@ slope_selector_server <- function( # nolint observeEvent(list(manual_slopes_override(), plot_data()), { req(manual_slopes_override(), plot_data()) - if (nrow(manual_slopes_override()) == 0) return(NULL) + if (nrow(manual_slopes_override()$manual_slopes) == 0) return(NULL) - log_debug_list("Manual slopes override:", manual_slopes_override()) + log_debug_list("Manual slopes override:", manual_slopes_override()$manual_slopes) allowed_keys <- c("PCSPEC", "USUBJID", "PARAM", "ATPTREF", "DOSNOA") - use_keys <- intersect(allowed_keys, names(manual_slopes_override())) + use_keys <- intersect(allowed_keys, names(manual_slopes_override()$manual_slopes)) - override_valid <- manual_slopes_override() %>% + override_valid <- manual_slopes_override()$manual_slopes %>% mutate(across(all_of(use_keys), as.character)) %>% # mutate incase of type issues semi_join(plot_data()$conc$data %>% mutate(across(all_of(use_keys), as.character)), by = use_keys) %>% - nrow() == nrow(manual_slopes_override()) + nrow() == nrow(manual_slopes_override()$manual_slopes) if (!override_valid) { msg <- "Manual slopes not compatible with current data, leaving as default." @@ -363,14 +363,16 @@ slope_selector_server <- function( # nolint return(NULL) } - manual_slopes(manual_slopes_override()) + manual_slopes(manual_slopes_override()$manual_slopes) }) #' return reactive with slope exclusions data to be displayed in Results -> Exclusions tab - list( - manual_slopes = manual_slopes, - profiles_per_subject = profiles_per_subject, - slopes_groups = slopes_groups - ) + reactive({ + list( + manual_slopes = manual_slopes(), + profiles_per_subject = profiles_per_subject(), + slopes_groups = slopes_groups() + ) + }) }) } From c3c099e513da09fe7c3ea3f05f130191c35ca16f Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Fri, 23 Jan 2026 13:54:49 +0100 Subject: [PATCH 20/25] lint --- inst/shiny/modules/tab_data/data_upload.R | 2 +- inst/shiny/modules/tab_nca.R | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index 1af216c78..6b95b04c0 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -83,7 +83,7 @@ data_upload_server <- function(id) { # check if settings file is loaded and then create settings override tryCatch({ # check if error aligns with what we expect for settings file - if (conditionMessage(e_pk) != "Invalid data format. Data frame was expected, but received list.") { + if (conditionMessage(e_pk) != "Invalid data format. Data frame was expected, but received list.") { #nolint return(list(status = "error", msg = conditionMessage(e_pk), name = name)) } diff --git a/inst/shiny/modules/tab_nca.R b/inst/shiny/modules/tab_nca.R index 59130d999..8f77859d5 100644 --- a/inst/shiny/modules/tab_nca.R +++ b/inst/shiny/modules/tab_nca.R @@ -74,7 +74,13 @@ tab_nca_server <- function(id, pknca_data, extra_group_vars, settings_override) adnca_data <- reactive(pknca_data()$conc$data) # #' NCA Setup module - nca_setup <- setup_server("nca_setup", adnca_data, pknca_data, extra_group_vars, settings_override) + nca_setup <- setup_server( + "nca_setup", + adnca_data, + pknca_data, + extra_group_vars, + settings_override + ) processed_pknca_data <- nca_setup$processed_pknca_data settings <- nca_setup$settings From 4f972215fd8bd8d5ab103be8d0a8e30157025a44 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Fri, 23 Jan 2026 14:15:00 +0100 Subject: [PATCH 21/25] update PR template --- .github/PULL_REQUEST_TEMPLATE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ad5f31524..d8b26aaf8 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -22,6 +22,7 @@ How to test features not covered by unit tests. - [ ] App or package changes are reflected in NEWS - [ ] Package version is incremented - [ ] R script works with the new implementation (if applicable) +- [ ] Settings upload works with the new implementation (if applicable) ## Notes to reviewer From 7b909ae2b6bd008be58871ce4d0ff851b1cce08c Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Fri, 23 Jan 2026 14:16:24 +0100 Subject: [PATCH 22/25] update description and news --- DESCRIPTION | 2 +- NEWS.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index d10fb1978..8e65df0c1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: aNCA Title: (Pre-)Clinical NCA in a Dynamic Shiny App -Version: 0.1.0.9043 +Version: 0.1.0.9044 Authors@R: c( person("Ercan", "Suekuer", email = "ercan.suekuer@roche.com", role = "aut", comment = c(ORCID = "0009-0001-1626-1526")), diff --git a/NEWS.md b/NEWS.md index b9b2497a6..bb12d1588 100644 --- a/NEWS.md +++ b/NEWS.md @@ -16,6 +16,7 @@ * CMAX automatically selected in box plots if available (#890) * Allow user to select additional `grouping variables` (chosen in the mapping) for ratio calculations (#868) * General button at top page to save all NCA results, settings & draft slides as a ZIP file (#638) +* Settings are now uploaded on initial opening of the app in the data tab, and applied to the next steps (#860) ## Bugs fixed From 72ea2e401acb44ecf30408c8df1710c6b974ac69 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Fri, 23 Jan 2026 16:18:12 +0100 Subject: [PATCH 23/25] update rscript data to raw_data() --- inst/shiny/modules/tab_data/data_upload.R | 5 +++++ inst/shiny/modules/tab_nca/zip.R | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index 294ce75a1..7d4382c9c 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -162,6 +162,11 @@ data_upload_server <- function(id) { }) %>% bindEvent(input$data_upload, ignoreNULL = FALSE) ) + + observeEvent(raw_data(), { + session$userData$raw_data <- raw_data() + } + ) reactable_server( "data_display", diff --git a/inst/shiny/modules/tab_nca/zip.R b/inst/shiny/modules/tab_nca/zip.R index 25f3d33fa..39623c3dd 100644 --- a/inst/shiny/modules/tab_nca/zip.R +++ b/inst/shiny/modules/tab_nca/zip.R @@ -189,7 +189,7 @@ zip_server <- function(id, res_nca, settings, grouping_vars) { # Save input dataset used data_tmpdir <- file.path(output_tmpdir, "data") dir.create(data_tmpdir, recursive = TRUE) - data <- read_pk(session$userData$data_path) + data <- session$userData$raw_data saveRDS(data, paste0(data_tmpdir, "/data.rds")) # Save a code R script template for the session From adadea936a229d42424435ce2a3133f350e860f4 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Fri, 23 Jan 2026 16:19:14 +0100 Subject: [PATCH 24/25] lint --- inst/shiny/modules/tab_data/data_upload.R | 9 +-------- inst/shiny/modules/tab_nca/zip.R | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index 7d4382c9c..ad477b12d 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -52,13 +52,6 @@ data_upload_server <- function(id) { }) datapath <- getOption("aNCA.datapath", NULL) - observe({ - if (!is.null(input$data_upload$datapath)) { - session$userData$data_path <- input$data_upload$datapath - } else { - session$userData$data_path <- system.file("shiny/data/example-ADNCA.csv", package = "aNCA") - } - }) raw_data <- ( reactive({ @@ -162,7 +155,7 @@ data_upload_server <- function(id) { }) %>% bindEvent(input$data_upload, ignoreNULL = FALSE) ) - + observeEvent(raw_data(), { session$userData$raw_data <- raw_data() } diff --git a/inst/shiny/modules/tab_nca/zip.R b/inst/shiny/modules/tab_nca/zip.R index 39623c3dd..2d6e06483 100644 --- a/inst/shiny/modules/tab_nca/zip.R +++ b/inst/shiny/modules/tab_nca/zip.R @@ -183,7 +183,7 @@ zip_server <- function(id, res_nca, settings, grouping_vars) { slope_rules = session$userData$slope_rules() ) saveRDS(settings_to_save, paste0(setts_tmpdir, "/settings.rds")) - + } # Save input dataset used From e9d8d3efa7738c71f4c732473191c3180b856682 Mon Sep 17 00:00:00 2001 From: Jana Spinner Date: Fri, 23 Jan 2026 16:20:19 +0100 Subject: [PATCH 25/25] lint --- inst/shiny/modules/tab_data/data_upload.R | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/inst/shiny/modules/tab_data/data_upload.R b/inst/shiny/modules/tab_data/data_upload.R index ad477b12d..d661d3735 100644 --- a/inst/shiny/modules/tab_data/data_upload.R +++ b/inst/shiny/modules/tab_data/data_upload.R @@ -155,11 +155,10 @@ data_upload_server <- function(id) { }) %>% bindEvent(input$data_upload, ignoreNULL = FALSE) ) - + observeEvent(raw_data(), { session$userData$raw_data <- raw_data() - } - ) + }) reactable_server( "data_display",