Skip to content

Commit

Permalink
Bug: AUC start 0 (which also needs Feature: C0 imputation) (#138)
Browse files Browse the repository at this point in the history
* bug: force doses times to be AFRLT.dose (at ARRLT = 0)

* data: correct PKROUTE -> ROUTE

* enhancement: create function to create impute_c0 column

* enhancement: include additional C0 imputation strategies

* feature: intervals include imputate strategy with duplicated rows apart for non-c0 parameters

* bug: PKNCAconc formula adapted for PKNCA to consider predoses for impute_predose

* bug: solved classification of doses in create_c0_impute

* bug: perfectionated formulas to consider different analytes appropiately

* style: solve most lintr issues

* refactor: delete report files that should not have been called

* refactor: nolint in customized PKNCA_impute_method functions

* wordlist: add PKNCA_impute_method functions

* documentation: functions in R/PKNCA_impute_method_additions.R

* feature: c0 input & when no checked use as interval start 1st observation

* bug: solved PKNCA warnings "No concentration data"

* bug: solved issue of duplicated tmax in results

* refactor: NCA results with all dose and conc columns first

* bug: fixed impute_method_start_c1 unneded argument issue

* refactor: delete unused functions in reshape

* refactor: input selectors for analyte and dosno put together in UI and renamed (select_X)

* refactor: change strategy for input of AUC intervals

* bug: fixed new intervals strategy and align with PKNCA running

* revert feat: back to old UI function for AUC intervals

* fix: interval default start since dose, aucint for manual intervals, adjust reshape for it

* fix: when C0 is not imputed, start is at C1

* lintr: code cleaning

* fix: issue in slope_selector with new name for input$cyclenca

* refactor: make own function to create intervals with dose data

* fix: adapt lambda_slope_plot to use type_interval column instead of end==Inf

* fix: adapt create_c0_impute_column to not use artificial time_dose column

* fix bug: correct call for mydata$dose instead of mydose

* fix: solve issues when C0 is not imputed to start at C1

* lintr: lint_dir cleaning

* fix oldrel: deleted line used for testing

* fix: update roxygen2 documentation for format_data.R functions

* fix: spellcheck added words to WORDLIST

* fix: roxygen2 for missing documetnation PKNCA_impute_method_additions.R

* fix: solved issue app crashes with auc rule sets

* fix: created pknca_trigger to run slope_selector when apply/save changes

* refactor: data selection tab with arranged dataset by subject

* aesthetics: add hovering message and new label in checkbox C0 imputations

* fix: lintr, roxygen doc and clast added to default params in NCA

* fix: reporting all parameters instead of just auc related for intervals

* documentation: roxygen update

* fix: delete partial_auc_input.R from R/ folder and leave in inst/shiny/functions

* fix: add tests and prevent input errors in format_data.R functions

* fix: issue with select_analyte after merge

* test: add tests for PKNCA_impute_method_additions.R and prevent NA in start_log

* refactor: create_c0_impute testing, column preventions and renaming (create_start_impute)

* fix: lintr code cleaning and roxygen documentation

* fix: update description and wordlist

* fix: impossible test deleted and improved results column order display

* style: add details to function description and rename PKNCA_impute_method_start_log(slope)

* style: time == start & link on PKNCA custom function guidelines

* test: modify tests from expect_s3_class to expect_no_error for nested functions

* style: delete unnecessary variable assignment in function

* documentation: update roxygen2

* fix: filtering later and using dose.time + arrlt for non-t0 solves partially problem

* data: corect ADOSEDUR (ADOSEDUR<0 turned into |ADOSEDUR|)

* data: adapt USUBJID=11102, DOSNO=9 to a reasonable dose time (AFRLT-ARRLT = 1680.5)

adnca2 %>% mutate(AFRLT = ifelse(DOSNO==9 & USUBJID==11102, AFRLT + 168, AFRLT),
NFRLT = ifelse(DOSNO==9 & USUBJID==11102, NFRLT + 168, NFRLT)
)

* fix: solve issue with end<start due to incorrect create_dose rows output

* refactor: lintr code cleaning

* style: apply suggestions from m-kolomanski

Co-authored-by: Mateusz Kołomański <[email protected]>

* style: drug_column call instead of hardcoded "DRUG" in create_start_impute.R

* style: lintr code cleaning

* style: improve conditional syntax in create_start_impute.R

* style issue: clean computation of pk.calc.c0 logslope

* style: suggestions from code review m-kolomanski

Co-authored-by: Mateusz Kołomański <[email protected]>

* nitpick: solve nitpicks pointed out by m-kolomanski

* refactor: rename reshape_PKNCA_results to pivot_wider_pknca_results

* refactor: change the names of format_data.R functions and update documentation

* fix: format_pkncadose_data includes either DOSNO or TIME (dose time) to slice data. route_column (unneeded argument) was removed

* refactor: lintr cleaning and roxygen2 documentation update

* spelling: update wordlist

* suggestions: nitpicks, returns m-kolomanski

Co-authored-by: Mateusz Kołomański <[email protected]>

* refactor: clarify with logical columns create_start_impute.R assignation

* issue: eliminate all redundant dplyr/tidyr namespacing

* issue: change base function to dplyr (base::merge > dplyr::inner_join)

* fix: use describe/it in tests PKNCA_impute_method_additions & create_start_impute

* nitpick, suggestion: nca.R add backlash and de-namespace mutate

Co-authored-by: Mateusz Kołomański <[email protected]>

* fix: filtering of dosno/analyte in displayed in `Data Selection` tab table

* fix: crash on slope_selector due to filtering results with NA lambda.z

* style: lintr clean code

* style: lintr code cleaning

* fix: remove redundant inst/WORDLIST.txt

---------

Co-authored-by: Mateusz Kołomański <[email protected]>
  • Loading branch information
Gero1999 and m-kolomanski authored Jan 17, 2025
1 parent 430c969 commit 64dc3dc
Show file tree
Hide file tree
Showing 25 changed files with 1,816 additions and 1,049 deletions.
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: aNCA
Title: (Pre-)clinical NCA in a dynamic shiny app
Title: (Pre-)Clinical NCA in a Dynamic Shiny App
Version: 0.0.0.9000
Authors@R: c(
person("Ercan", "Suekuer", , "[email protected]", role = c("aut", "cre"),
Expand Down Expand Up @@ -62,6 +62,7 @@ Imports:
tidyr,
tools,
utils,
rlang,
yaml,
zip
Encoding: UTF-8
Expand Down
13 changes: 9 additions & 4 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# Generated by roxygen2: do not edit by hand

export(PKNCA_impute_method_start_c1)
export(PKNCA_impute_method_start_logslope)
export(anonymize_pk_data)
export(apply_filters)
export(apply_labels)
export(as_factor_preserve_label)
export(calculate_summary_stats)
export(create_conc)
export(create_dose)
export(create_start_impute)
export(filter_breaks)
export(flexible_violinboxplot)
export(format_data)
export(format_pkncaconc_data)
export(format_pkncadata_intervals)
export(format_pkncadose_data)
export(g_pkconc_ind_lin)
export(g_pkconc_ind_log)
export(general_lineplot)
Expand All @@ -18,11 +21,11 @@ export(geometric_mean)
export(get_label)
export(has_label)
export(lambda_slope_plot)
export(pivot_wider_pknca_results)
export(parse_annotation)
export(parse_tlg_definitions)
export(pkcg01)
export(pptestcd_dict)
export(reshape_pknca_results)
export(run_app)
export(set_empty_label)
import(bslib)
Expand All @@ -43,6 +46,7 @@ importFrom(PKNCA,PKNCA.options)
importFrom(PKNCA,PKNCAconc)
importFrom(PKNCA,PKNCAdata)
importFrom(PKNCA,PKNCAdose)
importFrom(PKNCA,pk.calc.c0)
importFrom(PKNCA,pk.nca)
importFrom(PKNCA,pknca_units_table)
importFrom(checkmate,assert_numeric)
Expand Down Expand Up @@ -99,6 +103,7 @@ importFrom(reactable,renderReactable)
importFrom(reactable.extras,dropdown_extra)
importFrom(reactable.extras,text_extra)
importFrom(rio,export_list)
importFrom(rlang,sym)
importFrom(rmarkdown,render)
importFrom(scales,breaks_log)
importFrom(scales,label_log)
Expand Down
75 changes: 75 additions & 0 deletions R/PKNCA_impute_method_additions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#' This function imputes the start concentration using the log slope method.
#'
#' @param conc Numeric vector of concentrations.
#' @param time Numeric vector of times corresponding to the concentrations.
#' @param start Numeric value indicating the start/dose time.
#' @param end Numeric value indicating the end time.
#' @param ... Additional arguments (currently not used).
#' @param options List of options (currently not used).
#'
#' @returns A data frame with imputed start concentration.
#' @details
#' This function adheres to the structure required by the `PKNCA` package to work with its
#' functionalities. For more information, see the
#' [PKNCA Data Imputation Vignette](https://cran.r-project.org/web/packages/PKNCA/vignettes).
#' @export
#'
#' @examples
#' conc <- c(5, 4, 3, 2, 1)
#' time <- c(1, 2, 3, 4, 5)
#' start <- 0
#' end <- 4
#' PKNCA_impute_method_start_logslope(conc, time, start, end)

PKNCA_impute_method_start_logslope <- function(conc, time, start, end, ..., options = list()) { # nolint

d_conc_time <- data.frame(conc = conc, time = time)
if (!any(time == start)) {
all_concs <- conc[time >= start & time <= end]
all_times <- time[time >= start & time <= end]
if (!all(is.na(all_concs))) {
c0 <- PKNCA::pk.calc.c0(all_concs, all_times, method = "logslope")
if (!is.na(c0)) {
d_conc_time <- rbind(d_conc_time, data.frame(time = start, conc = c0))
d_conc_time <- d_conc_time[order(d_conc_time$time), ]
}
}
}
d_conc_time
}

#' This function imputes the start concentration using the first concentration after dose
#'
#' @param conc Numeric vector of concentrations.
#' @param time Numeric vector of times corresponding to the concentrations.
#' @param start Numeric value indicating the start/dose time.
#' @param end Numeric value indicating the end time.
#' @param ... Additional arguments (currently not used).
#' @param options List of options (currently not used).
#'
#' @returns A data frame with imputed start concentration.
#' @details
#' This function adheres to the structure required by the `PKNCA` package to work with its
#' functionalities.For more information, see the
#' [PKNCA Data Imputation Vignette](https://cran.r-project.org/web/packages/PKNCA/vignettes).
#' @export
#'
#' @examples
#' conc <- c(1, 2, 3, 4, 5)
#' time <- c(1, 2, 3, 4, 5)
#' start <- 0
#' end <- 4
#' PKNCA_impute_method_start_c1(conc, time, start, end)
PKNCA_impute_method_start_c1 <- function(conc, time, start, end, ..., options = list()) { # nolint
d_conc_time <- data.frame(conc = conc, time = time)
if (!any(time == start)) {
all_concs <- conc[time >= start & time <= end]
all_times <- time[time >= start & time <= end]
if (!all(is.na(all_concs))) {
c1 <- all_concs[which.min(all_times)]
d_conc_time <- rbind(d_conc_time, data.frame(time = start, conc = c1))
d_conc_time <- d_conc_time[order(d_conc_time$time), ]
}
}
d_conc_time
}
101 changes: 101 additions & 0 deletions R/create_start_impute.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#' Create C0 Impute Column
#'
#' Defines an impute column in the intervals of the PKNCAdata object based on data
#'
#' @param mydata A PKNCAdata object containing concentration and dose data.
#' @returns A PKNCAdata object with updated intervals table including start imputation strategies.
#' @import dplyr
#' @importFrom rlang sym
#' @importFrom PKNCA pk.calc.c0
#' @export
#'
#' @examples
#' \dontrun{
#' mydata <- create_start_impute(mydata)
#' }
create_start_impute <- function(mydata) {

# Define columns
conc_column <- mydata$conc$columns$conc
time_column <- mydata$conc$columns$time
analyte_column <- mydata$conc$columns$groups$group_analyte
route_column <- mydata$dose$columns$route
duration_column <- mydata$dose$columns$duration
drug_column <- "DRUG" # TODO: At some point should be mapped manually in the App
conc_group_columns <- unname(unlist(mydata$conc$columns$groups))
dose_group_columns <- unname(unlist(mydata$dose$columns$groups))
group_columns <- unique(c(conc_group_columns, dose_group_columns))

# Define dose number (DOSNO) if not present in dose data
if (!"DOSNO" %in% mydata$dose$data) {
mydata$dose$data <- mydata$dose$data %>%
group_by(across(all_of(dose_group_columns))) %>%
mutate(DOSNO = row_number()) %>%
ungroup()
}

mydata_with_int <- merge(
x = mydata$conc$data %>%
select(any_of(c(conc_group_columns, conc_column, time_column))),
y = mydata$dose$data %>%
select(any_of(c(dose_group_columns, route_column,
duration_column, "DOSNO", "DRUG")))
) %>%
merge(mydata$intervals)

# Define dosing drug as analyte if not present
if (!drug_column %in% colnames(mydata_with_int)) {
if (analyte_column %in% colnames(mydata_with_int)) {
drug_column <- analyte_column
} else {
mydata_with_int <- mutate(mydata_with_int,
ANALYTE = "A")
analyte_column <- "ANALYTE"
drug_column <- analyte_column
}
}

# Process imputation strategy based on each interval
mydata$intervals <- mydata_with_int %>%
group_by(across(all_of(c(group_columns, "DOSNO", "start", "end")))) %>%
arrange(across(all_of(c(group_columns, time_column)))) %>%
mutate(
is.first.dose = DOSNO == 1,
is.ivbolus = tolower(!!sym(route_column)) == "intravascular" & !!sym(duration_column) == 0,
is.analyte.drug = !!sym(analyte_column) == !!sym(drug_column),
is.possible.c0.logslope = !is.na(pk.calc.c0(conc = !!sym(conc_column),
time = !!sym(time_column),
time.dose = start[1],
method = "logslope"))
) %>%
arrange(
(!!sym(time_column) - start) < 0,
(!!sym(time_column) - start)
) %>%
slice(1) %>%
ungroup() %>%
rowwise() %>%
mutate(
impute = case_when(
# Start concentration already present: No imputation (NA)
!!sym(time_column) == start & !is.na(!!sym(conc_column)) ~ NA,

# 1st dose with not IV bolus or analyte =! drug : Start concentration is 0
is.first.dose & (!is.ivbolus | !is.analyte.drug) ~ "start_conc0",

# Posterior doses not IV bolus or analyte =! drug : Start concentration shifts to predose
!is.first.dose & (!is.ivbolus | !is.analyte.drug) ~ "start_predose",

# IV bolus with analyte = drug : Start concentration is log-backextrapolated (if possible)
is.ivbolus & is.analyte.drug & is.possible.c0.logslope ~ "start_logslope",

# IV bolus with analyte = drug and not possible logslope: Start concentration is 1st conc
is.ivbolus & is.analyte.drug ~ "start_c1"
)
) %>%
# Select only the columns of interest
select(any_of(c(names(mydata$intervals), "impute")))

mydata

}
Loading

0 comments on commit 64dc3dc

Please sign in to comment.