Skip to content

Commit 37a4c34

Browse files
committed
feat: add option to drop end-interval concentration for regular parameters
1 parent e1be854 commit 37a4c34

19 files changed

Lines changed: 308 additions & 6 deletions

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: aNCA
22
Title: (Pre-)Clinical NCA in a Dynamic Shiny App
3-
Version: 0.1.0.9185
3+
Version: 0.1.0.9186
44
Authors@R: c(
55
person("Ercan", "Suekuer", email = "ercan.suekuer@roche.com", role = "aut",
66
comment = c(ORCID = "0009-0001-1626-1526")),

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export(PKNCA_build_units_table)
1010
export(PKNCA_calculate_nca)
1111
export(PKNCA_create_data_object)
1212
export(PKNCA_hl_rules_exclusion)
13+
export(PKNCA_impute_method_end_conc_drop)
1314
export(PKNCA_impute_method_start_c1)
1415
export(PKNCA_impute_method_start_logslope)
1516
export(PKNCA_update_data_object)

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
* 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)
2626
* "Min. Points for Half-life" setting added (range 2–10, default 3) (#1155)
2727
* BLQ imputation rules via `NCA Setup > Data Imputation` (#139)
28+
* "Drop End Concentration" switch in `NCA Setup > Data Imputation` drops the concentration at the end of each main interval before regular parameter calculations (partial/interval parameters unaffected) (#TODO)
2829
* General Exclusions section for in-app NCA exclusions, with "Excl. TLG" checkbox per entry (#851, #1018)
2930
* Parameter Exclusions tab: exclude individual PK parameter rows from descriptive statistics and ADPP export via PPSUMFL/PPSUMRSN flags (#1040)
3031
* NCA flag rules (NCAwXRS) from ADNCA standards — flagged records are excluded from NCA (#752)

R/PKNCA.R

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ PKNCA_create_data_object <- function( # nolint: object_name_linter
283283
#' (forwarded to [update_main_intervals()]).
284284
#' @param blq_imputation_rule Optional list defining the BLQ imputation rule
285285
#' (forwarded to [update_main_intervals()]).
286+
#' @param drop_end_conc Logical indicating whether to drop the concentration at
287+
#' the end of each main interval for regular parameters (forwarded to
288+
#' [update_main_intervals()]). Default `FALSE`.
286289
#' @param custom_units_table Optional data frame with PPSTRESU overrides.
287290
#' When provided, applied via [dplyr::rows_update()] on the PKNCAdata units table.
288291
#'
@@ -308,6 +311,7 @@ PKNCA_update_data_object <- function( # nolint: object_name_linter
308311
parameter_selections = NULL,
309312
int_parameters = NULL,
310313
blq_imputation_rule = NULL,
314+
drop_end_conc = FALSE,
311315
custom_units_table = NULL) {
312316

313317
data <- adnca_data
@@ -371,7 +375,8 @@ PKNCA_update_data_object <- function( # nolint: object_name_linter
371375
parameter_selections = parameter_selections,
372376
int_parameters = int_parameters,
373377
impute = start_impute,
374-
blq_imputation_rule = blq_imputation_rule
378+
blq_imputation_rule = blq_imputation_rule,
379+
drop_end_conc = drop_end_conc
375380
)
376381

377382
# Apply custom units table
@@ -583,6 +588,45 @@ PKNCA_impute_method_start_c1 <- function(conc, time, start, end, ..., options =
583588
d_conc_time
584589
}
585590

591+
#' Drop the concentration measured exactly at the end of the interval
592+
#'
593+
#' Removes a concentration sitting exactly at `time == end` for an interval, if
594+
#' one is present (no-op otherwise). This is typically used with multiple-dose
595+
#' data where the boundary point belongs to the next dose (e.g. an imputed C0),
596+
#' so it should not contribute to parameters on the current interval.
597+
#'
598+
#' @param conc Numeric vector of concentrations.
599+
#' @param time Numeric vector of times corresponding to the concentrations.
600+
#' @param end Numeric value (or vector) indicating the end time of the interval.
601+
#' @param ... Additional arguments (currently not used).
602+
#' @param options List of options (currently not used).
603+
#'
604+
#' @returns A data frame of `conc`/`time` with any end-boundary point removed.
605+
#' @details
606+
#' This function adheres to the structure required by the `PKNCA` package to work
607+
#' with its imputation functionality. For more information, see the
608+
#' [PKNCA Data Imputation Vignette](https://CRAN.R-project.org/package=PKNCA).
609+
#'
610+
#' TODO(end_conc_drop): remove this local copy once humanpred/pknca#572 is merged
611+
#' and aNCA depends on a PKNCA release that exports
612+
#' `PKNCA_impute_method_end_conc_drop()`. At that point drop this definition and
613+
#' the corresponding `@export`/NAMESPACE entry and rely on the PKNCA-native method.
614+
#' @export
615+
#'
616+
#' @examples
617+
#' conc <- c(10, 5, 1)
618+
#' time <- c(0, 12, 24)
619+
#' end <- 24
620+
#' PKNCA_impute_method_end_conc_drop(conc, time, end)
621+
PKNCA_impute_method_end_conc_drop <- function(conc, time, end, ..., options = list()) { # nolint
622+
d_conc_time <- data.frame(conc = conc, time = time)
623+
mask_end <- time %in% end
624+
if (any(mask_end)) {
625+
d_conc_time <- d_conc_time[!mask_end, , drop = FALSE]
626+
}
627+
d_conc_time
628+
}
629+
586630
#' Build Units Table for PKNCA
587631
#'
588632
#' This function generates a PKNCA units table including the potential unit segregating columns

R/intervals.R

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ format_pkncadata_intervals <- function(pknca_conc,
206206
#' Each element can be a numeric value (substituting the BLQ value), or a string such as
207207
#' `"drop"` (ignores the value) or `"keep"` (keeps the value as 0). Default is NULL,
208208
#' which does not specify any BLQ imputation in any interval.
209+
#' @param drop_end_conc Logical. If `TRUE`, the concentration measured exactly at
210+
#' the end of each main interval is dropped before regular (non-partial) parameter
211+
#' calculations via the `end_conc_drop` imputation. This does not affect
212+
#' interval/partial parameter rows (`type_interval == "manual"`). Default `FALSE`.
209213
#'
210214
#' @importFrom dplyr left_join mutate across where select all_of if_else bind_rows filter
211215
#' @importFrom dplyr group_by ungroup slice_max distinct
@@ -217,7 +221,8 @@ update_main_intervals <- function(
217221
parameter_selections = NULL,
218222
int_parameters = NULL,
219223
impute = TRUE,
220-
blq_imputation_rule = NULL
224+
blq_imputation_rule = NULL,
225+
drop_end_conc = FALSE
221226
) {
222227

223228
if (is.null(parameter_selections)) parameter_selections <- list()
@@ -305,6 +310,24 @@ update_main_intervals <- function(
305310
)
306311
}
307312

313+
############################################
314+
# Drop the end-boundary concentration for regular parameters (main intervals
315+
# only). Partial/interval parameters (type_interval == "manual") are untouched.
316+
if (isTRUE(drop_end_conc)) {
317+
data$intervals <- data$intervals %>%
318+
mutate(
319+
impute = ifelse(
320+
type_interval == "main",
321+
ifelse(
322+
is.na(impute) | impute == "",
323+
"end_conc_drop",
324+
paste0(impute, ", end_conc_drop")
325+
),
326+
impute
327+
)
328+
)
329+
}
330+
308331
############################################
309332
# Remove any imputation from the observational parameters
310333
data <- rm_impute_obs_params(data, metadata_nca_parameters)

inst/shiny/modules/tab_nca/nca_setup.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ nca_setup_server <- function(id, data, adnca_data, extra_group_vars, settings_ov
134134
min_hl_points = settings()$min_hl_points,
135135
parameter_selections = parameters_output$selections(),
136136
int_parameters = settings()$int_parameters,
137-
blq_imputation_rule = settings()$data_imputation$blq_imputation_rule
137+
blq_imputation_rule = settings()$data_imputation$blq_imputation_rule,
138+
drop_end_conc = settings()$data_imputation$drop_end_conc
138139
)
139140

140141
# Wait for study types to settle during reactive transitions

inst/shiny/modules/tab_nca/setup/data_imputation.R

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,44 @@ data_imputation_ui <- function(id) {
128128
width = "500px"
129129
)
130130
)
131+
),
132+
hr(),
133+
# Drop end-of-interval concentration widget and help button
134+
fluidRow(
135+
column(
136+
width = 10,
137+
input_switch(
138+
id = ns("drop_end_conc"),
139+
label = "Drop End Concentration",
140+
value = FALSE
141+
)
142+
),
143+
column(
144+
width = 2,
145+
dropdown(
146+
div(
147+
tags$h2("Drop End Concentration Help"),
148+
p(
149+
"Drops the concentration measured exactly at the end of each",
150+
"interval before regular (non-partial) parameter calculations.",
151+
"Only applies to main intervals; partial/interval parameters are",
152+
"left untouched."
153+
),
154+
p(
155+
"This is useful for multiple-dose data where the concentration at",
156+
"the interval end really belongs to the next dose (e.g. an imputed",
157+
"C0). Including it can distort parameters such as Cmax, Tmax and AUC;",
158+
"genuine troughs are unaffected when the point does not sit exactly",
159+
"at the interval end."
160+
)
161+
),
162+
style = "unite",
163+
right = TRUE,
164+
icon = icon("question"),
165+
status = "primary",
166+
width = "500px"
167+
)
168+
)
131169
)
132170
)
133171
}
@@ -149,6 +187,11 @@ data_imputation_server <- function(id, settings_override) {
149187
update_switch("should_impute_c0", value = imputation$impute_c0)
150188
}
151189

190+
# Restore drop_end_conc switch
191+
if (!is.null(imputation$drop_end_conc)) {
192+
update_switch("drop_end_conc", value = imputation$drop_end_conc)
193+
}
194+
152195
# Restore BLQ strategy dropdown
153196
valid_strategies <- c(
154197
"Tmax based imputation",
@@ -249,6 +292,7 @@ data_imputation_server <- function(id, settings_override) {
249292

250293
list(
251294
should_impute_c0 = reactive(input$should_impute_c0),
295+
drop_end_conc = reactive(input$drop_end_conc),
252296
blq_strategy = reactive(input$select_blq_strategy),
253297
blq_imputation_rule = blq_imputation_rule
254298
)

inst/shiny/modules/tab_nca/setup/settings.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ settings_server <- function(id, data, adnca_data, settings_override) {
460460
min_hl_points = input$min_hl_points,
461461
data_imputation = list(
462462
impute_c0 = data_imputation$should_impute_c0(),
463+
drop_end_conc = data_imputation$drop_end_conc(),
463464
blq_strategy = data_imputation$blq_strategy(),
464465
blq_imputation_rule = data_imputation$blq_imputation_rule()
465466
),

inst/www/templates/clinical_template.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ settings:
22
method: lin up/log down
33
data_imputation:
44
impute_c0: yes
5+
drop_end_conc: no
56
blq_strategy: No BLQ handling
67
blq_imputation_rule:
78
first: keep

inst/www/templates/preclinical_LM_template.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ settings:
33
bioavailability: f_aucinf.obs
44
data_imputation:
55
impute_c0: yes
6+
drop_end_conc: no
67
blq_strategy: Set value for all BLQ
78
blq_imputation_rule:
89
first: drop

0 commit comments

Comments
 (0)