Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions inst/shiny/functions/utils-exclusions.R
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ EXCL_COLOR_BOTH <- "#FFD9B3" # orange — NCA + TLG
exclusion_list(append(current, list_new_reason))
updateTextInput(session, "exclusion_reason", value = "")
updateReactable(table_id, selected = NA)

type_label <- .exclusion_type_label(nca_checked, tlg_checked)
log_info(
"Exclusion added: ", length(rows_sel), " rows, type=", type_label,
", reason='", reason, "'"
)
}
}

Expand Down
9 changes: 9 additions & 0 deletions inst/shiny/modules/tab_nca/setup/data_imputation.R
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,15 @@ data_imputation_server <- function(id, settings_override) {
}
})

observeEvent(input$select_blq_strategy, {
log_info("BLQ imputation strategy changed: ", input$select_blq_strategy)
}, ignoreInit = TRUE)

observeEvent(input$should_impute_c0, {
state <- if (isTRUE(input$should_impute_c0)) "enabled" else "disabled"
log_info("Start concentration imputation ", state)
}, ignoreInit = TRUE)

blq_imputation_rule <- reactive({
req(input$select_blq_strategy)
rule_list <- switch(input$select_blq_strategy,
Expand Down
2 changes: 2 additions & 0 deletions inst/shiny/modules/tab_nca/setup/general_exclusions.R
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ general_exclusions_server <- function(

xbtn_counter(max(new_ids))
exclusion_list(rehydrated_list)
log_info("Exclusions restored from settings: ", length(overrides), " rules loaded")
}
})

Expand Down Expand Up @@ -167,6 +168,7 @@ general_exclusions_server <- function(
lapply(lst, function(item) {
xbtn_id <- item$xbtn_id
observeEvent(input[[xbtn_id]], {
log_info("Exclusion removed: reason='", item$reason, "'")
current <- exclusion_list()
exclusion_list(
Filter(function(x) x$xbtn_id != xbtn_id, current)
Expand Down
6 changes: 3 additions & 3 deletions inst/shiny/modules/tab_nca/setup/manual_slopes_table.R
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ manual_slopes_table_server <- function(

# Add a new row to the table when the user clicks the add button
observeEvent(input$add_rule, {
log_trace("{id}: adding manual slopes row")
log_trace("Slope selector: adding manual slope rule")
Comment thread
Shaakon35 marked this conversation as resolved.
first_group <- slopes_pknca_groups()[1, ]
time_col <- pknca_data()$conc$columns$time
new_row <- cbind(
Expand Down Expand Up @@ -126,7 +126,7 @@ manual_slopes_table_server <- function(

# Remove selected rows from the table when the user clicks the remove button
observeEvent(input$remove_rule, {
log_trace("{id}: removing manual slopes row")
log_trace("Slope selector: removing manual slope rule")
selected <- getReactableState("manual_slopes", "selected")
req(selected)
edited_slopes <- manual_slopes()[-selected, ]
Expand All @@ -138,7 +138,7 @@ manual_slopes_table_server <- function(
# Render the manual slopes table (reactable)
output$manual_slopes <- renderReactable({
req(manual_slopes())
log_trace("{id}: rendering slope edit data table")
log_trace(id, ": rendering slope edit data table")
isolate({
data <- manual_slopes()
})
Expand Down
5 changes: 4 additions & 1 deletion inst/shiny/modules/tab_nca/setup/parameter_selection.R
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,10 @@ parameter_selection_server <- function(id, processed_pknca_data, parameter_overr
params <- selection_debounce()
n_params <- if (is.null(params)) 0 else length(params)

log_info("Parameter selection for '{study_type}': {n_params} parameters selected.")
log_info("Parameter selection for '", study_type, "': ", n_params, " parameters selected.")
if (n_params > 0) {
log_debug("Parameters for '", study_type, "': ", paste(params, collapse = ", "))
Comment thread
Shaakon35 marked this conversation as resolved.
}
}, ignoreNULL = FALSE, ignoreInit = TRUE)
})
})
Expand Down
49 changes: 48 additions & 1 deletion inst/shiny/modules/tab_nca/setup/settings.R
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@ settings_server <- function(id, data, adnca_data, settings_override) {
# A guard flag prevents infinite observer loops.
updating_filters <- reactiveVal(FALSE)

# Guard to suppress log noise during initial data load / settings restore.
# Set to TRUE after the first analyte cascade completes.
filters_initialized <- reactiveVal(FALSE)

# settings_override is consumed once during the first cascade after
# settings upload. After that, pending_settings is set to NULL so
# subsequent user-driven changes are not overridden by stale values.
Expand Down Expand Up @@ -299,7 +303,14 @@ settings_server <- function(id, data, adnca_data, settings_override) {
req(data(), input$select_analyte)
if (updating_filters()) return()
updating_filters(TRUE)
on.exit(updating_filters(FALSE))
on.exit({
updating_filters(FALSE)
if (!filters_initialized()) filters_initialized(TRUE)
})

if (filters_initialized()) {
log_info("Analyte selection changed: ", paste(input$select_analyte, collapse = ", "))
}

settings <- .consume_settings()

Expand Down Expand Up @@ -335,6 +346,10 @@ settings_server <- function(id, data, adnca_data, settings_override) {
updating_filters(TRUE)
on.exit(updating_filters(FALSE))

if (filters_initialized()) {
log_info("Specimen selection changed: ", paste(input$select_pcspec, collapse = ", "))
}

settings <- .consume_settings()

all_analyte <- unique(data()$PARAM) %>% na.omit()
Expand All @@ -356,6 +371,25 @@ settings_server <- function(id, data, adnca_data, settings_override) {
.update_profile(settings)
})

# Log profile, method, and min half-life points changes
observeEvent(input$select_profile, {
if (filters_initialized()) {
log_info("NCA profile changed: ", paste(input$select_profile, collapse = ", "))
}
}, ignoreInit = TRUE)

observeEvent(input$method, {
if (filters_initialized()) {
log_info("Extrapolation method changed: ", input$method)
}
}, ignoreInit = TRUE)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ignoreInit = TRUE prevents firing on first render, but input$method is still updated programmatically during settings restore via .restore_non_filter_settingsupdateSelectInput(session, "method", ...). This will log "Extrapolation method changed" when the user uploads settings — which is a restore, not a user change.

The analyte, specimen, and profile observers already guard against this with filters_initialized(). Consider applying the same pattern here:

observeEvent(input$method, {
  if (filters_initialized()) {
    log_info("Extrapolation method changed: ", input$method)
  }
}, ignoreInit = TRUE)

observeEvent(input$min_hl_points, {
  if (filters_initialized()) {
    log_info("Min. half-life points changed: ", input$min_hl_points)
  }
}, ignoreInit = TRUE)

If logging during settings restore is intentional, add a comment noting that.


observeEvent(input$min_hl_points, {
if (filters_initialized()) {
log_info("Min. half-life points changed: ", input$min_hl_points)
}
}, ignoreInit = TRUE)

# Include keyboard limits for the settings GUI display

# Keyboard limits for the setting thresholds
Expand All @@ -365,6 +399,19 @@ settings_server <- function(id, data, adnca_data, settings_override) {
limit_input_value(input, session, "LAMZSPN_threshold", min = 0, lab = "LAMZSPN")
limit_input_value(input, session, "min_hl_points", max = 10, min = 2, lab = "Min. HL Points")

# Log flag rule changes
lapply(c("R2ADJ", "R2", "AUCPEO", "AUCPEP", "LAMZSPN"), function(flag) {
rule_id <- paste0(flag, "_rule")
threshold_id <- paste0(flag, "_threshold")
observeEvent(input[[rule_id]], {
state <- if (input[[rule_id]]) "enabled" else "disabled"
log_info("Flag rule ", flag, " ", state)
}, ignoreInit = TRUE)
observeEvent(input[[threshold_id]], {
log_info("Flag rule ", flag, " threshold changed: ", input[[threshold_id]])
}, ignoreInit = TRUE)
})

# Reactive value to store the partial intervals data table
# Define the parameters that can be used for partial area calculations
PARTIAL_INT_PARAMS <- metadata_nca_parameters %>%
Expand Down
5 changes: 5 additions & 0 deletions inst/shiny/modules/tab_nca/setup/slope_selector.R
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ slope_selector_server <- function( # nolint
observeEvent(manual_slopes(), {
req(manual_slopes())

n_rules <- nrow(manual_slopes())
n_excl <- sum(manual_slopes()$TYPE == "Exclusion", na.rm = TRUE)
n_incl <- n_rules - n_excl
log_info("Slope rules updated: ", n_rules, " total (", n_incl, " selections, ", n_excl, " exclusions)")

Comment thread
Shaakon35 marked this conversation as resolved.
# Update reactable with rules
reactable::updateReactable(
outputId = "manual_slopes",
Expand Down