Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: aNCA
Title: (Pre-)Clinical NCA in a Dynamic Shiny App
Version: 0.1.0.9185
Version: 0.1.0.9186
Authors@R: c(
person("Ercan", "Suekuer", email = "ercan.suekuer@roche.com", role = "aut",
comment = c(ORCID = "0009-0001-1626-1526")),
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export(PKNCA_build_units_table)
export(PKNCA_calculate_nca)
export(PKNCA_create_data_object)
export(PKNCA_hl_rules_exclusion)
export(PKNCA_impute_method_end_conc_drop)
export(PKNCA_impute_method_start_c1)
export(PKNCA_impute_method_start_logslope)
export(PKNCA_update_data_object)
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* Partial interval parameters section supports calculations beyond `AUCINT`: `RCAMINT`, `AUCINTD`, `CAVGINT`, and others. Table starts empty by default with a Remove Row button (#524, #1249)
* "Min. Points for Half-life" setting added (range 2–10, default 3) (#1155)
* BLQ imputation rules via `NCA Setup > Data Imputation` (#139)
* "Drop End Concentration" switch in `NCA Setup > Data Imputation` drops the concentration at the end of each non-last main interval before regular parameter calculations, so a next-dose boundary point (e.g. an imputed C0) does not affect the previous dose profile. Partial/interval parameters and the last dose profile per group are unaffected (#1411)
* General Exclusions section for in-app NCA exclusions, with "Excl. TLG" checkbox per entry (#851, #1018)
* Parameter Exclusions tab: exclude individual PK parameter rows from descriptive statistics and ADPP export via PPSUMFL/PPSUMRSN flags (#1040)
* NCA flag rules (NCAwXRS) from ADNCA standards — flagged records are excluded from NCA (#752)
Expand Down
46 changes: 45 additions & 1 deletion R/PKNCA.R
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ PKNCA_create_data_object <- function( # nolint: object_name_linter
#' (forwarded to [update_main_intervals()]).
#' @param blq_imputation_rule Optional list defining the BLQ imputation rule
#' (forwarded to [update_main_intervals()]).
#' @param drop_end_conc Logical indicating whether to drop the concentration at
#' the end of each main interval for regular parameters (forwarded to
#' [update_main_intervals()]). Default `FALSE`.
#' @param custom_units_table Optional data frame with PPSTRESU overrides.
#' When provided, applied via [dplyr::rows_update()] on the PKNCAdata units table.
#'
Expand All @@ -308,6 +311,7 @@ PKNCA_update_data_object <- function( # nolint: object_name_linter
parameter_selections = NULL,
int_parameters = NULL,
blq_imputation_rule = NULL,
drop_end_conc = FALSE,
custom_units_table = NULL) {

data <- adnca_data
Expand Down Expand Up @@ -371,7 +375,8 @@ PKNCA_update_data_object <- function( # nolint: object_name_linter
parameter_selections = parameter_selections,
int_parameters = int_parameters,
impute = start_impute,
blq_imputation_rule = blq_imputation_rule
blq_imputation_rule = blq_imputation_rule,
drop_end_conc = drop_end_conc
)

# Apply custom units table
Expand Down Expand Up @@ -583,6 +588,45 @@ PKNCA_impute_method_start_c1 <- function(conc, time, start, end, ..., options =
d_conc_time
}

#' Drop the concentration measured exactly at the end of the interval
#'
#' Removes a concentration sitting exactly at `time == end` for an interval, if
#' one is present (no-op otherwise). This is typically used with multiple-dose
#' data where the boundary point belongs to the next dose (e.g. an imputed C0),
#' so it should not contribute to parameters on the current interval.
#'
#' @param conc Numeric vector of concentrations.
#' @param time Numeric vector of times corresponding to the concentrations.
#' @param end Numeric value (or vector) indicating the end time of the interval.
#' @param ... Additional arguments (currently not used).
#' @param options List of options (currently not used).
#'
#' @returns A data frame of `conc`/`time` with any end-boundary point removed.
#' @details
#' This function adheres to the structure required by the `PKNCA` package to work
#' with its imputation functionality. For more information, see the
#' [PKNCA Data Imputation Vignette](https://CRAN.R-project.org/package=PKNCA).
#'
#' TODO(end_conc_drop): remove this local copy once humanpred/pknca#572 is merged
#' and aNCA depends on a PKNCA release that exports
#' `PKNCA_impute_method_end_conc_drop()`. At that point drop this definition and
#' the corresponding `@export`/NAMESPACE entry and rely on the PKNCA-native method.
#' @export
#'
#' @examples
#' conc <- c(10, 5, 1)
#' time <- c(0, 12, 24)
#' end <- 24
#' PKNCA_impute_method_end_conc_drop(conc, time, end)
PKNCA_impute_method_end_conc_drop <- function(conc, time, end, ..., options = list()) { # nolint
d_conc_time <- data.frame(conc = conc, time = time)
mask_end <- time %in% end
if (any(mask_end)) {
d_conc_time <- d_conc_time[!mask_end, , drop = FALSE]
}
d_conc_time
}

#' Build Units Table for PKNCA
#'
#' This function generates a PKNCA units table including the potential unit segregating columns
Expand Down
40 changes: 38 additions & 2 deletions R/intervals.R
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,15 @@ format_pkncadata_intervals <- function(pknca_conc,
#' Each element can be a numeric value (substituting the BLQ value), or a string such as
#' `"drop"` (ignores the value) or `"keep"` (keeps the value as 0). Default is NULL,
#' which does not specify any BLQ imputation in any interval.
#' @param drop_end_conc Logical. If `TRUE`, the concentration measured exactly at
#' the end of each main interval is dropped before regular (non-partial) parameter
#' calculations via the `end_conc_drop` imputation. This does not affect
#' interval/partial parameter rows (`type_interval == "manual"`) nor the last dose
#' profile per concentration group, whose end-boundary point is a genuine terminal
#' sample rather than a next-dose C0. Default `FALSE`.
#'
#' @importFrom dplyr left_join mutate across where select all_of if_else bind_rows filter
#' @importFrom dplyr group_by ungroup slice_max distinct
#' @importFrom dplyr group_by ungroup slice_max distinct group_vars
#' @importFrom purrr pmap
#' @returns An updated PKNCAdata object with parameter intervals based on user selections.
#' @export
Expand All @@ -217,7 +223,8 @@ update_main_intervals <- function(
parameter_selections = NULL,
int_parameters = NULL,
impute = TRUE,
blq_imputation_rule = NULL
blq_imputation_rule = NULL,
drop_end_conc = FALSE
) {

if (is.null(parameter_selections)) parameter_selections <- list()
Expand Down Expand Up @@ -309,6 +316,35 @@ update_main_intervals <- function(
# Remove any imputation from the observational parameters
data <- rm_impute_obs_params(data, metadata_nca_parameters)

############################################
# Drop the end-boundary concentration for main intervals. Applied after
# rm_impute_obs_params() so it also covers observational parameters (e.g. Cmax,
# Tmax), where a spurious concentration at time == end would otherwise distort
# the result. Partial/interval parameters (type_interval == "manual") are
# untouched. The last dose profile per concentration group is also left
# untouched: its end-boundary point is a genuine terminal sample (the interval
# end is finite only because there is no next dose), not a next-dose C0.
if (isTRUE(drop_end_conc)) {
conc_groups <- intersect(group_vars(data$conc), names(data$intervals))
data$intervals <- data$intervals %>%
group_by(across(all_of(conc_groups))) %>%
mutate(
.is_last_main = type_interval == "main" &
start == suppressWarnings(max(start[type_interval == "main"])),
impute = ifelse(
type_interval == "main" & !.is_last_main,
ifelse(
is.na(impute) | impute == "",
"end_conc_drop",
paste0(impute, ", end_conc_drop")
),
impute
)
) %>%
ungroup() %>%
select(-.is_last_main)
}

data
}

Expand Down
1 change: 1 addition & 0 deletions R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
".dose_time",
".facet_label_values",
".facet_n",
".is_last_main",
".pp_excl",
".pp_excl_reason",
".ROWID",
Expand Down
11 changes: 1 addition & 10 deletions inst/WORDLIST
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ AEFRLT
AFRLT
ARRLT
ATPTREF
AUCIFOD
Comment thread
Shaakon35 marked this conversation as resolved.
AUCINT
AUCLSTD
AUCPEO
AUCPEP
AUCall
Expand All @@ -28,7 +26,6 @@ Bioavailability
Buckeridge
CDISC
CMAX
CMAXD
CRITy
CRITyFL
Clast
Expand Down Expand Up @@ -148,7 +145,6 @@ adnca
analysing
analyte
analytes
aucint
aucpext
aucs
bioavailability
Expand Down Expand Up @@ -176,6 +172,7 @@ frac
ggplot
ggplots
hardcoded
humanpred
ifelse
img
intravascular
Expand All @@ -187,15 +184,12 @@ logslope
mL
macroparameters
md
multidose
nav
nca
ng
normalised
oligo
pak
pc
pcspec
pharmacodynamics
pharmacokinetic
pharmacokinetics
Expand All @@ -204,20 +198,17 @@ pkgdown
pknca
plotly
pptest
pptestcd
pre
pred
px
qmd
rds
renderable
reproducibility
resizable
reupload
roadmap
rpptx
runnable
scrollable
selectable
signif
src
Expand Down
3 changes: 2 additions & 1 deletion inst/shiny/modules/tab_nca/nca_setup.R
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ nca_setup_server <- function(id, data, adnca_data, extra_group_vars, settings_ov
min_hl_points = settings()$min_hl_points,
parameter_selections = parameters_output$selections(),
int_parameters = settings()$int_parameters,
blq_imputation_rule = settings()$data_imputation$blq_imputation_rule
blq_imputation_rule = settings()$data_imputation$blq_imputation_rule,
drop_end_conc = settings()$data_imputation$drop_end_conc
)

# Wait for study types to settle during reactive transitions
Expand Down
44 changes: 44 additions & 0 deletions inst/shiny/modules/tab_nca/setup/data_imputation.R
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,44 @@ data_imputation_ui <- function(id) {
width = "500px"
)
)
),
hr(),
# Drop end-of-interval concentration widget and help button
fluidRow(
column(
width = 10,
input_switch(
id = ns("drop_end_conc"),
label = "Drop End Concentration",
value = FALSE
)
),
column(
width = 2,
dropdown(
div(
tags$h2("Drop End Concentration Help"),
p(
"Drops the concentration measured exactly at the end of each",
"interval before regular (non-partial) parameter calculations.",
"Only applies to main intervals; partial/interval parameters are",
"left untouched."
),
p(
"This is useful for multiple-dose data where the concentration at",
"the interval end really belongs to the next dose (e.g. an imputed",
"C0). Including it can distort parameters such as Cmax, Tmax and AUC;",
"genuine troughs are unaffected when the point does not sit exactly",
"at the interval end."
)
),
style = "unite",
right = TRUE,
icon = icon("question"),
status = "primary",
width = "500px"
)
)
)
)
}
Expand All @@ -149,6 +187,11 @@ data_imputation_server <- function(id, settings_override) {
update_switch("should_impute_c0", value = imputation$impute_c0)
}

# Restore drop_end_conc switch
if (!is.null(imputation$drop_end_conc)) {
update_switch("drop_end_conc", value = imputation$drop_end_conc)
}

# Restore BLQ strategy dropdown
valid_strategies <- c(
"Tmax based imputation",
Expand Down Expand Up @@ -249,6 +292,7 @@ data_imputation_server <- function(id, settings_override) {

list(
should_impute_c0 = reactive(input$should_impute_c0),
drop_end_conc = reactive(input$drop_end_conc),
blq_strategy = reactive(input$select_blq_strategy),
blq_imputation_rule = blq_imputation_rule
)
Expand Down
1 change: 1 addition & 0 deletions inst/shiny/modules/tab_nca/setup/settings.R
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ settings_server <- function(id, data, adnca_data, settings_override) {
min_hl_points = input$min_hl_points,
data_imputation = list(
impute_c0 = data_imputation$should_impute_c0(),
drop_end_conc = data_imputation$drop_end_conc(),
blq_strategy = data_imputation$blq_strategy(),
blq_imputation_rule = data_imputation$blq_imputation_rule()
),
Expand Down
1 change: 1 addition & 0 deletions inst/www/templates/clinical_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ settings:
method: lin up/log down
data_imputation:
impute_c0: yes
drop_end_conc: no
blq_strategy: No BLQ handling
blq_imputation_rule:
first: keep
Expand Down
1 change: 1 addition & 0 deletions inst/www/templates/preclinical_LM_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ settings:
bioavailability: f_aucinf.obs
data_imputation:
impute_c0: yes
drop_end_conc: no
blq_strategy: Set value for all BLQ
blq_imputation_rule:
first: drop
Expand Down
1 change: 1 addition & 0 deletions inst/www/templates/preclinical_SM_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ settings:
bioavailability: f_aucinf.obs
data_imputation:
impute_c0: yes
drop_end_conc: no
blq_strategy: Set value for all BLQ
blq_imputation_rule:
first: drop
Expand Down
1 change: 1 addition & 0 deletions inst/www/templates/script_template.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pknca_obj <- adnca_data %>%
selected_profile = settings_list$settings$profile,
selected_pcspec = settings_list$settings$pcspec,
start_impute = settings_list$settings$data_imputation$impute_c0,
drop_end_conc = settings_list$settings$data_imputation$drop_end_conc %||% FALSE,
exclusion_list = settings_list$settings$general_exclusions,
hl_adj_rules = slope_rules,
keep_interval_cols = setdiff(extra_vars_to_keep, c("DOSEA", "ATPTREF", "ROUTE")),
Expand Down
1 change: 1 addition & 0 deletions inst/www/templates/settings_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ settings:
bioavailability: f_aucinf.obs
data_imputation:
impute_c0: yes
drop_end_conc: no
blq_strategy: No BLQ handling
blq_imputation_rule:
first: keep
Expand Down
Loading
Loading