Nothing
#'@import rhandsontable
#'@import dplyr
#'@import tidyr
#'@import tidyr
#'@import formods
#'@import shiny
#'@importFrom digest digest
#'@importFrom rlang :=
#'@importFrom shinyAce aceEditor updateAceEditor
#'@importFrom stringr str_replace str_detect str_split
#'@importFrom utils head
#'@export
#'@title Fetch Non-Compartmental Analysis State
#'@description Merges default app options with the changes made in the UI
#'@param id An ID string that corresponds with the ID used to call the modules UI elements
#'@param FM_yaml_file App configuration file with FM as main section.
#'@param MOD_yaml_file Module configuration file with MC as main section.
#'@param id_ASM ID string for the app state management module used to save and load app states
#'@param id_UD ID string for the upload data module used to save and load app states
#'@param id_DW ID string for the data wrangling module used to save and load app states
#'@param deployed Boolean variable indicating whether the app is deployed or not.
#'@param react_state Variable passed to server to allow reaction outside of module (\code{NULL})
#'@return list containing the current state of the app including default
#'values from the yaml file as well as any changes made by the user. The list
#'has the following structure:
#' \itemize{
#' \item{yaml:} Full contents of the supplied yaml file.
#' \item{MC:} Module components of the yaml file.
#' \item{NCA:}
#' \itemize{
#' \item{isgood:} Boolean object indicating if the file was successfully loaded.
#' \item{checksum:} This is an MD5 sum of the contents element and can be
#' used to detect changes in the state.
#' }
#' \item{MOD_TYPE:} Character data containing the type of module \code{"NCA"}
#' \item{id:} Character data containing the module id module in the session variable.
#' \item{FM_yaml_file:} App configuration file with FM as main section.
#' \item{MOD_yaml_file:} Module configuration file with MC as main section.
#'}
#'@example inst/test_apps/nca_app.R
NCA_Server <- function(id,
FM_yaml_file = system.file(package = "formods", "templates", "formods.yaml"),
MOD_yaml_file = system.file(package = "ruminate", "templates", "NCA.yaml"),
id_ASM = "ASM",
id_UD = "UD",
id_DW = "DW",
deployed = FALSE,
react_state = NULL) {
moduleServer(id, function(input, output, session) {
#------------------------------------
# Generated data reading code
observe({
# Reacting to file changes
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
input[["button_fg_ind_obs_save"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
if(is.null(current_ana[["code_sa"]])){
uiele = "# Run analysis to see code."
} else {
uiele = paste0(current_ana[["code_sa"]], collapse="\n")
}
shinyAce::updateAceEditor(
session = session,
editorId = "ui_nca_code",
theme = state[["yaml"]][["FM"]][["code"]][["theme"]],
showLineNumbers = state[["yaml"]][["FM"]][["code"]][["showLineNumbers"]],
readOnly = state[["MC"]][["code"]][["readOnly"]],
mode = state[["MC"]][["code"]][["mode"]],
value = uiele)
})
#------------------------------------
# User messages:
output$ui_nca_msg = renderText({
input[["button_ana_add_int"]]
input[["button_ana_use_scenario"]]
input[["button_fg_ind_obs_save"]]
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
input[["switch_ana_fig"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = state[["NCA"]][["ui_msg"]]
uiele})
#------------------------------------
# Side buttons:
# new
output$ui_nca_new_ana = renderUI({
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = shinyWidgets::actionBttn(
inputId = NS(id, "button_ana_new"),
label = state[["MC"]][["labels"]][["new_ana"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_ana_new"]][["size"]],
block = state[["MC"]][["formatting"]][["button_ana_new"]][["block"]],
color = "success",
icon = icon("plus"))
# Optinally adding the tooltip:
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["button_ana_new"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["button_ana_new"]][["tooltip_position"]])
uiele})
#------------------------------------
# save
output$ui_nca_save_ana = renderUI({
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = shinyWidgets::actionBttn(
inputId = NS(id, "button_ana_save"),
label = state[["MC"]][["labels"]][["save_ana"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_ana_save"]][["size"]],
block = state[["MC"]][["formatting"]][["button_ana_save"]][["block"]],
color = "primary",
icon = icon("arrow-down"))
# Optinally adding the tooltip:
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["button_ana_save"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["button_ana_save"]][["tooltip_position"]])
uiele})
#------------------------------------
# clip code
output$ui_nca_clip_code = renderUI({
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = NULL
if((system.file(package="clipr") != "") & !deployed){
uiele = shinyWidgets::actionBttn(
inputId = NS(id, "button_ana_clip"),
label = state[["MC"]][["labels"]][["clip_ana"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_ana_clip"]][["size"]],
block = state[["MC"]][["formatting"]][["button_ana_clip"]][["block"]],
color = "royal",
icon = icon("clipboard", lib="font-awesome"))
# Optinally adding the tooltip:
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["button_ana_clip"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["button_ana_clip"]][["tooltip_position"]])
}
uiele})
#------------------------------------
# delete
output$ui_nca_del_ana = renderUI({
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = shinyWidgets::actionBttn(
inputId = NS(id, "button_ana_del"),
label = state[["MC"]][["labels"]][["del_ana"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_ana_del"]][["size"]],
block = state[["MC"]][["formatting"]][["button_ana_del"]][["block"]],
color = "danger",
icon = icon("minus"))
# Optinally adding the tooltip:
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["button_ana_del"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["button_ana_del"]][["tooltip_position"]])
uiele})
#------------------------------------
# copy
output$ui_nca_copy_ana = renderUI({
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = shinyWidgets::actionBttn(
inputId = NS(id, "button_ana_copy"),
label = state[["MC"]][["labels"]][["copy_ana"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_ana_copy"]][["size"]],
block = state[["MC"]][["formatting"]][["button_ana_copy"]][["block"]],
color = "royal",
icon = icon("copy"))
# Optinally adding the tooltip:
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["button_ana_copy"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["button_ana_copy"]][["tooltip_position"]])
uiele})
#------------------------------------
# Captions
# name
output$ui_nca_ana_name = renderUI({
#react_state[[id_UD]]
#react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
value = current_ana[["key"]]
uiele = textInput(inputId = NS(id, "text_ana_key"),
label = NULL,
value = value,
placeholder = state[["MC"]][["tooltips"]][["ph"]][["ana_key"]])
uiele})
#------------------------------------
# notes
output$ui_nca_ana_notes = renderUI({
#react_state[[id_UD]]
#react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
value = current_ana[["notes"]]
uiele = textAreaInput(inputId = NS(id, "text_ana_notes"),
width = state[["MC"]][["formatting"]][["notes"]][["width"]],
height = state[["MC"]][["formatting"]][["notes"]][["height"]],
label = NULL,
value = value,
placeholder = state[["MC"]][["tooltips"]][["ph"]][["notes"]])
uiele})
#------------------------------------
output$ui_nca_curr_anas = renderUI({
#react_state[[id_UD]]
#react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
if(is.null(names(state[["NCA"]][["anas"]]))){
uiele = tags$em(state[["MC"]][["labels"]][["curr_anas_none"]])
} else {
# This is the current analysis ID
current_ana_id = state[["NCA"]][["current_ana"]]
choices = c()
cnames = c()
subtext = c()
for(ana_id in names(state[["NCA"]][["anas"]])){
tmp_ana = state[["NCA"]][["anas"]][[ana_id]]
# Creating the select subtext from the caption
if(is.null(tmp_ana[["notes"]])){
subtext = c(subtext, "")
} else {
subtext = c(subtext, strtrim(tmp_ana[["notes"]], 20))
}
choices = c(choices, ana_id)
cnames = c(cnames, tmp_ana[["key"]])
}
choicesOpt = list( subtext = subtext)
names(choices) = cnames
uiele =
shinyWidgets::pickerInput(
selected = current_ana_id,
inputId = NS(id, "select_current_ana"),
label = state[["MC"]][["labels"]][["select_current_ana"]],
choices = choices,
width = state[["MC"]][["formatting"]][["select_current_ana"]][["width"]],
choicesOpt = choicesOpt)
}
uiele})
# Data Sources
output$ui_nca_curr_views = renderUI({
#react_state[[id_UD]]
#react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
if(!is.null(state[["MC"]][["tooltips"]][["url_data"]])){
data_link = icon_link(href=state[["MC"]][["tooltips"]][["url_data"]])
}else{
data_link = NULL
}
# This creates the selection but it is updated in the observe() below
choicesOpt = NULL
uiele =
shinyWidgets::pickerInput(
selected = "PH",
inputId = NS(id, "select_current_view"),
#label = state[["MC"]][["labels"]][["select_current_view"]],
label = tagList(state[["MC"]][["labels"]][["select_current_view"]], data_link),
choices = c("PH"),
width = state[["MC"]][["formatting"]][["select_current_view"]][["width"]],
choicesOpt = choicesOpt)
uiele})
#------------------------------------
# This forces the dataset view selection to update
observe({
input$button_ana_new
input$button_ana_save
input$button_ana_copy
input$button_ana_del
input$select_current_ana
#req(input$select_current_view)
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
# Forcing a reaction to changes in other modules
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
if(state[["NCA"]][["isgood"]]){
# If this is triggered before datasets have been loaded the state will
# be bad:
# Pulling out the data set views catalog
ds_catalog = state[["NCA"]][["DSV"]][["catalog"]]
if(current_ana[["ana_dsview"]] %in% ds_catalog[["object"]]){
current_view_id= current_ana[["ana_dsview"]]
} else {
current_view_id = ds_catalog[["object"]][1]
formods::FM_le(state, paste0("ui_nca_curr_views: dataset view missing." ))
formods::FM_le(state, paste0("ana_key: ", current_ana[["key"]] ))
formods::FM_le(state, paste0("ana_dsview: ", current_ana[["ana_dsview"]]))
formods::FM_le(state, paste0("switching to view:", current_view_id ))
}
choices = ds_catalog[["object"]]
names(choices) = ds_catalog[["label"]]
choicesOpt = NULL
shinyWidgets::updatePickerInput(
session = session,
selected = current_view_id,
inputId = "select_current_view",
choices = choices,
choicesOpt = choicesOpt)
}
})
#------------------------------------
# interval range
output$ui_nca_ana_int_range = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
# We need the time column defined to use this element
req(input[["select_ana_col_time"]])
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
# Pulling out the current analysis to get the column information
uiele = NULL
current_ana = NCA_fetch_current_ana(state)
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
value_start = current_ana[["interval_range"]][1]
value_stop = current_ana[["interval_range"]][2]
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# This is all the times in the dataset:
time_choices = unique(sort(ds[["DS"]][[current_ana[["col_time"]] ]]))
# Now we need to convert it to text and add infinity as an option
time_choices = c(as.character(time_choices), "Inf")
# Now we're going figure out if the interval in the current analysis
# exists in the current choices:
if((value_start %in% time_choices)){
idx_start = which(value_start == time_choices)
} else {
idx_start = 1
}
if((value_stop %in% time_choices)){
idx_stop = which(value_stop == time_choices)
} else {
idx_stop = length(time_choices)
}
uiele =
shinyWidgets::sliderTextInput(
inputId = NS(id, "select_ana_interval_range"),
label = state[["MC"]][["labels"]][["select_ana_interval_range"]],
width = state[["MC"]][["formatting"]][["select_ana_interval_range"]][["width"]],
choices = time_choices,
selected = time_choices[c(idx_start, idx_stop)]
)
}
}
uiele})
#------------------------------------
# NCA parameters to compute
output$ui_nca_ana_params = renderUI({
input$button_ana_use_scenario
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
# Currently selected parameters:
value = current_ana[["nca_parameters"]]
# Choice list
choices = state[["NCA"]][["nca_parameters"]][["choices"]]
if(!is.null(state[["MC"]][["tooltips"]][["url_parameters"]])){
parameters_link = icon_link(href=state[["MC"]][["tooltips"]][["url_parameters"]])
}else{
parameters_link = NULL
}
picker_options = do.call(shinyWidgets::pickerOptions,
state[["MC"]][["formatting"]][["select_ana_nca_parameters"]][["picker_options"]])
picker_options[["size"]] = state[["yaml"]][["FM"]][["ui"]][["select_size"]]
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_nca_parameters"),
choices = choices,
label = tagList(state[["MC"]][["labels"]][["select_ana_nca_parameters"]], parameters_link),
selected = value,
multiple = TRUE,
width = state[["MC"]][["formatting"]][["select_ana_nca_parameters"]][["width"]],
options = picker_options,
inline = TRUE)
uiele})
#------------------------------------
# Data source sampling (sparse or serail)
output$ui_nca_ana_source_sampling = renderUI({
input$button_ana_use_scenario
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
value = current_ana[["sampling"]]
choices = list("Serial"="serial", "Sparse"="sparse")
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_source_sampling"),
choices = choices,
label = state[["MC"]][["labels"]][["select_ana_source_sampling"]],
selected = value,
width = state[["MC"]][["formatting"]][["select_ana_source_sampling"]][["width"]],
inline = TRUE)
uiele})
#------------------------------------
# Data source sampling (sparse or serail)
output$ui_nca_ana_run = renderUI({
input$button_ana_use_scenario
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = shinyWidgets::actionBttn(
inputId = NS(id, "button_ana_run"),
label = state[["MC"]][["labels"]][["run_ana"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_ana_run"]][["size"]],
block = state[["MC"]][["formatting"]][["button_ana_run"]][["block"]],
color = "primary",
icon = icon("arrow-down"))
uiele})
#------------------------------------
# Figure Results
output$ui_nca_ana_results_fig = renderUI({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
uiele = tagList(
htmlOutput( NS(id, "ui_nca_ana_results_fig_general")),
htmlOutput( NS(id, "ui_nca_ana_results_fig_controls")),
htmlOutput( NS(id, "ui_nca_ana_results_fig_plot")))
uiele})
#------------------------------------
# Table Results (show table)
output$ui_nca_ana_results_tab_table = renderUI({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
input[["switch_ana_tab"]]
# Update on save
input[["button_tb_ind_obs_save"]]
input[["button_tb_ind_params_save"]]
input[["button_tb_sum_params_save"]]
# Don't build out the table until the tab_view has been created
req(input[["select_ana_tab_view"]])
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
if(current_ana[["isgood"]]){
fobj = NCA_fetch_current_obj(state, "table")
#pvw = state[["MC"]][["formatting"]][["preview"]][["width"]]
#pvh = state[["MC"]][["formatting"]][["preview"]][["height"]]
#pv_div_style = paste0("height:",pvh,";width:",pvw,";display:inline-block;vertical-align:top")
# If we fetched everything then we return the table
if(fobj[["isgood"]]){
if(current_ana[["tab_type"]] == "report"){
uiele = flextable::htmltools_value(fobj[["ft"]])
} else {
uiele = DT::DTOutput(NS(id, "ui_nca_ana_results_tab_table_dt"))
}
} else {
# Otherwise we return messages to the user
uiele = fobj[["msgs"]]
}
}
uiele})
#------------------------------------
# Table Results (show table data table DT output)
output$ui_nca_ana_results_tab_table_dt = DT::renderDT({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
input[["switch_ana_tab"]]
# Update on save
input[["button_tb_ind_obs_save"]]
input[["button_tb_ind_params_save"]]
input[["button_tb_sum_params_save"]]
# Don't build out the table until the tab_view has been created
req(input[["select_ana_tab_view"]])
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
if(current_ana[["isgood"]]){
fobj = NCA_fetch_current_obj(state, "table")
uiele = fobj[["df"]]
}
uiele}, options=list(pageLength=100,
lengthMenu = c(25, 50, 100)) )
#------------------------------------
# Figure Results (show plot)
output$ui_nca_ana_results_fig_plot = renderUI({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
input[["switch_ana_fig"]]
input[["button_fg_ind_obs_save"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
# pvh = state[["MC"]][["formatting"]][["preview"]][["height"]]
# pvw = state[["MC"]][["formatting"]][["preview"]][["width"]]
# pv_div_style = paste0("height:",pvh,"px;width:",pvw,"px;display:inline-block;vertical-align:top")
pvw = state[["MC"]][["formatting"]][["preview"]][["width"]]
pvh = state[["MC"]][["formatting"]][["preview"]][["height"]]
pv_div_style = paste0("height:",pvh,";width:",pvw,";display:inline-block;vertical-align:top")
if(current_ana[["fig_type"]] == "interactive"){
uiele = tagList(
div(style=pv_div_style, plotly::plotlyOutput(NS(id, "ui_nca_ana_results_fig_plotly"), width=pvw, height=pvh)))
} else {
uiele = tagList(
div(style=pv_div_style, plotOutput( NS(id, "ui_nca_ana_results_fig_ggplot"), width=pvw, height=pvh)))
}
uiele})
#------------------------------------
# Figure Results (select figure)
output$ui_nca_ana_results_fig_general = renderUI({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# We only generate the ui element if the
# analysis is in a good state
if(current_ana[["isgood"]]){
choices = c()
cnames = c()
subtext = c()
for(fig_id in names(state[["MC"]][["figures"]])){
choices = c(choices, fig_id)
cnames = c(cnames, state[["MC"]][["figures"]][[fig_id]][["choice"]])
subtext = c(subtext, state[["MC"]][["figures"]][[fig_id]][["subtext"]])
}
# Applying names
names(choices) = cnames
# Adding the subtext
choicesOpt = list(
subtext = subtext)
# If the current_ana figure view exists we default to that
# otherwise we just choose the first choice.
if(current_ana[["fig_view"]] %in% choices){
selected = current_ana[["fig_view"]]
} else {
selected = choices[1]
}
uiele_picker = shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_fig_view"),
choices = choices,
selected = selected,
width = state[["MC"]][["formatting"]][["select_ana_fig_view"]][["width"]],
inline = TRUE,
choicesOpt = choicesOpt)
choiceValues = c("report", "interactive")
choiceNames = c(state[["MC"]][["labels"]][["switch_ana_fig_report"]],
state[["MC"]][["labels"]][["switch_ana_fig_interactive"]])
uiele_switch =
shinyWidgets::radioGroupButtons(
inputId = NS(id, "switch_ana_fig"),
label = state[["MC"]][["labels"]][["switch_ana_fig"]],
selected = current_ana[["fig_type"]],
choiceValues = choiceValues,
choiceNames = choiceNames ,
status = "primary")
pv_div_style = paste0("display:inline-block") #;vertical-align:top")
uiele = tagList(div(style=pv_div_style, uiele_picker),
div(style=pv_div_style, uiele_switch))
} else {
uiele = state[["MC"]][["errors"]][["nca_no_fig"]]
}
uiele})
#------------------------------------
# Figure Results ggplot
output$ui_nca_ana_results_fig_ggplot = renderPlot({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
input[["switch_ana_fig"]]
input[["button_fg_ind_obs_save"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# We only return a non-NULL result if the current analysis is good
# This should only be called if an interactive as _not_ been selected
# so we just need to return the ggplot object.
if(current_ana[["isgood"]]){
# Pulling out the current figure
fobj = NCA_fetch_current_obj(state, "figure")
if(!is.null(fobj)){
uiele = fobj[["ggplot"]]
}
}
uiele})
#------------------------------------
# Figure Results plotly
output$ui_nca_ana_results_fig_plotly = plotly::renderPlotly({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
input[["switch_ana_fig"]]
input[["button_fg_ind_obs_save"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# We only return a non-NULL result if the current analysis is good
# and this should only be called if an interactive figure has been
# selected. For that we need the ggplotly output of the ggplot object:
if(current_ana[["isgood"]]){
fobj = NCA_fetch_current_obj(state, "figure")
if(!is.null(fobj)){
uiele = plotly::ggplotly(fobj[["ggplot"]])
}
}
uiele})
#------------------------------------
# Figure Results (plot controls)
output$ui_nca_ana_results_fig_controls = renderUI({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
input[["switch_ana_fig"]]
# This is dependent on the figure view so
# shouldn't build out until that.
req(input[["select_ana_fig_view"]])
#input[["button_fg_ind_obs_save"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = NULL
current_ana = NCA_fetch_current_ana(state)
# If the current analysis state is bad then we return NULL and wait for
# the user to fix it.
if(current_ana[["isgood"]]){
if(current_ana[["fig_view"]] == "fg_ind_obs"){
uiele_save =
shinyWidgets::actionBttn(
inputId = NS(id, "button_fg_ind_obs_save"),
label = state[["MC"]][["labels"]][["fg_save"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_fg_save"]][["size"]],
block = state[["MC"]][["formatting"]][["button_fg_save"]][["block"]],
color = "primary",
icon = icon("arrow-down"))
uiele_nrow =
shinyWidgets::pickerInput(
inputId = NS(id, "select_fg_ind_obs_nrow"),
choices = state[["MC"]][["formatting"]][["preview"]][["nrow_opt"]],
label = state[["MC"]][["labels"]][["select_fg_ind_obs_nrow"]],
selected = current_ana[["fg_ind_obs_nrow"]],
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
width = state[["MC"]][["formatting"]][["select_fg_ind_obs_nrow"]][["width"]],
)
uiele_ncol =
shinyWidgets::pickerInput(
inputId = NS(id, "select_fg_ind_obs_ncol"),
choices = state[["MC"]][["formatting"]][["preview"]][["ncol_opt"]],
label = state[["MC"]][["labels"]][["select_fg_ind_obs_ncol"]],
selected = current_ana[["fg_ind_obs_ncol"]],
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
width = state[["MC"]][["formatting"]][["select_fg_ind_obs_ncol"]][["width"]]
)
uiele_page = htmlOutput(NS(id, "ui_nca_ana_results_fig_pages"))
uiele_logy = shinyWidgets::awesomeCheckbox(
inputId = NS(id, "check_fg_ind_obs_logy"),
label = state[["MC"]][["labels"]][["check_fg_ind_obs_logy"]],
width = state[["MC"]][["formatting"]][["check_fg_ind_obs"]][["width"]],
value = current_ana[["fg_ind_obs_logy"]])
dvstyle = "display:inline-block"
uiele = tagList(div(style=dvstyle, uiele_save),
div(style=dvstyle, uiele_nrow),
div(style=dvstyle, uiele_ncol),
div(style=dvstyle, uiele_logy),
div(style=dvstyle, uiele_page))
}
}
uiele})
#------------------------------------
# Table page ui element
output$ui_nca_ana_results_tab_pages = renderUI({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
# This is dependent on the table view so
# shouldn't build out until that.
req(input[["select_ana_tab_view"]])
input[["button_tb_ind_obs_save"]]
input[["button_tb_ind_params_save"]]
input[["button_tb_sum_params_save"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = NULL
current_ana = NCA_fetch_current_ana(state)
# JMH here: Generalize for all tables and add
# - tb_ind_params
# - tb_sum_params
if(current_ana[["isgood"]]){
if(current_ana[["tab_view"]] == "tb_ind_obs"){
page_values = names(current_ana[["objs"]][["tb_ind_obs"]][["value"]][["tables"]])
if(current_ana[["curr_tb_ind_obs"]] %in% page_values){
selected_page = current_ana[["curr_tb_ind_obs"]]
} else {
selected_page = page_values[1]
}
names(page_values) = 1:length(page_values)
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_tb_ind_obs_page"),
choices = page_values,
label = state[["MC"]][["labels"]][["select_tb_page"]],
selected = selected_page,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
width = state[["MC"]][["formatting"]][["select_tb_page"]][["width"]]
)
}
if(current_ana[["tab_view"]] == "tb_ind_params"){
page_values = names(current_ana[["objs"]][["tb_ind_params"]][["value"]][["tables"]])
if(current_ana[["curr_tb_ind_params"]] %in% page_values){
selected_page = current_ana[["curr_tb_ind_params"]]
} else {
selected_page = page_values[1]
}
names(page_values) = 1:length(page_values)
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_tb_ind_params_page"),
choices = page_values,
label = state[["MC"]][["labels"]][["select_tb_page"]],
selected = selected_page,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
width = state[["MC"]][["formatting"]][["select_tb_page"]][["width"]]
)
}
if(current_ana[["tab_view"]] == "tb_sum_params"){
}
}
uiele})
#------------------------------------
# Figure page ui element
output$ui_nca_ana_results_fig_pages = renderUI({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
input[["switch_ana_fig"]]
# This is dependent on the figure view so
# shouldn't build out until that.
req(input[["select_ana_fig_view"]])
input[["button_fg_ind_obs_save"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = NULL
current_ana = NCA_fetch_current_ana(state)
if(current_ana[["isgood"]]){
page_values = names(current_ana[["objs"]][["fg_ind_obs"]][["value"]][["figures"]])
if(current_ana[["curr_fg_ind_obs"]] %in% page_values){
selected_page = current_ana[["curr_fg_ind_obs"]]
} else {
selected_page = page_values[1]
}
names(page_values) = 1:length(page_values)
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_fg_ind_obs_page"),
choices = page_values,
label = state[["MC"]][["labels"]][["select_fg_ind_obs_page"]],
selected = selected_page,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
width = state[["MC"]][["formatting"]][["select_fg_ind_obs_page"]][["width"]]
)
}
uiele})
#------------------------------------
# Tabular Results
output$ui_nca_ana_results_tab = renderUI({
input$button_ana_run
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = tagList(
htmlOutput(NS(id, "ui_nca_ana_results_tab_general")),
htmlOutput(NS(id, "ui_nca_ana_results_tab_controls")),
htmlOutput(NS(id, "ui_nca_ana_results_tab_table"))
)
uiele})
#------------------------------------
# Table Results (table controls)
output$ui_nca_ana_results_tab_controls = renderUI({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
# This is dependent on the table view so
# shouldn't build out until that.
req(input[["select_ana_tab_view"]])
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = NULL
current_ana = NCA_fetch_current_ana(state)
# this is the common ui to select pages that's used below
uiele_page = htmlOutput(NS(id, "ui_nca_ana_results_tab_pages"))
# If the current analysis state is bad then we return NULL and wait for
# the user to fix it.
if(current_ana[["isgood"]]){
if(current_ana[["tab_view"]] == "tb_ind_obs"){
uiele_save =
shinyWidgets::actionBttn(
inputId = NS(id, "button_tb_ind_obs_save"),
label = state[["MC"]][["labels"]][["tb_save"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_tb_save"]][["size"]],
block = state[["MC"]][["formatting"]][["button_tb_save"]][["block"]],
color = "primary",
icon = icon("arrow-down"))
dvstyle = "display:inline-block"
uiele = tagList(div(style=dvstyle, uiele_save),
div(style=dvstyle, uiele_page))
}
if(current_ana[["tab_view"]] == "tb_nca_raw"){
# Currently there are no controls for the raw NCA output
}
if(current_ana[["tab_view"]] == "tb_ind_params"){
uiele_save =
shinyWidgets::actionBttn(
inputId = NS(id, "button_tb_ind_params_save"),
label = state[["MC"]][["labels"]][["tb_save"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_tb_save"]][["size"]],
block = state[["MC"]][["formatting"]][["button_tb_save"]][["block"]],
color = "primary",
icon = icon("arrow-down"))
dvstyle = "display:inline-block"
uiele = tagList(div(style=dvstyle, uiele_save),
div(style=dvstyle, uiele_page))
}
if(current_ana[["tab_view"]] == "tb_sum_params"){
# JMH add controls
uiele_save =
shinyWidgets::actionBttn(
inputId = NS(id, "button_tb_sum_params_save"),
label = state[["MC"]][["labels"]][["tb_save"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_tb_save"]][["size"]],
block = state[["MC"]][["formatting"]][["button_tb_save"]][["block"]],
color = "primary",
icon = icon("arrow-down"))
dvstyle = "display:inline-block"
uiele = tagList(div(style=dvstyle, uiele_save),
div(style=dvstyle, uiele_page))
}
}
uiele})
#------------------------------------
# Table Results (select table)
output$ui_nca_ana_results_tab_general = renderUI({
input[["button_ana_run"]]
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# We only generate the ui element if the
# analysis is in a good state
if(current_ana[["isgood"]]){
choices = c()
cnames = c()
subtext = c()
for(fig_id in names(state[["MC"]][["tables"]])){
choices = c(choices, fig_id)
cnames = c(cnames, state[["MC"]][["tables"]][[fig_id]][["choice"]])
subtext = c(subtext, state[["MC"]][["tables"]][[fig_id]][["subtext"]])
}
# Applying names
names(choices) = cnames
# Adding the subtext
choicesOpt = list(
subtext = subtext)
# If the current_ana figure view exists we default to that
# otherwise we just choose the first choice.
if(current_ana[["tab_view"]] %in% choices){
selected = current_ana[["tab_view"]]
} else {
selected = choices[1]
}
uiele_picker = shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_tab_view"),
choices = choices,
selected = selected,
width = state[["MC"]][["formatting"]][["select_ana_fig_view"]][["width"]],
inline = TRUE,
choicesOpt = choicesOpt)
# uiele_switch =
# shinyWidgets::materialSwitch(
# inputId = NS(id, "switch_ana_tab_type"),
# label = state[["MC"]][["labels"]][["switch_ana_tab_type"]],
# value = current_ana[["tab_type_rpt"]],
# inline = TRUE,
# status = "success"
# )
#
# uiele = tagList(uiele_picker, uiele_switch)
choiceValues = c("report", "interactive")
choiceNames = c(state[["MC"]][["labels"]][["switch_ana_tab_report"]],
state[["MC"]][["labels"]][["switch_ana_tab_interactive"]])
uiele_switch =
shinyWidgets::radioGroupButtons(
inputId = NS(id, "switch_ana_tab"),
label = state[["MC"]][["labels"]][["switch_ana_tab"]],
selected = current_ana[["tab_type"]],
choiceValues = choiceValues,
choiceNames = choiceNames ,
status = "primary")
pv_div_style = paste0("display:inline-block") #;vertical-align:top")
uiele = tagList(div(style=pv_div_style, uiele_picker),
div(style=pv_div_style, uiele_switch))
} else {
uiele = state[["MC"]][["errors"]][["nca_no_tab"]]
}
uiele})
#------------------------------------
# Column Mapping
# id column
output$ui_nca_ana_col_id = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_id"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_id"]],
patterns = state[["MC"]][["detect_col"]][["id"]],
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_id"),
choices = dscols,
label = state[["MC"]][["labels"]][["select_ana_col_id"]],
selected = value,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_id"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_id"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_id"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# nominal time column
output$ui_nca_ana_col_ntime = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
input[["switch_ana_dose_from"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_ntime"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_ntime"]],
patterns = state[["MC"]][["detect_col"]][["ntime"]],
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_ntime"),
choices = dscols,
label = state[["MC"]][["labels"]][["select_ana_col_ntime"]],
selected = value,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_ntime"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_ntime"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_ntime"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# time column
output$ui_nca_ana_col_time = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_time"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_time"]],
patterns = state[["MC"]][["detect_col"]][["time"]],
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_time"),
choices = dscols,
label = state[["MC"]][["labels"]][["select_ana_col_time"]],
selected = value,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_time"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_time"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_time"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# dose column
output$ui_nca_ana_col_dose = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
input[["switch_ana_dose_from"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_dose"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_dose"]],
patterns = state[["MC"]][["detect_col"]][["dose"]],
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_dose"),
choices = dscols,
label = state[["MC"]][["labels"]][["select_ana_col_dose"]],
selected = value,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_dose"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_dose"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_dose"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# dur column
output$ui_nca_ana_col_dur = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_dur"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_dur"]],
patterns = state[["MC"]][["detect_col"]][["dur"]],
null_ok = TRUE,
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
#prepending for the N/A option
sel_style = c("", sel_style)
sel_subtext = c("", sel_subtext)
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_dur"),
choices = c("N/A", dscols),
label = state[["MC"]][["labels"]][["select_ana_col_dur"]],
selected = value,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_dur"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_dur"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_dur"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# rotue column
output$ui_nca_ana_col_route = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_route"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_route"]],
patterns = state[["MC"]][["detect_col"]][["route"]],
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_route"),
choices = dscols,
label = state[["MC"]][["labels"]][["select_ana_col_route"]],
selected = value,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_route"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_route"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_route"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# conc column
output$ui_nca_ana_col_conc = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_conc"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_conc"]],
patterns = state[["MC"]][["detect_col"]][["conc"]],
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_conc"),
choices = dscols,
label = state[["MC"]][["labels"]][["select_ana_col_conc"]],
selected = value,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_conc"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_conc"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_conc"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# dose cycle column
output$ui_nca_ana_col_cycle = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
input[["switch_ana_dose_from"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
if(current_ana[["dose_from"]] == "cols"){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_cycle"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_cycle"]],
patterns = state[["MC"]][["detect_col"]][["cycle"]],
null_ok = TRUE,
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_cycle"),
choices = dscols,
label = state[["MC"]][["labels"]][["select_ana_col_cycle"]],
selected = value,
multiple = FALSE,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_cycle"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_cycle"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_cycle"]][["tooltip_position"]])
}
}
}
uiele})
#------------------------------------
# evid column
output$ui_nca_ana_col_evid = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
input[["switch_ana_dose_from"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
if(current_ana[["dose_from"]] == "rows"){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_evid"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_evid"]],
patterns = state[["MC"]][["detect_col"]][["evid"]],
null_ok = TRUE,
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_evid"),
choices = dscols,
label = state[["MC"]][["labels"]][["select_ana_col_evid"]],
selected = value,
multiple = FALSE,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_evid"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_evid"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_evid"]][["tooltip_position"]])
}
}
}
uiele})
#------------------------------------
# group column
output$ui_nca_ana_col_group = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# This only generates the UI element if there is a data set
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_group"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_group"]],
patterns = state[["MC"]][["detect_col"]][["group"]],
null_ok = TRUE,
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_group"),
choices = dscols,
label = state[["MC"]][["labels"]][["select_ana_col_group"]],
selected = value,
multiple = TRUE,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_group"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_group"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_group"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# analyte column
output$ui_nca_ana_col_analyte = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
# Pulling out the dataset list
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Finding the value to use:
value = NCA_find_col(
curr_ana = current_ana[["col_analyte"]],
curr_ui = state[["NCA"]][["ui"]][["select_ana_col_analyte"]],
patterns = state[["MC"]][["detect_col"]][["analyte"]],
null_ok = TRUE,
dscols = dscols)
# Pulling out column header formatting information.
hfmt = FM_fetch_data_format(ds[["DS"]], state)
sel_style = c(rep("", length(dscols)))
sel_subtext = c(as.vector(unlist( hfmt[["col_subtext"]])))
#prepending for the N/A option
sel_style = c("", sel_style)
sel_subtext = c("", sel_subtext)
# Creating the selection input
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_col_analyte"),
choices = c("N/A", dscols),
label = state[["MC"]][["labels"]][["select_ana_col_analyte"]],
selected = value,
multiple = FALSE,
options = list(size = state[["yaml"]][["FM"]][["ui"]][["select_size"]]),
choicesOpt = list( style = sel_style,
subtext = sel_subtext,
"live-search"=TRUE),
width = state[["MC"]][["formatting"]][["select_ana_col_analyte"]][["width"]],
inline = TRUE)
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["select_ana_col_analyte"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["select_ana_col_analyte"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# Selecting how dosing should be inferred
output$ui_nca_ana_dose_from = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["button_ana_save"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# We only generate the ui element if the
# analysis is in a good state
if(!is.null(current_ana[["ana_dsview"]])){
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]])){
choiceValues = c("cols", "rows")
choiceNames = c(state[["MC"]][["labels"]][["switch_ana_dose_from_cols"]],
state[["MC"]][["labels"]][["switch_ana_dose_from_rows"]])
uiele =
shinyWidgets::radioGroupButtons(
inputId = NS(id, "switch_ana_dose_from"),
label = state[["MC"]][["labels"]][["switch_ana_dose_from"]],
selected = current_ana[["dose_from"]],
choiceValues = choiceValues,
choiceNames = choiceNames ,
status = "primary")
uiele = formods::FM_add_ui_tooltip(state, uiele,
tooltip = state[["MC"]][["formatting"]][["dose_from"]][["tooltip"]],
position = state[["MC"]][["formatting"]][["dose_from"]][["tooltip_position"]])
}
}
uiele})
#------------------------------------
# Specifying Units
# include units checkbox
output$ui_nca_ana_check_units = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele =
shinyWidgets::materialSwitch(
inputId = NS(id, "switch_ana_include_units"),
label = state[["MC"]][["labels"]][["switch_ana_include_units"]],
value = current_ana[["include_units"]],
status = "success"
)
uiele})
#------------------------------------
# amt units
output$ui_nca_ana_units_amt = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
req(input$switch_ana_include_units)
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# We only show the selection if include units is checked.
if(input$switch_ana_include_units){
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_units_amt"),
choices = state[["MC"]][["units"]][["amt"]],
label = state[["MC"]][["labels"]][["select_ana_units_amt"]],
selected = current_ana[["units_amt"]],
multiple = FALSE,
width = state[["MC"]][["formatting"]][["select_ana_units_amt"]][["width"]],
inline = TRUE)
}
uiele})
#------------------------------------
# units
output$ui_nca_ana_units_dose = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
req(input$switch_ana_include_units)
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# We only show the selection if include units is checked.
if(input$switch_ana_include_units){
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_units_dose"),
choices = state[["MC"]][["units"]][["dose"]],
label = state[["MC"]][["labels"]][["select_ana_units_dose"]],
selected = current_ana[["units_dose"]],
multiple = FALSE,
width = state[["MC"]][["formatting"]][["select_ana_units_dose"]][["width"]],
inline = TRUE)
}
uiele})
#------------------------------------
# conc units
output$ui_nca_ana_units_conc = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
req(input$switch_ana_include_units)
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# We only show the selection if include units is checked.
if(input$switch_ana_include_units){
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_units_conc"),
choices = state[["MC"]][["units"]][["conc"]],
label = state[["MC"]][["labels"]][["select_ana_units_conc"]],
selected = current_ana[["units_conc"]],
multiple = FALSE,
width = state[["MC"]][["formatting"]][["select_ana_units_conc"]][["width"]],
inline = TRUE)
}
uiele})
#------------------------------------
# time units
output$ui_nca_ana_units_time = renderUI({
react_state[[id_UD]]
react_state[[id_DW]]
react_state[[id_ASM]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
req(input$switch_ana_include_units)
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# We only show the selection if include units is checked.
if(input$switch_ana_include_units){
uiele =
shinyWidgets::pickerInput(
inputId = NS(id, "select_ana_units_time"),
choices = state[["MC"]][["units"]][["time"]],
label = state[["MC"]][["labels"]][["select_ana_units_time"]],
selected = current_ana[["units_time"]],
multiple = FALSE,
width = state[["MC"]][["formatting"]][["select_ana_units_time"]][["width"]],
inline = TRUE)
}
uiele})
#------------------------------------
# Analysis Scenarios
# Scenario selector
output$ui_nca_ana_scenario = renderUI({
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
# Pulling out the current analysis
current_ana = NCA_fetch_current_ana(state)
# Pulling out the scenario for the current analysis
ana_scenario = current_ana[["ana_scenario"]]
# Building the selector from the scenarios in the yaml file:
choices = list()
for(choice in names(state[["MC"]][["ana_scenarios"]])){
choices[[ state[["MC"]][["ana_scenarios"]][[choice]][["description"]] ]] = choice
}
uiele =
shinyWidgets::pickerInput(
selected = ana_scenario,
inputId = NS(id, "select_ana_scenario"),
label = state[["MC"]][["labels"]][["select_ana_scenario"]],
choices = choices,
width = state[["MC"]][["formatting"]][["select_ana_scenario"]][["width"]])
uiele})
#------------------------------------
# Add interval button
output$ui_nca_ana_add_int = renderUI({
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = shinyWidgets::actionBttn(
inputId = NS(id, "button_ana_add_int"),
label = state[["MC"]][["labels"]][["ana_add_int"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_ana_add_int"]][["size"]],
block = state[["MC"]][["formatting"]][["button_ana_add_int"]][["block"]],
color = "success",
icon = icon("plus-sign", lib="glyphicon"))
uiele})
#------------------------------------
# Scenario button
output$ui_nca_ana_scenario_use = renderUI({
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
uiele = shinyWidgets::actionBttn(
inputId = NS(id, "button_ana_use_scenario"),
label = state[["MC"]][["labels"]][["ana_use_scenario"]],
style = state[["yaml"]][["FM"]][["ui"]][["button_style"]],
size = state[["MC"]][["formatting"]][["button_ana_use_scenario"]][["size"]],
block = state[["MC"]][["formatting"]][["button_ana_use_scenario"]][["block"]],
color = "primary",
icon = icon("arrow-down"))
uiele})
#------------------------------------
# Analysis Options
output$ui_nca_ana_options = renderUI({
input[["button_ana_new"]]
input[["button_ana_save"]]
input[["button_ana_del"]]
input[["button_ana_run"]]
input[["button_ana_copy"]]
input[["select_current_ana"]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
# Pulling out the current analysis
current_ana = NCA_fetch_current_ana(state)
# NCA configuration for the current analysis
nca_config = current_ana[["nca_config"]]
# NCA configuration summary table
nc_summary = state[["NCA"]][["nca_config"]][["summary"]]
# This will hold all of the tabs:
uiele = tagList()
# Pulling the option width from the config file
opt_width = state[["MC"]][["formatting"]][["nca_config_option"]][["width"]]
for(tmpgroup in unique(nc_summary[["group"]])){
group_ele = tagList()
for(cfg_ele in nc_summary[nc_summary[["group"]] == tmpgroup, ]$key){
if(cfg_ele %in% names(nca_config)){
# Determining if we need to add a tool tip
ADD_TOOL_TIP = FALSE
if(state[["MC"]][["tooltips"]][["include"]]){
# If a tooltip is defined for this element then we attach it
if(!is.null((nca_config[[cfg_ele]][["tooltip"]]))){
if(system.file(package="prompter") != ""){
ADD_TOOL_TIP = TRUE
}
}
}
tmp_tt = NULL
if(is.null(nca_config[[cfg_ele]][["options"]])){
# If no options are specified we build out a text box
tmp_tI = textInput(
inputId = NS(id, nca_config[[cfg_ele]][["ui_id"]]),
width = opt_width,
label = nca_config[[cfg_ele]][["label"]],
value = nca_config[[cfg_ele]][["value"]]
)
# Adding tooltip if necessary
if(ADD_TOOL_TIP){
# JMH convert to use FM_add_ui_tooltip
tmp_tI = prompter::add_prompt(
tmp_tI,
position = "right",
size = "medium",
message = nca_config[[cfg_ele]][["tooltip"]]
)
}
# Adding the text input
group_ele = tagList(group_ele,
div(style="display:inline-block;vertical-align:top", #align-items:bottom;justify-content:center",
tmp_tI
)
)
} else {
# If there are options then we create a select box
tmp_sI =
selectInput(inputId = NS(id, nca_config[[cfg_ele]][["ui_id"]]),
width = opt_width,
label = nca_config[[cfg_ele]][["label"]],
selected = nca_config[[cfg_ele]][["value"]],
choices = nca_config[[cfg_ele]][["options"]]
)
# Adding tooltip if necessary
if(ADD_TOOL_TIP){
# JMH convert to use FM_add_ui_tooltip
tmp_sI = prompter::add_prompt(
tmp_sI,
position = "right",
size = "medium",
message = nca_config[[cfg_ele]][["tooltip"]]
)
}
# Adding the select input
group_ele = tagList(group_ele,
div(style="display:inline-block;vertical-align:top", #align-items:bottom;justify-content:center",
tmp_sI
)
)
}
}
}
# Adding the current group as a tab:
uiele = tagList(uiele,tags$h3(tmpgroup), group_ele)
}
uiele})
#------------------------------------
# Current DW elements
output$hot_nca_intervals = rhandsontable::renderRHandsontable({
input[["button_ana_add_int"]]
input[["button_ana_use_scenario"]]
input[["button_ana_new"]]
input[["button_ana_del"]]
input[["button_ana_copy"]]
# This forces reaction to the delete button
input$hot_nca_intervals
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
# Pulling out the current analysis
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
# Pulling out the widths to make it easier to deal with them below
w_start = state[["MC"]][["formatting"]][["intervals_start"]][["width"]]
w_stop = state[["MC"]][["formatting"]][["intervals_stop"]][["width"]]
w_np_text = state[["MC"]][["formatting"]][["intervals_np_text"]][["width"]]
w_delete = state[["MC"]][["formatting"]][["intervals_delete"]][["width"]]
# Total for the no intervals table
w_total = w_start + w_stop + w_np_text + w_delete
# By default intervals here is NULL and when new intervals are added it
# will become an dataframe:
if(is.null(current_ana[["intervals"]])){
df = data.frame("Intervals"= state[["MC"]][["labels"]][["no_intervals"]])
uiele = rhandsontable::rhandsontable(
df,
width = state[["MC"]][["formatting"]][["intervals"]][["width"]],
height = state[["MC"]][["formatting"]][["intervals"]][["height"]],
rowHeaders = NULL
) |>
hot_cols(colWidths = c(w_total))
} else {
# The user only sees np_text (pretty names) and not np_actual (actual
# names)
df = current_ana[["intervals"]]
# This will force things like 0 to be 0 instead of 0.0 and Inf to show
# up correctly.
df[["start"]] = as.character(df[["start"]])
df[["stop"]] = as.character(df[["stop"]])
df = dplyr::select(df, "start", "stop", "np_text", "delete")
df = dplyr::rename(df, "Start" = "start")
df = dplyr::rename(df, "Stop" = "stop")
df = dplyr::rename(df, "NCA Parameter" = "np_text")
df = dplyr::rename(df, "Delete" = "delete")
uiele = rhandsontable::rhandsontable(
df,
width = state[["MC"]][["formatting"]][["intervals"]][["width"]],
height = state[["MC"]][["formatting"]][["intervals"]][["height"]],
rowHeaders = NULL
) |>
hot_col("Start" , readOnly = TRUE) |>
hot_col("Stop" , readOnly = TRUE) |>
hot_col("NCA Parameter" , readOnly = TRUE) |>
hot_cols(colWidths = c(w_start, w_stop, w_np_text, w_delete))
}
})
#------------------------------------
# This can be used to trigger notifications
toNotify <- reactive({
list(input$button_ana_add_int,
input$button_ana_save,
input$button_ana_copy,
input$button_ana_del,
input$button_ana_new,
input$button_ana_use_scenario)
})
observeEvent(toNotify(), {
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
# Triggering optional notifications
notify_res = formods::FM_notify(
state = state,
session = session)
})
# Creates the ui for the compact view of the module
#------------------------------------
output$NCA_ui_compact = renderUI({
# Forcing a reaction to changes in other modules
#react_state[[id_UD]]
#react_state[[id_DW]]
react_state[[id_ASM]]
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
current_ana = NCA_fetch_current_ana(state)
uiele = NULL
if(is.null(current_ana)){
uiele = state[["MC"]][["labels"]][["no_dataset"]]
} else {
uiele_code_button = NULL
# Generating code button if enabled
if( state[["MC"]][["compact"]][["code"]]){
uiele_code = tagList(shinyAce::aceEditor(
NS(id, "ui_nca_code"),
height = state[["MC"]][["formatting"]][["code"]][["height"]]
))
uiele_code_button = tagList(
shinyWidgets::dropdownButton(
uiele_code,
inline = FALSE,
right = TRUE ,
size = "sm",
circle = FALSE,
width = state[["MC"]][["formatting"]][["code"]][["width"]],
status = "danger btn-custom-nca",
icon = icon("code", lib="font-awesome"),
tooltip = shinyWidgets::tooltipOptions(title = state[["MC"]][["tooltips"]][["show_code"]]))
)
# Button with FG elements table
uiele_nca_intervals = rhandsontable::rHandsontableOutput(NS(id, "hot_nca_intervals"))
uiele_nca_intervals_button = tagList(
shinyWidgets::dropdownButton(
uiele_nca_intervals,
inline = FALSE,
right = TRUE ,
size = "sm",
circle = FALSE,
status = "primary btn-custom-nca",
icon = icon("layer-group", lib="font-awesome"),
tooltip = shinyWidgets::tooltipOptions(title = state[["MC"]][["tooltips"]][["nca_intervals"]]))
)
}
# We only show the clip button if it's enabled
uiele_clip_button = NULL
if(state[["MC"]][["compact"]][["clip"]]){
uiele_clip_button = htmlOutput(NS(id, "ui_nca_clip_code"))
}
uiele_buttons_right = tagList(
tags$style(".btn-custom-nca {width: 100px;}"),
div(style="display:inline-block;vertical-align:top",
uiele_nca_intervals_button,
uiele_code_button,
uiele_clip_button,
htmlOutput(NS(id, "ui_nca_save_ana")),
htmlOutput(NS(id, "ui_nca_copy_ana")),
htmlOutput(NS(id, "ui_nca_del_ana")),
htmlOutput(NS(id, "ui_nca_new_ana"))
))
if(!is.null(state[["MC"]][["tooltips"]][["url_dosing"]])){
dosing_link = icon_link(href=state[["MC"]][["tooltips"]][["url_dosing"]])
}else{
dosing_link = NULL
}
if(!is.null(state[["MC"]][["tooltips"]][["url_intervals"]])){
interval_link = icon_link(href=state[["MC"]][["tooltips"]][["url_intervals"]])
}else{
interval_link = NULL
}
if(!is.null(state[["MC"]][["tooltips"]][["url_data"]])){
data_link = icon_link(href=state[["MC"]][["tooltips"]][["url_data"]])
}else{
data_link = NULL
}
# Main NCA options tab
uiele_nca_options = tagList(
tags$h3(state[["MC"]][["labels"]][["head_analysis_template"]]),
div(style="display:inline-block;vertical-align:bottom",
htmlOutput(NS(id, "ui_nca_ana_scenario"))
),
div(style="display:inline-block;vertical-align:bottom",
htmlOutput(NS(id, "ui_nca_ana_scenario_use")), tags$br()
),
tags$br(),
tags$h3(state[["MC"]][["labels"]][["head_intervals"]], interval_link),
tags$h4(state[["MC"]][["labels"]][["head_intervals_create"]]),
div(style="display:inline-block;vertical-align:bottom",
htmlOutput(NS(id, "ui_nca_ana_int_range"))
),
div(style="display:inline-block;vertical-align:bottom",
htmlOutput(NS(id, "ui_nca_ana_params"))
),
div(style="display:inline-block;vertical-align:bottom",
htmlOutput(NS(id, "ui_nca_ana_add_int")), tags$br()
),
#tags$br(),
#tags$h4(state[["MC"]][["labels"]][["head_intervals_current"]]),
#tagList(rhandsontable::rHandsontableOutput(NS(id, "hot_nca_intervals"))),
tags$br(),
tags$h3(state[["MC"]][["labels"]][["head_dose_from"]], dosing_link),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_dose_from"))),
tags$br(),
tags$h3(state[["MC"]][["labels"]][["head_col_mapping"]], data_link),
tags$h4(state[["MC"]][["labels"]][["head_col_mapping_required"]]),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_id"))),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_time"))),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_ntime"))),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_conc"))),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_dose"))),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_route"))),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_cycle"))),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_evid"))),
tags$br(),
tags$h4(state[["MC"]][["labels"]][["head_col_mapping_optional"]]),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_group"))),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_analyte"))),
div(style="display:inline-block",
htmlOutput(NS("NCA", "ui_nca_ana_col_dur"))),
tags$br(),
tags$h3(state[["MC"]][["labels"]][["head_units"]]),
div(style="display:inline-block",
htmlOutput(NS(id, "ui_nca_ana_check_units"))
),
tags$br(),
div(style="display:inline-block",
htmlOutput(NS(id, "ui_nca_ana_units_time"))
),
div(style="display:inline-block",
htmlOutput(NS(id, "ui_nca_ana_units_dose"))
),
div(style="display:inline-block",
htmlOutput(NS(id, "ui_nca_ana_units_conc"))
),
div(style="display:inline-block",
htmlOutput(NS(id, "ui_nca_ana_units_amt"))
),
tags$br(),
tags$h3(state[["MC"]][["labels"]][["head_run_analysis"]]),
div(style="display:inline-block;vertical-align:bottom",
htmlOutput(NS(id, "ui_nca_ana_source_sampling"))
),
div(style="display:inline-block;vertical-align:bottom",
htmlOutput(NS(id, "ui_nca_ana_run")), tags$br()
)
)
uiele_preview = tagList(
div(
shinydashboard::tabBox(
width = 10,
title = NULL,
# The id lets us use input$tabset1 on the server to find the current tab
id = NS(id, "tabset_nca_optons"), # height = "250px",
shiny::tabPanel(id=NS(id, "panel_analysis_opts"),
title=tagList(shiny::icon("magnifying-glass-chart"),
state[["MC"]][["labels"]][["panel_analysis_opts"]]),
tagList(
uiele_nca_options
# htmlOutput(NS(id, "ui_nca_ana_results_fig"))
)
),
shiny::tabPanel(id=NS(id, "panel_figure"),
title=tagList(shiny::icon("chart-line"),
state[["MC"]][["labels"]][["panel_figures"]]),
htmlOutput(NS(id, "ui_nca_ana_results_fig"))
),
shiny::tabPanel(id=NS(id, "panel_tables"),
title=tagList(shiny::icon("table"),
state[["MC"]][["labels"]][["panel_tables"]]),
htmlOutput(NS(id, "ui_nca_ana_results_tab"))
),
shiny::tabPanel(id=NS(id, "panel_nca_config"),
title=tagList(shiny::icon("gear"),
state[["MC"]][["labels"]][["panel_nca_config"]]),
htmlOutput(NS(id, "ui_nca_ana_options"))
)
)
)
)
uiele = tagList(
div(style="display:inline-block", htmlOutput(NS(id, "ui_nca_curr_anas"))),
div(style="display:inline-block", htmlOutput(NS(id, "ui_nca_ana_name"))),
div(style="display:inline-block", htmlOutput(NS(id, "ui_nca_curr_views"))),
tags$br(),
div(style="display:inline-block", htmlOutput(NS(id, "ui_nca_ana_notes"))),
tags$br(),
verbatimTextOutput(NS(id, "ui_nca_msg")),
#uiele_buttons_left,
uiele_preview,
uiele_buttons_right
)
}
uiele})
#------------------------------------
# Creating reaction if a variable has been specified
if(!is.null(react_state)){
# Here we list the ui inputs that will result in a state change:
toListen <- reactive({
list(
input$button_ana_run,
input$button_ana_new,
input$button_ana_save,
input$button_ana_copy,
input$button_ana_del
)
})
# This updates the reaction state:
observeEvent(toListen(), {
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
formods::FM_le(state, "reaction state updated")
#react_state[[id]] = state
state_list = list(
checksum = state[["NCA"]][["checksum"]],
ui = state[["NCA"]][["ui"]]
)
react_state[[id]][["NCA"]] = state_list
})
}
#------------------------------------
# Copying code to clipboard
observeEvent(input$button_ana_clip, {
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
formods::FM_le(state, "clipping code")
# This is all conditional on the whether clipr is installed $
# and if the app isn't deployed
if((system.file(package="clipr") != "") & !deployed){
current_ana = NCA_fetch_current_ana(state)
if(is.null(current_ana[["code_sa"]])){
uiele = "# Run analysis to see code."
} else {
uiele = paste0(current_ana[["code_sa"]], collapse="\n")
}
clipr::write_clip(uiele)
}
})
#------------------------------------
# Removing holds
remove_hold_listen <- reactive({
list(react_state[[id_ASM]],
input$select_current_ana,
input$select_current_view)
})
observeEvent(remove_hold_listen(), {
# Once the UI has been regenerated we
# remove any holds for this module
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
formods::FM_le(state, "removing holds")
# Removing all holds
for(hname in names(state[["NCA"]][["ui_hold"]])){
remove_hold(state, session, hname)
}
}, priority = -100)
#------------------------------------
})
}
#'@export
#'@title Fetch ruminate State
#'@description Merges default app options with the changes made in the UI
#'@param id Shiny module ID
#'@param input Shiny input variable
#'@param session Shiny session variable
#'@param FM_yaml_file App configuration file with FM as main section.
#'@param MOD_yaml_file Module configuration file with MC as main section.
#'@param id_ASM ID string for the app state management module used to save and load app states
#'@param id_UD ID string for the upload data module used to save and load app states
#'@param id_DW ID string for the data wrangling module used to save and load app states
#'@param react_state Variable passed to server to allow reaction outside of module (\code{NULL})
#'@return list containing the current state of the app including default
#'values from the yaml file as well as any changes made by the user. The list
#'has the following structure:
#' \itemize{
#' \item{yaml:} Full contents of the supplied yaml file.
#' \item{MC:} Module components of the yaml file.
#' \item{NCA:}
#' \itemize{
#' \item{ana_cntr:} Analysis counter.
#' \item{anas:} List of analyses: Each analysis has the following structure:
#' \itemize{
#' \item{ana_dsview:} Dataset view/ID (name from DSV) selected as a data source for this analysis.
#' \item{ana_scenario:} Analysis scenario selected in the UI
#' \item{checksum:} checksum of the analysis (used to detect changes in the analysis).
#' \item{code:} Code to generate analysis from start to finish or error messages if code generation/analysis failed.
#' \item{code_components:} List containing the different components from code
#' \item{col_conc:} Column from ana_dsview containing the concentration data.
#' \item{col_dose:} Column from ana_dsview containing the dose amount.
#' \item{col_dur:} Column from ana_dsview containing the infusion duration or N/A if unused.
#' \item{col_group:} Columns from ana_dsview containing other grouping variables.
#' \item{col_id:} Column from ana_dsview containing the subject IDs.
#' \item{col_ntime:} Column from ana_dsview containing the nominal time values
#' \item{col_route:} Column from ana_dsview containing the dosing route.
#' \item{col_time:} Column from ana_dsview containing the time values.
#' \item{id:} Character id (\code{ana_idx}).
#' \item{idx:} Numeric id (\code{1}).
#' \item{include_units:} Boolean variable indicating in units should included in the analysis.
#' \item{interval_range:} Vector with the first element representing he beginning of the interval
#' and the second element containing the end of the interval.
#' \item{intervals:} List of the intervals to include.
#' \item{isgood:} Current status of the analysis.
#' \item{key:} Analysis key acts as a title/caption (user editable)
#' \item{msgs:} Messages generated when checking configuration and analysis options.
#' \item{nca_config:} List of NCA configuration options for this analysis.
#' \item{nca_object_name:} Prefix for NCA objects associated with this analyis.
#' \item{nca_parameters:} NCA parameters selected for calculation in the UI.
#' \item{notes:} Analysis notes (user editable)
#' \item{objs:} List of names and values for objects created with generated code.
#' \item{sampling:} Sampling method either "sparse" or "serial"
#' \item{units_amt:} Amount units.
#' \item{units_conc:} Concentration units.
#' \item{units_dose:} Dosing units.
#' \item{units_time:} Time units.
#' }
# ' \item{button_counters:} List of counters to detect button clicks.
#' \item{current_ana:} Currently selected analysis (list name element from anas).
#' \item{DSV:} Available data source views (see \code{\link[formods]{FM_fetch_ds}})
#' \item{checksum:} This is an MD5 sum of the module (checksum of the analysis checksums).
#' \item{nca_config:} List of PKNCA configuration options for this analysis.
#' \item{nca_parameters:} List with two elements
#' \itemize{
#' \item{choices:} List consisting of "Common Parameters" and
#' "Other" (used for grouping in the UI).
#' Each of these is a list of text parameter
#' names with a value of the PKNCA parameter
#' name.
#' \item{summary:} Summary table with the following columns:
#' \itemize{
#' \item{parameter:} PKNCA Paramter name.
#' \item{text:} Name used in text output.
#' \item{md:} Name used markdown output.
#' \item{latex:} Name used in latex output.
#' \item{description:} Verbose textual description of the parameter.
#' }
#' }
#' \item{ui:} Current value of form elements in the UI.
#' \item{ui_ana_map:} Map between UI element names and analysis in the object you get from \code{\link{NCA_fetch_current_ana}}
#' \item{ui_ids:} Vector of UI elements for the module.
#' \item{ui_hold:} List of hold elements to disable updates before a full ui referesh is complete.
#' }
#' \item{MOD_TYPE:} Character data containing the type of module \code{"NCA"}
#' \item{id:} Character data containing the module id module in the session variable.
#' \item{FM_yaml_file:} App configuration file with FM as main section.
#' \item{MOD_yaml_file:} Module configuration file with MC as main section.
#'}
#'@example inst/test_apps/NCA_funcs.R
NCA_fetch_state = function(id, input, session,
FM_yaml_file, MOD_yaml_file,
id_ASM, id_UD, id_DW, react_state){
# Template for an empty dataset
#---------------------------------------------
# Getting the current state
state = formods::FM_fetch_mod_state(session, id)
# If the state has not yet been defined then we
# initialize it
if(is.null(state)){
# General state information
state = NCA_init_state(FM_yaml_file, MOD_yaml_file, id, id_UD, id_DW, session)
}
# Detecting changes in the datasets
# JMH Test this update in full app. Test the following:
# - new uploaded dataset
# - data view in use changes
# - data view in use is deleted
UPDATE_DS = FALSE
# The main uploaded dataset
if("checksum" %in% names(isolate(react_state[[id_UD]][["UD"]]))){
if(!is.null(isolate(react_state[[id_UD]][["UD"]][["checksum"]]))){
if(is.null(state[["NCA"]][["DSV"]][["modules"]][["UD"]][[id_UD]])){
# If the UD checksum isn't NULL but the stored value in DSV is then we
# need to update the dataset
UPDATE_DS = TRUE
} else if(isolate(react_state[[id_UD]][["UD"]][["checksum"]]) !=
state[["NCA"]][["DSV"]][["modules"]][["UD"]][[id_UD]]){
# If the stored checksum in DSV is different than the currently
# uploaded dataset in UD then we force a reset as well:
UPDATE_DS = TRUE
}
}
}
# Changes in data views from data wrangling module
if("checksum" %in% names(isolate(react_state[[id_DW]][["DW"]]))){
if(!is.null(isolate(react_state[[id_DW]][["DW"]][["checksum"]]))){
if(isolate(react_state[[id_DW]][["DW"]][["hasds"]])){
if(is.null(state[["NCA"]][["DSV"]][["modules"]][["DW"]][[id_DW]])){
# If the DW checksum isn't NULL but the stored value in DSV is then we
# need to update the dataset
UPDATE_DS = TRUE
} else if(isolate(react_state[[id_DW]][["DW"]][["checksum"]]) !=
state[["NCA"]][["DSV"]][["modules"]][["DW"]][[id_DW]]){
# If the stored checksum in DSV is different than the currently
# uploaded dataset in DW then we force a reset as well:
UPDATE_DS = TRUE
}
} else {
# If there is no dataset but there was one once before we also
# trigger a dataset update:
if(!is.null(state[["NCA"]][["DSV"]][["modules"]][["DW"]][[id_DW]])){
UPDATE_DS = TRUE
}
}
}
}
# # This is changes in the wrangled data views
# if("checksum" %in% names(isolate(react_state[[id_DW]][["DW"]]))){
# if(!is.null(isolate(react_state[[id_DW]][["DW"]][["checksum"]]))){
# if(is.null(state[["NCA"]][["DSV"]][["modules"]][["DW"]][[id_DW]])){
# # If the DW checksum isn't NULL but the stored value in DSV is then we
# # need to update the dataset
# UPDATE_DS = TRUE
# } else if(isolate(react_state[[id_DW]][["DW"]][["checksum"]]) !=
# state[["NCA"]][["DSV"]][["modules"]][["DW"]][[id_DW]]){
# # If the stored checksum in DSV is different than the currently
# # uploaded dataset in DW then we force a reset as well:
# UPDATE_DS = TRUE
# }
# }
# }
if(UPDATE_DS){
formods::FM_le(state, "Updating DS")
# updating the "DSV" components
if(state[["NCA"]][["isgood"]]){
state[["NCA"]][["DSV"]] = formods::FM_fetch_ds(state, session, c(id_UD, id_DW))
} else {
state = NCA_init_state(FM_yaml_file,
MOD_yaml_file,
id,
id_UD,
id_DW,
session)
}
}
#---------------------------------------------
# Here we update the state based on user input
for(ui_name in state[["NCA"]][["ui_ids"]]){
if(!is.null(isolate(input[[ui_name]]))){
# Prevents updating when the ui is being held.
if(!fetch_hold(state, ui_name)){
state[["NCA"]][["ui"]][[ui_name]] = isolate(input[[ui_name]])
}
} else {
state[["NCA"]][["ui"]][[ui_name]] = ""
}
}
msgs = c()
#---------------------------------------------
# This will sync the analysis options in the UI to the values in the UI
for(ui_name in names(state[["NCA"]][["ui_ana_map"]])){
# We only update if there are no holds set:
# for the current ui_name
if(!fetch_hold(state, ui_name)){
# Pulling out the current analysis
current_ana = NCA_fetch_current_ana(state)
# This prevents updating analysis elements if
# the ui_element has not yet been created:
SAVE_ANA_NAME = FALSE
if(length(state[["NCA"]][["ui"]][[ui_name]])>1){
SAVE_ANA_NAME = TRUE
}else if(state[["NCA"]][["ui"]][[ui_name]] != "" ){
SAVE_ANA_NAME = TRUE
}
if(SAVE_ANA_NAME){
ana_name = state[["NCA"]][["ui_ana_map"]][[ui_name]]
# Messaging detected change
if(has_changed(ui_val = state[["NCA"]][["ui"]][[ui_name]],
old_val = current_ana[[ana_name]])){
formods::FM_le(state, paste0("setting analysis: ", ana_name, " = ", paste(state[["NCA"]][["ui"]][[ui_name]], collapse=", ")))
}
current_ana[[ana_name]] = state[["NCA"]][["ui"]][[ui_name]]
}
# Storing any changes here:
state = NCA_set_current_ana(state, current_ana)
}
}
#---------------------------------------------
#---------------------------------------------
# This will sync the nca options in the UI to the values in the state
current_ana = NCA_fetch_current_ana(state)
for(nca_opt in names(current_ana[["nca_config"]])){
# Getting the ui_id for the current option:
ui_name = current_ana[["nca_config"]][[nca_opt]][["ui_id"]]
# We only update the nca option if it exists in the UI
if(!is.null(state[["NCA"]][["ui"]][[ui_name]])){
# We only update the nca option of there is no hold
if(!fetch_hold(state, ui_name)){
if(state[["NCA"]][["ui"]][[ui_name]] != ""){
# We compare the values in the ui to the nca_config and if they are
# different we assign them
if(as.character(state[["NCA"]][["ui"]][[ui_name]]) !=
as.character(current_ana[["nca_config"]][[nca_opt]][["value"]])){
# Updating the current analysis with the ui from the state
current_ana[["nca_config"]][[nca_opt]][["value"]] =
state[["NCA"]][["ui"]][[ui_name]]
formods::FM_le(state, paste0("setting NCA option: ", nca_opt, " = ", state[["NCA"]][["ui"]][[ui_name]]))
}
}
}
}
}
# Storing any changes here:
state = NCA_set_current_ana(state, current_ana)
#---------------------------------------------
# Here we're processing any element delete requests
# - first we only do this if the hot_nca_intervals has been defined
if(!fetch_hold(state,"hot_nca_intervals")){
if(is.list(state[["NCA"]][["ui"]][["hot_nca_intervals"]])){
# - If that's the case we get the data frame for it:
hot_df = rhandsontable::hot_to_r(state[["NCA"]][["ui"]][["hot_nca_intervals"]])
# - Because the UI initialzes to a "no intervals" message we need
# to make sure there is a delete column
if("Delete" %in% names(hot_df)){
# - lastly we check to see if any have been selected for deletion:
if(any(hot_df$Delete == TRUE)){
# Pulling out the current analysis
current_ana = NCA_fetch_current_ana(state)
# Just keeping the rows that are _not_ marked for deletion:
current_ana[["intervals"]] = current_ana[["intervals"]][!hot_df$Delete, ]
# If we delete the last entry we set it to NULL so it will display
# the empty intervals message:
if(nrow(current_ana[["intervals"]]) == 0){
current_ana[["intervals"]] = NULL
}
# Storing any changes here:
state = NCA_set_current_ana(state, current_ana)
}
}
}
}
#---------------------------------------------
# Process option changes to the fg_ind_obs figure
# the current selection in the UI:
if(has_changed(ui_val = state[["NCA"]][["ui"]][["button_fg_ind_obs_save"]],
old_val = state[["NCA"]][["button_counters"]][["button_fg_ind_obs_save"]])){
formods::FM_le(state, "updating fg_ind_obs")
# updating just the fg_ind_obs figure
state = run_nca_components(state, "fg_ind_obs")
# Saving the button state to the counter
state[["NCA"]][["button_counters"]][["button_fg_ind_obs_save"]] =
state[["NCA"]][["ui"]][["button_fg_ind_obs_save"]]
}
#---------------------------------------------
# Process scenario button selection here to overwrite
# the current selection in the UI:
if(has_changed(ui_val = state[["NCA"]][["ui"]][["button_ana_use_scenario"]],
old_val = state[["NCA"]][["button_counters"]][["button_ana_use_scenario"]])){
# Empty messages:
msgs = c()
# Current scenario:
ana_scenario = current_ana[["ana_scenario"]]
# Loading the scenario:
state = NCA_load_scenario(state, ana_scenario)
# Saving the button state to the counter
state[["NCA"]][["button_counters"]][["button_ana_use_scenario"]] =
state[["NCA"]][["ui"]][["button_ana_use_scenario"]]
}
#---------------------------------------------
# Process scenario button selection here to overwrite
# the current selection in the UI:
if(has_changed(ui_val = state[["NCA"]][["ui"]][["button_ana_add_int"]],
old_val = state[["NCA"]][["button_counters"]][["button_ana_add_int"]])){
# Default to adding the interval
ADD_INTERVAL = TRUE
# Pulling the interval specifications from the ui elements:
if(length(state[["NCA"]][["ui"]][["select_ana_interval_range"]])==2){
interval_start = state[["NCA"]][["ui"]][["select_ana_interval_range"]][1]
interval_stop = state[["NCA"]][["ui"]][["select_ana_interval_range"]][2]
} else {
ADD_INTERVAL = FALSE
interval_start = NA
interval_stop = NA
msgs = c(msgs, "Interval range should be of lenght 2")
}
interval_start = as.numeric(as.character(interval_start))
interval_stop = as.numeric(as.character(interval_stop))
# Pulling out the NCA parameters
nca_parameters = state[["NCA"]][["ui"]][["select_ana_nca_parameters"]]
# Some basic error checking
if(is.na(interval_start)){
ADD_INTERVAL = FALSE
msgs = c(msgs, "Unknown interval start time. Must be a number, 0, or Inf")
}
if(is.na(interval_stop)){
ADD_INTERVAL = FALSE
msgs = c(msgs, "Unknown interval stop time. Must be a number, 0, or Inf")
}
if(!is.na(interval_start) & !is.na(interval_stop)){
if(interval_start > interval_stop){
ADD_INTERVAL = FALSE
msgs = c(msgs, paste0("Interval start (", interval_start, ") should be less than the interval end (", interval_stop, ")"))
}
}
if(length(nca_parameters) == 1){
if(nca_parameters ==""){
ADD_INTERVAL = FALSE
msgs = c(msgs, "You must select at least one NCA parameter per interval.")
}
}
# If everything is good up top we add the interval
if(ADD_INTERVAL){
state = NCA_add_int(state=state,
interval_start = interval_start,
interval_stop = interval_stop,
nca_parameters = nca_parameters)
details = paste0("[", interval_start, ", ",
interval_stop, "] ",
paste0(nca_parameters, collapse=", "))
# Adding a notification
notify_text = state[["MC"]][["notifications"]][["ana_add_int_success"]]
notify_text = stringr::str_replace(notify_text, "===DETAILS===", details)
notify_type = "success"
formods::FM_le(state, notify_text)
state = FM_set_notification(state, notify_text, "Interval Added", "success")
} else {
notify_text = paste(msgs, collapse="\n")
notify_type = "failure"
state = FM_set_notification(state, notify_text, "Interval Not Added", "failure")
formods::FM_le(state, "interval was not added")
}
# Saving the button state to the counter
state[["NCA"]][["button_counters"]][["button_ana_add_int"]] =
state[["NCA"]][["ui"]][["button_ana_add_int"]]
# Updating any messages
state = formods::FM_set_ui_msg(state, msgs)
}
#---------------------------------------------
# Run Analysis
if(has_changed(ui_val = state[["NCA"]][["ui"]][["button_ana_run"]],
old_val = state[["NCA"]][["button_counters"]][["button_ana_run"]])){
formods::FM_le(state, "running nca and generating subsequent figures and tables")
# Pausing access to the screen
formods:: FM_pause_screen(
state = state,
message = state[["MC"]][["labels"]][["busy"]][["run_nca"]],
session = session)
# This will build the code and run the different components:
state = run_nca_components(state)
# Removing the pause
FM_resume_screen(state = state,
session = session)
# Saving the button state to the counter
state[["NCA"]][["button_counters"]][["button_ana_run"]] =
state[["NCA"]][["ui"]][["button_ana_run"]]
}
#---------------------------------------------
# Here we react to changes between the UI and the current state
if(has_changed(ui_val = state[["NCA"]][["ui"]][["select_current_ana"]],
old_val = state[["NCA"]][["current_ana"]]) &
(!fetch_hold(state, "select_current_ana"))){
# Changing the current view to the one selected in the UI
# JMH create NCA_mkactive_ana here to set active
# state[["NCA"]][["current_ana"]] = state[["NCA"]][["ui"]][["select_current_ana"]]
state = NCA_mkactive_ana(state, state[["NCA"]][["ui"]][["select_current_ana"]])
state = set_hold(state)
# browser()
}
#---------------------------------------------
# Copy Analysis
if(has_changed(ui_val = state[["NCA"]][["ui"]][["button_ana_copy"]],
old_val = state[["NCA"]][["button_counters"]][["button_ana_copy"]])){
formods::FM_le(state, "copying current analysis")
# Pausing access to the screen because the rebuilding portion below can
# take a while and we don't want the user mucking around with things while
# that is happening.
formods::FM_pause_screen(
state = state,
message = state[["MC"]][["labels"]][["busy"]][["run_nca"]],
session = session)
# This creates a copy of the current analysis which will become the old
# one :).
old_ana = NCA_fetch_current_ana(state)
# Creating a new analysis and pulling it out of the
# state object:
state = NCA_new_ana(state)
current_ana = NCA_fetch_current_ana(state)
# Now we take the current (new one we just created) analysis and
# we populate it with all the individual elements except
# the following:
exnames = c("id", "key", "idx", "nca_object_name", "objs")
# This is all the names
copy_names = names(old_ana)
# And this removes the exclusions:
copy_names = copy_names[!(copy_names %in% exnames)]
for(ana_name in copy_names){
current_ana[[ana_name]] = old_ana[[ana_name]]
}
# Now we save the copy of the new analysis that has been updated with
# the elements of the old analysis. This has to be done before we rerun
# the components below:
state = NCA_set_current_ana(state, current_ana)
# Lastly we need to rebuild the analysis elements so all the id in
# the generated code are correct. It's a little slow but it ensures the
# objs list element is correct
state = run_nca_components(state)
# Setting hold for all the elements
state = set_hold(state, inputId = NULL)
# Removing the pause
FM_resume_screen(state = state,
session = session)
# Saving the button state to the counter
state[["NCA"]][["button_counters"]][["button_ana_copy"]] =
state[["NCA"]][["ui"]][["button_ana_copy"]]
}
#---------------------------------------------
# New Analysis
if(has_changed(ui_val = state[["NCA"]][["ui"]][["button_ana_new"]],
old_val = state[["NCA"]][["button_counters"]][["button_ana_new"]])){
formods::FM_le(state, "creating new analysis")
msgs = c()
# Creating a new analysis
state = NCA_new_ana(state)
# Setting hold for all the elements
state = set_hold(state, inputId = NULL)
#state = set_hold(state, inputId = "select_current_ana")
#state = set_hold(state, inputId = "select_current_view")
# Saving the button state to the counter
state[["NCA"]][["button_counters"]][["button_ana_new"]] =
state[["NCA"]][["ui"]][["button_ana_new"]]
# Updating any messages
state = formods::FM_set_ui_msg(state, msgs)
}
#---------------------------------------------
# Delete analysis
if(has_changed(ui_val = state[["NCA"]][["ui"]][["button_ana_del"]],
old_val = state[["NCA"]][["button_counters"]][["button_ana_del"]])){
formods::FM_le(state, "deleting analysis")
msgs = c()
# Getting the current analysis
current_ana = NCA_fetch_current_ana(state)
# Deleting the analysis
state[["NCA"]][["anas"]][[current_ana[["id"]]]] = NULL
# If there are no analysis left then we create an empty one
if( length(state[["NCA"]][["anas"]]) == 0){
state = NCA_new_ana(state)
} else {
# If there are analysis then we set the first one as active
state[["NCA"]][["current_ana"]] = names(state[["NCA"]][["anas"]])[1]
}
# Setting hold for analysis select
state = set_hold(state, inputId = "select_current_ana")
state = set_hold(state, inputId = "select_current_view")
# Saving the button state to the counter
state[["NCA"]][["button_counters"]][["button_ana_del"]] =
state[["NCA"]][["ui"]][["button_ana_del"]]
# Updating any messages
state = formods::FM_set_ui_msg(state, msgs)
}
#---------------------------------------------
# Save analysis
if(has_changed(ui_val = state[["NCA"]][["ui"]][["button_ana_save"]],
old_val = state[["NCA"]][["button_counters"]][["button_ana_save"]])){
formods::FM_le(state, "saving changes to current analysis")
# Getting the current analysis
current_ana = NCA_fetch_current_ana(state)
if(state[["NCA"]][["ui"]][["text_ana_key"]] != ""){
# Resetting the key
current_ana[["key"]] = state[["NCA"]][["ui"]][["text_ana_key"]]
# If the key is the same as the ID (the default value) then we name it
# the same as the data view being used:
if(current_ana[["key"]] == current_ana[["id"]]){
ana_dsview = state[["NCA"]][["ui"]][["select_current_view"]]
if(!is.null(state[["NCA"]][["DSV"]][["ds"]][[ ana_dsview ]][["label"]])){
if(state[["NCA"]][["DSV"]][["ds"]][[ ana_dsview ]][["label"]] != ""){
current_ana[["key"]] = state[["NCA"]][["DSV"]][["ds"]][[ ana_dsview ]][["label"]]
}
}
}
} else {
# returning an error
msgs = c(msgs,
state[["MC"]][["errors"]][["current_key_empty"]])
}
# Saving the caption as well
current_ana[["notes"]] = state[["NCA"]][["ui"]][["text_ana_notes"]]
# updating the view id
current_ana[["ana_dsview"]] = state[["NCA"]][["ui"]][["select_current_view"]]
# Saving changes to the current analysis
state = NCA_set_current_ana(state, current_ana)
# Setting holds to ensure any key changes are made
state = set_hold(state)
notify_text = paste(
tagList(paste0("Caption: ", current_ana[["key"]], ", " ),
paste0("Source Data: ", state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]][["label"]], ", "),
paste0("Notes: ", current_ana[["notes"]] )),
collapse="\n")
state = FM_set_notification(state, notify_text, "Analysis saved", "info")
# Saving the button state to the counter
state[["NCA"]][["button_counters"]][["button_ana_save"]] =
state[["NCA"]][["ui"]][["button_ana_save"]]
# Updating any messages
state = formods::FM_set_ui_msg(state, msgs)
}
#---------------------------------------------
# Passing any messages back to the user
#state = formods::FM_set_ui_msg(state, msgs, append=TRUE)
#---------------------------------------------
# Saving the state
FM_set_mod_state(session, id, state)
# Returning the state
state}
#'@title Initialize NCA Module State
#'@description Creates a list of the initialized module state
#'@param FM_yaml_file App configuration file with FM as main section.
#'@param MOD_yaml_file Module configuration file with MC as main section.
#'@param id ID string for the module.
#'@param id_UD ID string for the upload data module used to handle uploads or the name of the list element in react_state where the data set is stored.
#'@param id_DW ID string for the data wrangling module to process any uploaded data
#'@param session Shiny session variable (in app) or a list (outside of app)
#'@return list containing an empty NCA state
NCA_init_state = function(FM_yaml_file, MOD_yaml_file, id, id_UD, id_DW, session){
button_counters = c("button_ana_new",
"button_ana_del",
"button_ana_run",
"button_ana_save",
"button_ana_copy",
"button_ana_add_int",
"button_ana_use_scenario",
"button_fg_ind_obs_save",
"switch_ana_include_units")
# mapping name in UI to name used in the analysis
ui_ana_map = list(
"switch_ana_include_units" = "include_units",
"select_ana_interval_range" = "interval_range",
"select_fg_ind_obs_ncol" = "fg_ind_obs_ncol",
"select_fg_ind_obs_nrow" = "fg_ind_obs_nrow",
"select_fg_ind_obs_page" = "curr_fg_ind_obs",
"select_tb_ind_obs_page" = "curr_tb_ind_obs",
"select_tb_ind_params_page" = "curr_tb_ind_params",
"select_tb_sum_params_page" = "curr_tb_sum_params",
"fg_ind_obs_rpt" = "fg_ind_obs_rpt",
"tb_ind_obs_rpt" = "tb_ind_obs_rpt",
"tb_ind_params_rpt" = "tb_ind_params_rpt",
"tb_sum_params_rpt" = "tb_sum_params_rpt",
"check_fg_ind_obs_logy" = "fg_ind_obs_logy",
"select_ana_source_sampling" = "sampling",
"switch_ana_dose_from" = "dose_from",
"switch_ana_fig" = "fig_type",
"switch_ana_tab" = "tab_type",
"text_ana_key" = "key",
"select_ana_nca_parameters" = "nca_parameters",
"select_ana_scenario" = "ana_scenario",
"select_ana_units_time" = "units_time",
"select_ana_units_conc" = "units_conc",
"select_ana_units_dose" = "units_dose",
"select_ana_units_amt" = "units_amt",
"select_ana_col_id" = "col_id" ,
"select_ana_col_time" = "col_time" ,
"select_ana_col_ntime" = "col_ntime" ,
"select_ana_col_dose" = "col_dose" ,
"select_ana_col_dur" = "col_dur" ,
"select_ana_col_conc" = "col_conc" ,
"select_ana_col_route" = "col_route" ,
"select_ana_col_group" = "col_group",
"select_ana_col_evid" = "col_evid",
"select_ana_col_cycle" = "col_cycle",
"select_ana_col_analyte" = "col_analyte",
"select_ana_fig_view" = "fig_view",
"select_ana_tab_view" = "tab_view"
)
# We add all of the button counters as well as
# the ui inputs specified in ui_ana_map above.
# Then we append the other ui elements we want to
# use in the state:
ui_ids = c(button_counters,
names(ui_ana_map),
"hot_nca_intervals",
"select_current_ana",
"select_current_view",
"text_ana_notes")
ui_hold = c()
isgood = TRUE
state = formods::FM_init_state(
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id = id,
dep_mod_ids = c(id_UD, id_DW),
MT = "NCA",
button_counters = button_counters,
ui_ids = ui_ids,
ui_hold = ui_hold,
session = session)
# These will be the default options
nca_config = state[["MC"]][["nca_config"]]
# This table summarizes the different options
nc_summary = NULL
for(nca_opt in names(nca_config)){
nca_config_ui_id = paste0("nca_opt_",nca_opt)
# Storing the ui_id for the option in the list
nca_config[[nca_opt]][["ui_id"]] = nca_config_ui_id
nc_summary =
rbind(nc_summary,
data.frame(key = nca_opt,
ui_id = nca_config_ui_id,
group = state[["MC"]][["nca_config"]][[nca_opt]][["group"]],
label = state[["MC"]][["nca_config"]][[nca_opt]][["label"]],
pknca_option = state[["MC"]][["nca_config"]][[nca_opt]][["pknca_option"]])
)
}
# This will pull out the nca parameters meta information.
np_meta = NCA_fetch_np_meta(MOD_yaml_file = MOD_yaml_file)
np_choices = np_meta[["choices"]]
np_summary = np_meta[["summary"]]
# IDs for NCA options start with nca_opt_ (see data.frame command above)
# We add those to the list of the ui_ids:
ui_ids = c(ui_ids, nc_summary[["ui_id"]])
# Adding all of the ui_ids to the list of ui_hold
ui_hold = ui_ids
# Now we recreate the initialized state with all of the ui_ids
state = FM_init_state(
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id = id,
dep_mod_ids = c(id_UD, id_DW),
MT = "NCA",
button_counters = button_counters,
ui_ids = ui_ids,
ui_hold = ui_hold,
session = session)
# This table summarizes the options
state[["NCA"]][["nca_config"]][["summary"]] = nc_summary
state[["NCA"]][["nca_config"]][["default"]] = nca_config
# This summarizes the parameters
state[["NCA"]][["nca_parameters"]][["summary"]] = np_summary
state[["NCA"]][["nca_parameters"]][["choices"]] = np_choices
# Storing the analysis map
state[["NCA"]][["ui_ana_map"]] = ui_ana_map
# Creating an empty docx report. It has the style information
# needed for building tables
init_cmd = state[["yaml"]][["FM"]][["reporting"]][["content_init"]][["docx"]]
# Changing to the user directory to create the report object:
current_dir = getwd()
user_dir = FM_fetch_user_files_path(state)
setwd(user_dir)
on.exit( setwd(current_dir))
tcres = formods::FM_tc(cmd = init_cmd, tc_env = list(), capture="rpt")
state[["NCA"]][["docx_rpt"]] = tcres[["capture"]][["rpt"]]
# Returning back to the current directory
setwd(current_dir)
# Finding the dataset
DSV = formods::FM_fetch_ds(state, session, c(id_UD, id_DW))
# If the dataset isn't good then we need to
# flag the whole module as not being good
if(!DSV[["isgood"]]){
isgood = FALSE
}
# Module-specific elements
state[["NCA"]][["isgood"]] = isgood
state[["NCA"]][["DSV"]] = DSV
state[["NCA"]][["anas"]] = NULL
state[["NCA"]][["ana_cntr"]] = 0
state[["NCA"]][["current_ana"]] = NULL
state[["NCA"]][["mod_deps"]] = FM_fetch_deps(state = state, session = session)
formods::FM_le(state, "State initialized")
if(isgood){
# Initializing an empty analysis
state = NCA_new_ana(state)
}
formods::FM_le(state, "State initialized")
state}
#'@export
#'@title Fetch Module Code
#'@description Fetches the code to generate results seen in the app
#'@param state NCA state from \code{NCA_fetch_state()}
#'@return Character object vector with the lines of code
#'@example inst/test_apps/NCA_funcs.R
NCA_fetch_code = function(state){
code = c()
ana_found = FALSE
for(ana_id in names(state[["NCA"]][["anas"]])){
current_ana = state[["NCA"]][["anas"]][[ana_id]]
if(current_ana[["isgood"]]){
ana_found = TRUE
code = c(code, current_ana[["code_components"]][["code_ana_only"]])
code = c(code, current_ana[["code_components"]][["code_fg_ind_obs"]])
code = c(code, current_ana[["code_components"]][["code_tb_ind_obs"]])
code = c(code, current_ana[["code_components"]][["code_tb_ind_params"]])
}
}
# if at least one analysis was found then we
# attach the nps definition code
if(ana_found){
# This will fetch the nps table based on the NCA.yaml file bundled in the
# exporte zip file:
nps_def = paste0('NCA_nps = NCA_fetch_np_meta(file.path("config", "',
basename(state[["MOD_yaml_file"]]),
'"))[["summary"]]')
code = c("# NCA analyses ----", "", nps_def, code)
} else {
# Otherwise we just pass a comment that there were
# no valid analyses found
code = "# No valid NCA analyses were found"
}
code}
#'@export
#'@title Append Report Elements
#'@description Takes an NCA state object and appends any reportable elements
#'for the specified report type. On NCA analyses that are in a "good" state
#'will be reported. Those not in a good state will be ignored.
#'@param state NCA state from \code{NCA_fetch_state()}
#'@param rpt Report with the current content of the report which will be appended to in
#'this function. For details on the structure see the documentation for \code{\link[formods]{FM_generate_report}}.
#'@param rpttype Type of report to generate (supported "xlsx", "pptx", "docx").
#'@param gen_code_only Boolean value indicating that only code should be
#'generated (\code{FALSE}).
#'@return list containing the following elements
#'\itemize{
#' \item{isgood:} Return status of the function.
#' \item{hasrptele:} Boolean indicator if the module has any reportable elements.
#' \item{code:} Code to create report elements.
#' \item{msgs:} Messages to be passed back to the user.
#' \item{rpt:} Report with any additions passed back to the user.
#'}
#'@seealso \code{\link{FM_generate_report}}
#'@examples
#'# We need a state object to use below
#'sess_res = NCA_test_mksession(session=list(), full_session=FALSE)
#'state = sess_res$state
#'
#'# here we need an empty report object for tabular data
#'rpt = list(summary = list(), sheets=list())
#'
#'# Now we append the report indicating we want
#'# Excel output:
#'rpt_res = NCA_append_report(state,
#' rpt = rpt,
#' rpttype = "xlsx",
#' gen_code_only = TRUE)
#'
#'# Shows if report elements are present
#'rpt_res$hasrptele
#'
#'# Code chunk to generate report element
#'cat(paste(rpt_res$code, collapse="\n"))
NCA_append_report = function(state, rpt, rpttype, gen_code_only=FALSE){
isgood = TRUE
hasrptele = FALSE
code = c()
msgs = c()
# The NCA module supports the following report types:
supported_rpttypes = c("xlsx", "pptx", "docx")
if(rpttype %in% supported_rpttypes){
for(ana in names(state[["NCA"]][["anas"]])){
# Only the analyses that are in a good state are reported
tmp_ana = state[["NCA"]][["anas"]][[ana]]
if(tmp_ana[["isgood"]]){
# We're creating a list for to pass into the try/catch enviornment.
# This will create all of the NCA-related objects so that they can be
# used for reporting.
tc_env = list()
for(obj_key in names(tmp_ana[["objs"]])){
tc_env[[ tmp_ana[["objs"]][[obj_key]][["name"]] ]] =
tmp_ana[["objs"]][[obj_key]][["value"]]
}
# Here we process the analyses based on the report type selected:
#----------------------------------------------------------
# Excel
if(rpttype == "xlsx"){
hasrptele = TRUE
#----------------------------------------------------------
# Table of final PKNCA results
ind_sheet_name = paste0(tmp_ana[["id"]], "_RES")
# This appends the data frame to the report list
code_chunk = paste0('rpt[["sheets"]][["',
ind_sheet_name,
'"]]=',
tmp_ana[["objs"]][["tb_ind_params"]][["name"]],
'[["one_table"]]')
# Evaluating the code
if(!gen_code_only){
# We have to make sure the try/catch environment is using the
# latest rpt object, so before we cal FM_tc, we need to update the
# rpt object. This is done below for each FM_tc call:
tc_env[["rpt"]] = rpt
tc_res = formods::FM_tc(capture="rpt", cmd=code_chunk, tc_env = tc_env)
if(tc_res[["isgood"]]){
rpt = tc_res[["capture"]][["rpt"]]
} else {
formods::FM_le(state, "Failed to add report element: ")
formods::FM_le(state, paste0(" Analysis: ", ana))
formods::FM_le(state, paste0(" Table: ", ind_sheet_name))
if(!is.null(tc_res[["msgs"]])){
formods::FM_le(state, tc_res[["msgs"]])
}
}
}
# Appending to returned code
code = c(code, code_chunk)
# Appends the mapping between sheet name and description:
code_chunk = c('rpt[["summary"]] = rbind(rpt[["summary"]],',
" data.frame(",
paste0(' Sheet_Name="', ind_sheet_name, '",'),
paste0(' Description="', tmp_ana[["key"]], ' (indiviudal results)"'),
" )",
')')
# Evaluating the code
if(!gen_code_only){
tc_env[["rpt"]] = rpt
tc_res = formods::FM_tc(capture="rpt", cmd=code_chunk, tc_env = tc_env)
if(tc_res[["isgood"]]){
rpt = tc_res[["capture"]][["rpt"]]
} else {
formods::FM_le(state, "Failed to add report element: ")
formods::FM_le(state, paste0(" Analysis: ", ana))
formods::FM_le(state, paste0(" Table: ", ind_sheet_name))
if(!is.null(tc_res[["msgs"]])){
formods::FM_le(state, tc_res[["msgs"]])
}
}
}
# Appending to returned code
code = c(code, code_chunk)
#----------------------------------------------------------
# Table of raw PKNCA results
raw_sheet_name = paste0(tmp_ana[["id"]], "_RAW")
# This appends the data frame to the report list
code_chunk = paste0('rpt[["sheets"]][["',
raw_sheet_name,
'"]]=as.data.frame(',
tmp_ana[["objs"]][["res"]][["name"]],
")")
# Evaluating the code
if(!gen_code_only){
tc_env[["rpt"]] = rpt
tc_res = formods::FM_tc(capture="rpt", cmd=code_chunk, tc_env = tc_env)
if(tc_res[["isgood"]]){
rpt = tc_res[["capture"]][["rpt"]]
} else {
formods::FM_le(state, "Failed to add report element: ")
formods::FM_le(state, paste0(" Analysis: ", ana))
formods::FM_le(state, paste0(" Table: ", ind_sheet_name))
if(!is.null(tc_res[["msgs"]])){
formods::FM_le(state, tc_res[["msgs"]])
}
}
}
# Appending to returned code
code = c(code, code_chunk)
# Appends the mapping between sheet name and description:
code_chunk = c('rpt[["summary"]] = rbind(rpt[["summary"]],',
" data.frame(",
paste0(' Sheet_Name="', raw_sheet_name, '",'),
paste0(' Description="', tmp_ana[["key"]], ' (raw NCA results)"'),
" )",
')')
# Evaluating the code
if(!gen_code_only){
tc_env[["rpt"]] = rpt
tc_res = formods::FM_tc(capture="rpt", cmd=code_chunk, tc_env = tc_env)
if(tc_res[["isgood"]]){
rpt = tc_res[["capture"]][["rpt"]]
} else {
formods::FM_le(state, "Failed to add report element: ")
formods::FM_le(state, paste0(" Analysis: ", ana))
formods::FM_le(state, paste0(" Table: ", ind_sheet_name))
if(!is.null(tc_res[["msgs"]])){
formods::FM_le(state, tc_res[["msgs"]])
}
}
}
# Appending to returned code
code = c(code, code_chunk)
#----------------------------------------------------------
}
#----------------------------------------------------------
# Word or PowerPoint
if(rpttype %in% c("docx", "pptx")){
#----------------------------------------------------------
# Reporting figures:
for(fid in names(state[["MC"]][["reporting"]][["figures"]])){
# This is the list name contiaing the selected report outputs for
# this figure
fid_rpt = paste0(fid, "_rpt")
if(rpttype %in% tmp_ana[[fid_rpt]]){
# This is the key that can be used in referencing the figure in
# Word
fig_id = paste0("fig_", tmp_ana[["id"]], "_", fid)
figisgood = TRUE
hasrptele = TRUE
figmsgs = c()
if(fid %in% names(tmp_ana[["objs"]])){
if(!is.null(names(tmp_ana[["objs"]][[fid]][["value"]][["figures"]]))){
# This is the pages of figures associated with the current
# figure:
tmp_figs = tmp_ana[["objs"]][[fid]][["value"]][["figures"]]
notes_str = NULL
# This is the counter used for creating captions
fig_idx = 1
for(tmp_fig in names(tmp_figs)){
# This is a character string that references the current
# ggplot object.
fg_object_name = paste0(tmp_ana[["objs"]][[fid]][["name"]],
'[["figures"]]',
'[["', tmp_fig, '"]][["gg"]]')
# Here we create the code chunk for either a powerpoint
# or docx whichever the report type
code_chunk = NULL
if(rpttype == "pptx"){
# Here we construct the title for the figure based on the
# specification in the configuration file:
if(length(names(tmp_figs)) > 1){
fig_title = state[["MC"]][["reporting"]][["figures"]][[fid]][["title_multiple"]]
fig_sub_title = state[["MC"]][["reporting"]][["figures"]][[fid]][["sub_title_multiple"]]
} else {
fig_title = state[["MC"]][["reporting"]][["figures"]][[fid]][["title_single"]]
fig_sub_title = state[["MC"]][["reporting"]][["figures"]][[fid]][["sub_title_single"]]
}
if(is.null(fig_title)){
title_code_chunk = NULL
}else{
fig_title = stringr::str_replace_all(fig_title, "===NCADESC===", tmp_ana[["key"]])
fig_title = stringr::str_replace_all(fig_title, "===FIGNUM===", as.character(fig_idx))
fig_title = stringr::str_replace_all(fig_title, "===FIGTOT===", as.character(length(names(tmp_figs))))
title_code_chunk = c(
paste0(' title = list( content = "', fig_title,'",'),
' type = "text"), ')
}
if(is.null(fig_sub_title)){
sub_title_code_chunk = NULL
}else{
sub_title_code_chunk = NULL
fig_sub_title = stringr::str_replace_all(fig_sub_title, "===NCADESC===", tmp_ana[["key"]])
fig_sub_title = stringr::str_replace_all(fig_sub_title, "===FIGNUM===", as.character(fig_idx))
fig_sub_title = stringr::str_replace_all(fig_sub_title, "===FIGTOT===", as.character(length(names(tmp_figs))))
sub_title_code_chunk = c(
paste0(' sub_title = list( content = "', fig_sub_title,'",'),
' type = "text"), ')
}
code_chunk = c(
paste0('# Inserting figure: ', fig_id),
'rpt = onbrand::report_add_slide(rpt, ',
' template = "content_list", ',
' elements = list( ',
title_code_chunk,
sub_title_code_chunk,
paste0(' content_body = list( content = ', fg_object_name, ', '),
' type = "ggplot"))) '
)
}
if(rpttype == "docx"){
# Here we construct the caption for the figure based on the
# specification in the configuration file:
if(length(names(tmp_figs)) > 1){
fig_caption = state[["MC"]][["reporting"]][["figures"]][[fid]][["caption_multiple"]]
} else {
fig_caption = state[["MC"]][["reporting"]][["figures"]][[fid]][["caption_single"]]
}
fig_caption = stringr::str_replace_all(fig_caption, "===NCADESC===", tmp_ana[["key"]])
fig_caption = stringr::str_replace_all(fig_caption, "===FIGNUM===", as.character(fig_idx))
fig_caption = stringr::str_replace_all(fig_caption, "===FIGTOT===", as.character(length(names(tmp_figs))))
code_chunk = c(
paste0('# Inserting figure: ', fig_id),
'rpt = onbrand::report_add_doc_content(rpt,',
' type = "ggplot",',
' content = list(',
notes_str,
paste0(' image = ', fg_object_name, ','),
paste0(' key = "', fig_id, '",'),
paste0(' caption_format = "',state[["MC"]][["reporting"]][["text_format"]],'",'),
paste0(' caption = "',fig_caption,'"))'),
'# adding a page break',
'rpt = onbrand::report_add_doc_content(rpt,',
' type = "break",',
' content = NULL)',
' '
)
}
# Now we evaluate the code chunk
if(!is.null(code_chunk)){
# Evaluating the code
if(!gen_code_only){
tc_env[["rpt"]] = rpt
tc_res = formods::FM_tc(capture="rpt", cmd=code_chunk, tc_env = tc_env)
if(tc_res[["isgood"]]){
fig_idx = fig_idx + 1
rpt = tc_res[["capture"]][["rpt"]]
} else {
formods::FM_le(state, "Failed to add report element: ")
formods::FM_le(state, paste0(" Analysis: ", ana))
formods::FM_le(state, paste0(" fig_id: ", fig_id))
formods::FM_le(state, paste0(" figure: ", tmp_fig))
if(!is.null(tc_res[["msgs"]])){
formods::FM_le(state, tc_res[["msgs"]])
}
}
}
# Appending to returned code
code = c(code, code_chunk)
}
}
} else {
figisgood = FALSE
figmsgs = c(figmsgs, paste0(" Figure id (", fid,") has no figures."))
}
} else {
figisgood = FALSE
figmsgs = c(figmsgs, paste0(" Figure id (", fid,") was not found."))
}
if(!figisgood){
formods::FM_le(state, "Failed to add report element: ")
formods::FM_le(state, paste0(" Analysis: ", ana))
formods::FM_le(state, paste0(" Figure: ", fid_rpt))
formods::FM_le(state, figmsgs)
}
}
}
#----------------------------------------------------------
# Reporting tables:
for(tid in names(state[["MC"]][["reporting"]][["tables"]])){
# This is the list name contiaing the selected report outputs for
# this table
tid_rpt = paste0(tid, "_rpt")
if(rpttype %in% tmp_ana[[tid_rpt]]){
# This is the key that can be used in referencing the table in
# Word
tab_id = paste0("tab_", tmp_ana[["id"]], "_", tid)
tabisgood = TRUE
hasrptele = TRUE
tabmsgs = c()
if(tid %in% names(tmp_ana[["objs"]])){
if(!is.null(names(tmp_ana[["objs"]][[tid]][["value"]][["tables"]]))){
# This is the pages of tables associated with the current
# table:
tmp_tabs = tmp_ana[["objs"]][[tid]][["value"]][["tables"]]
# This is the counter used for creating captions
tab_idx = 1
for(tmp_tab in names(tmp_tabs)){
notes_str = NULL
# This is a character string that references the current
# ggplot object.
tb_object_name = paste0(tmp_ana[["objs"]][[tid]][["name"]],
'[["tables"]]',
'[["', tmp_tab, '"]][["ft"]]')
# These are the notes for the current table
tb_notes = tmp_ana[["objs"]][[tid]][["value"]][["tables"]][[tmp_tab]][["notes"]]
if(!is.null(tb_notes)){
tb_notes_full = c()
for(tb_note in tb_notes){
tb_note_full = NULL
if(tb_note %in% names(state[["MC"]][["reporting"]][["notes"]])){
tb_note_full = state[["MC"]][["reporting"]][["notes"]][[tb_note]]
}
# If we didn't find the full note we flag that
# here. This probably shouldn't happen but it's not
# important enough to stop everything.
if(is.null(tb_note_full)){
formods::FM_le(state, "Note not added. Note string: ", tb_note)
formods::FM_le(state, paste0(" Analysis: ", ana))
formods::FM_le(state, paste0(" tab_id: ", tab_id))
formods::FM_le(state, paste0(" table: ", tmp_tab))
} else {
tb_notes_full = c(tb_notes_full, paste0(tb_note, ": ", tb_note_full))
}
}
# If we made it this far and we've found some
# notes then we create the actual notes.
if(!is.null(tb_notes_full)){
notes_str = c(
paste0(' notes = "', paste0(tb_notes_full, collapse=", "),'",'),
paste0(' notes_format = "',state[["MC"]][["reporting"]][["text_format"]],'",')
)
}
}
# Here we create the code chunk for either a powerpoint
# or docx whichever the report type
code_chunk = NULL
if(rpttype == "pptx"){
}
if(rpttype == "docx"){
# Here we construct the caption for the table based on the
# specification in the configuration file:
if(length(names(tmp_tabs)) > 1){
tab_caption = state[["MC"]][["reporting"]][["tables"]][[tid]][["caption_multiple"]]
} else {
tab_caption = state[["MC"]][["reporting"]][["tables"]][[tid]][["caption_single"]]
}
tab_caption = stringr::str_replace_all(tab_caption, "===NCADESC===", tmp_ana[["key"]])
tab_caption = stringr::str_replace_all(tab_caption, "===TABNUM===", as.character(tab_idx))
tab_caption = stringr::str_replace_all(tab_caption, "===TABTOT===", as.character(length(names(tmp_tabs))))
code_chunk = c(
paste0('# Inserting table: ', fig_id),
'rpt = onbrand::report_add_doc_content(rpt,',
' type = "flextable_object",',
' content = list(',
notes_str,
paste0(' ft = ', tb_object_name, ','),
paste0(' key = "', tab_id, '",'),
paste0(' caption_format = "',state[["MC"]][["reporting"]][["text_format"]],'",'),
paste0(' caption = "',tab_caption,'"))'),
'# adding a page break',
'rpt = onbrand::report_add_doc_content(rpt,',
' type = "break",',
' content = NULL)',
' '
)
}
# JMH
#browser()
# Now we evaluate the code chunk
if(!is.null(code_chunk)){
# Evaluating the code
if(!gen_code_only){
tc_env[["rpt"]] = rpt
tc_res = formods::FM_tc(capture="rpt", cmd=code_chunk, tc_env = tc_env)
if(tc_res[["isgood"]]){
tab_idx = tab_idx + 1
rpt = tc_res[["capture"]][["rpt"]]
} else {
formods::FM_le(state, "Failed to add report element: ")
formods::FM_le(state, paste0(" Analysis: ", ana))
formods::FM_le(state, paste0(" tab_id: ", tab_id))
formods::FM_le(state, paste0(" Table: ", tmp_tab))
if(!is.null(tc_res[["msgs"]])){
formods::FM_le(state, tc_res[["msgs"]])
}
}
}
# Appending to returned code
code = c(code, code_chunk)
}
}
} else {
tabisgood = FALSE
tabmsgs = c(tabmsgs, paste0(" Table id (", tid,") has no tables."))
}
} else {
tabisgood = FALSE
tabmsgs = c(tabmsgs, paste0(" Table id (", tid,") was not found."))
}
if(!tabisgood){
formods::FM_le(state, "Failed to add report element: ")
formods::FM_le(state, paste0(" Analysis: ", ana))
formods::FM_le(state, paste0(" Table: ", tid_rpt))
formods::FM_le(state, tabmsgs)
}
}
}
}
}
}
}
res = list(
isgood = isgood,
hasrptele = hasrptele,
code = code,
msgs = msgs,
rpt = rpt
)
res}
#'@export
#'@title Fetch Module Datasets
#'@description Fetches the datasets contained in the module
#'@param state NCA state from \code{NCA_fetch_state()}
#'@return list containing the following elements
#'\itemize{
#' \item{isgood:} Return status of the function.
#' \item{hasds:} Boolean indicator if the module has any datasets
#' \item{msgs:} Messages to be passed back to the user.
#' \item{ds:} List with datasets. Each list element has the name of
#' the R-object for that dataset. Each element has the following structure:
#' \itemize{
#' \item{label: Text label for the dataset}
#' \item{MOD_TYPE: Short name for the type of module.}
#' \item{id: module ID}
#' \item{DS: Dataframe containing the actual dataset.}
#' \item{DSMETA: Metadata describing DS}
#' \item{code: Complete code to build dataset.}
#' \item{checksum: Module checksum.}
#' \item{DSchecksum: Dataset checksum.}
#' }
#'}
#'@examples
#'# We need a state object to use below
#'sess_res = NCA_test_mksession(session=list(), full_session=FALSE)
#'state = sess_res$state
#'
#'myDs = NCA_fetch_ds(state)
NCA_fetch_ds = function(state){
hasds = FALSE
isgood = TRUE
msgs = c()
ds = list()
# Empty list for new datasets
NEWDS = list(label = NULL,
MOD_TYPE = "NCA",
id = state[["ID"]],
DS = NULL,
DSMETA = NULL,
code = NULL,
checksum = NULL,
DSchecksum = NULL)
if(length(names(state[["NCA"]][["anas"]]))>0){
for(ana_name in names(state[["NCA"]][["anas"]])){
# This shoudl contain the current analys, and we only
# process it if it's in a good state.
curr_ana = state[["NCA"]][["anas"]][[ana_name]]
if(curr_ana[["isgood"]]){
# Flipping the hasds switch:
hasds = TRUE
#-----------------------------------------------------------
# Adding the raw NCA data
tb_name = paste0(curr_ana[["id"]], "_raw")
tb_label = paste0(curr_ana[["key"]], " (Raw)")
# This will add only columns that are present in the dataset
# to the metadata
DSMETA = list()
for(cname in names(curr_ana[["objs"]][["tb_ind_params"]][["value"]][["raw_nca"]])){
if(cname %in% names(state[["MC"]][["labels"]][["PKNCA_raw"]])){
DSMETA[[cname]] = state[["MC"]][["labels"]][["PKNCA_raw"]][[cname]]
} else {
DSMETA[[cname]] = "Not defined"
formods::FM_le(state, paste0("No metadata for PKNCA_raw: ", cname))
}
}
# Creating an emtpy dataset
ds[[tb_name]] = NEWDS
ds[[tb_name]][["label"]] = tb_label
ds[[tb_name]][["DS"]] = curr_ana[["objs"]][["tb_ind_params"]][["value"]][["raw_nca"]]
ds[[tb_name]][["DSMETA"]] = DSMETA
ds[[tb_name]][["code"]] = curr_ana[["code"]]
ds[[tb_name]][["checksum"]] = state[["NCA"]][["checksum"]]
ds[[tb_name]][["DSchecksum"]] = digest::digest(curr_ana[["objs"]][["tb_ind_params"]][["value"]][["raw_nca"]],
algo=c("md5"))
#-----------------------------------------------------------
# Adding the indiviudal parameters
tb_name = paste0(curr_ana[["id"]], "_ind")
tb_label = paste0(curr_ana[["key"]], " (Individual Parameters)")
# This will add only columns that are present in the dataset
# to the metadata
DSMETA = list()
if(is.null(curr_ana[["objs"]][["tb_ind_params"]][["value"]][["one_header"]])){
formods::FM_le(state, paste0("No headers individual NCA parameter header: ", tb_name,":", tb_label))
} else {
for(cname in names(curr_ana[["objs"]][["tb_ind_params"]][["value"]][["one_table"]])){
if(cname %in% names(curr_ana[["objs"]][["tb_ind_params"]][["value"]][["one_header"]])){
DSMETA[[cname]] = paste(curr_ana[["objs"]][["tb_ind_params"]][["value"]][["one_header"]][[cname]], collapse=" ")
} else {
DSMETA[[cname]] = "Not defined"
formods::FM_le(state, paste0("No metadata for individual NCA parameter header: ", cname))
}
}
}
# Creating an emtpy dataset
ds[[tb_name]] = NEWDS
ds[[tb_name]][["label"]] = tb_label
ds[[tb_name]][["DS"]] = curr_ana[["objs"]][["tb_ind_params"]][["value"]][["one_table"]]
ds[[tb_name]][["DSMETA"]] = DSMETA
ds[[tb_name]][["code"]] = curr_ana[["code"]]
ds[[tb_name]][["checksum"]] = state[["NCA"]][["checksum"]]
ds[[tb_name]][["DSchecksum"]] = digest::digest(curr_ana[["objs"]][["tb_ind_params"]][["value"]][["one_table"]],
algo=c("md5"))
#-----------------------------------------------------------
}
}
}
res = list(hasds = hasds,
isgood = isgood,
msgs = msgs,
ds = ds)
res}
#'@export
#'@title Initialize New Analysis
#'@description Creates a new NCA analysis in an NCA module
#'@param state NCA state from \code{NCA_fetch_state()}
#'@return NCA state object containing a new empty analysis and that analysis
#'is set as the current active analyisis
#'@example inst/test_apps/NCA_funcs.R
NCA_new_ana = function(state){
# Incrementing the analysis counter
state[["NCA"]][["ana_cntr"]] = state[["NCA"]][["ana_cntr"]] + 1
# Creating a default NCA ID
nca_id = paste0("NCA_", state[["NCA"]][["ana_cntr"]])
# Pulling out the dataset views
DSV = state[["NCA"]][["DSV"]]
# Using the default dsview for the new analysis
ana_dsview = names(DSV[["ds"]])[1]
nca_object_name = paste0("NCA_", state[["MC"]][["nca_object_name"]], "_", state[["NCA"]][["ana_cntr"]])
# This is the object that contains the different components of
# the analysis list:
nca_def =
list(key = nca_id,
id = nca_id,
idx = state[["NCA"]][["ana_cntr"]],
nca_object_name = nca_object_name,
objs = list(),
msgs = c("New analysis"),
ana_dsview = ana_dsview,
nca_res = NULL, # JMH is this even used?
nca_config = state[["NCA"]][["nca_config"]][["default"]],
checksum = digest::digest(NULL, algo=c("md5")),
ana_scenario = "",
fig_view = "fg_ind_obs",
dose_from = "",
fg_ind_obs_nrow = "",
fg_ind_obs_ncol = "",
fg_ind_obs_logy = TRUE,
fg_ind_obs_rpt = c("docx", "pptx"),
tb_ind_obs_rpt = c("docx"),
tb_ind_params_rpt = c("docx"),
tb_sum_params_rpt = c("pptx"),
tab_view = "tb_ind_obs",
tab_type = "",
code_components = NULL,
code = NULL,
fig_type = "",
col_id = "", # The col_* values will be populated later
col_conc = "",
col_dose = "",
col_dur = "",
col_route = "",
col_time = "",
col_ntime = "",
col_group = "",
col_evid = "",
col_cycle = "",
curr_fg_ind_obs = "", # Current figure page
curr_tb_ind_obs = "", # Current table page
curr_tb_ind_params = "", #
curr_tb_sum_params = "", #
include_units = "",
intervals = NULL, # holds intervals added to the analysis
interval_range = c("0", "Inf"), # Current interval in the interface.
nca_parameters = "",
sampling = "",
tab_view = "",
units_conc = "",
units_dose = "",
units_amt = "",
units_time = "",
notes = "",
isgood = FALSE)
# I think these were really only needed for the figure
# page = 1,
# num_pages = 1,
# add_isgood = TRUE,
# elements_table = NULL)
# Default ds
ds = state[["NCA"]][["DSV"]][["ds"]][[ana_dsview]]
# These are the columns in the dataset:
dscols = names(ds[["DS"]])
# Initializing the columns
nca_def[["col_id"]] = NCA_find_col(
patterns = state[["MC"]][["detect_col"]][["id"]],
dscols = dscols)
nca_def[["col_time"]] = NCA_find_col(
patterns = state[["MC"]][["detect_col"]][["time"]],
dscols = dscols)
nca_def[["col_ntime"]] = NCA_find_col(
patterns = state[["MC"]][["detect_col"]][["ntime"]],
dscols = dscols)
nca_def[["col_dose"]] = NCA_find_col(
patterns = state[["MC"]][["detect_col"]][["dose"]],
dscols = dscols)
nca_def[["col_dur"]] = NCA_find_col(
patterns = state[["MC"]][["detect_col"]][["dur"]],
null_ok = TRUE,
dscols = dscols)
nca_def[["col_analyte"]] = NCA_find_col(
patterns = state[["MC"]][["detect_col"]][["analyte"]],
null_ok = TRUE,
dscols = dscols)
nca_def[["col_conc"]] = NCA_find_col(
patterns = state[["MC"]][["detect_col"]][["conc"]],
dscols = dscols)
nca_def[["col_route"]] = NCA_find_col(
patterns = state[["MC"]][["detect_col"]][["route"]],
dscols = dscols)
# Setting default dose determination source
nca_def[["dose_from"]] = state[["MC"]][["formatting"]][["dose_from"]][["default"]]
# Setting the units switch for the analysis
nca_def[["include_units"]] = state[["MC"]][["units"]][["include_units"]]
# and also for the counters:
state[["NCA"]][["button_counters"]][["switch_ana_include_units"]] =
state[["MC"]][["units"]][["include_units"]]
#state[["NCA"]][["button_counters"]][["switch_ana_fig"]] =
#state[["MC"]][["units"]][["fig_interactive"]]
# add the default units
nca_def[["units_conc"]] = state[["MC"]][["units"]][["conc_def"]]
nca_def[["units_time"]] = state[["MC"]][["units"]][["time_def"]]
nca_def[["units_dose"]] = state[["MC"]][["units"]][["dose_def"]]
nca_def[["units_amt"]] = state[["MC"]][["units"]][["amt_def"]]
# Setting the new analysis id as the current analysis
state[["NCA"]][["current_ana"]] = nca_id
# Setting default values for figures and tables
nca_def[["fg_ind_obs_nrow"]] = state[["MC"]][["formatting"]][["preview"]][["nrow"]]
nca_def[["fg_ind_obs_ncol"]] = state[["MC"]][["formatting"]][["preview"]][["ncol"]]
nca_def[["fg_ind_obs_logy"]] = state[["MC"]][["formatting"]][["preview"]][["logy"]]
nca_def[["fig_type"]] = state[["MC"]][["formatting"]][["preview"]][["fig_type"]]
nca_def[["tab_type"]] = state[["MC"]][["formatting"]][["preview"]][["tab_type"]]
# Setting scenario specific options for the default scenario
ana_scenarios = state[["MC"]][["ana_scenarios"]]
ana_scenario_def = state[["MC"]][["ana_scenario_def"]]
nca_def[["ana_scenario"]] = ana_scenario_def
nca_def[["nca_parameters"]] = ana_scenarios[[ana_scenario_def]][["nca_parameters"]]
nca_def[["sampling"]] = ana_scenarios[[ana_scenario_def]][["sampling"]]
# Storing the empty analysis object in the state
state = NCA_set_current_ana(state, nca_def)
state}
#'@export
#'@title Sets Current Analysis
#'@description Takes an NCA state and an analysis list and sets that figure list
#'as the value for the active figure
#'@param state NCA state from \code{NCA_fetch_state()}
#'@param ana Analysis list from \code{NCA_fetch_current_ana}
#'@return State with the current analysis updated
#'@example inst/test_apps/NCA_funcs.R
NCA_set_current_ana = function(state, ana){
# Current analysis ID
ana_id = state[["NCA"]][["current_ana"]]
# Current analysis
state[["NCA"]][["anas"]][[ana_id]] = ana
state}
#'@export
#'@title Determines Default Column Name
#'@description Based on the current analysis, value from the UI, an optional
#'list of patterns to search, and column names from a dataset this function
#'tries to find a default value for a column in the analysis (e.g. subject id,
#'dose, concentration, etc).
#'
#'Generally the following is done:
#'
#' - If curr_ui has a non-NULL, non-"" value it is compared to dscols. If it
#' is found there that value is returned.
#'
#' - If not then the patterns are considered. If the patterns from the YAML
#' file are not NULL they are compared sequentially to the columns names.
#' The first match found is returned.
#'
#' - If nothing is found then the first value of dscols is returned.
#'
#'@param curr_ana Current value in the analysis
#'@param curr_ui Current value in UI
#'@param patterns List of regular expression patterns to consider.
#'@param dscols Columns from the dataset.
#'@param null_ok Logical value indicating if a null result (nothing found) is
#' OK (default: \code{FALSE})
#'@return Name of column found based on the rules above.
#'@example inst/test_apps/NCA_funcs.R
NCA_find_col = function(curr_ana = NULL,
curr_ui = NULL,
patterns = NULL,
dscols,
null_ok = FALSE){
value = NULL
COL_FOUND = FALSE
# if curr_ana is supplied and it exisits in the dataset then that is used.
if(!is.null(curr_ana)){
if(curr_ana %in% dscols){
value = curr_ana
COL_FOUND = TRUE
}
}
if(!COL_FOUND){
if(!is.null(curr_ui)){
CURR_UI_HAS_DATA = FALSE
# Now we see if it has been defined already:
if(length(curr_ui)>1){
CURR_UI_HAS_DATA = TRUE
} else if(curr_ui != ""){
CURR_UI_HAS_DATA = TRUE
}
if(CURR_UI_HAS_DATA){
# If it has we see if it's in the dataset columns. If we switched
# views we may have a view where this column doesnt exist
if(any(curr_ui %in% dscols)){
COL_FOUND = TRUE
value = curr_ui[curr_ui %in% dscols]
}
}
}
}
# If it's not found then we need to see if there is a detection
# pattern:
if(!COL_FOUND){
if(!is.null(patterns)){
for(pattern in patterns){
if(!COL_FOUND){
if(any(stringr::str_detect(string=dscols, pattern=pattern))){
COL_FOUND = TRUE
value = dscols[stringr::str_detect(string=dscols, pattern=pattern)][1]
}
}
}
}
}
# If we made it this far and have not found the column we
# default to the first column in the dataset:
if(!COL_FOUND & !null_ok){
value = dscols[1]
}
value}
#'@export
#'@title Fetches Current Analysis
#'@description Takes an NCA state and returns the current active analysis
#'@param state NCA state from \code{NCA_fetch_state()}
#'@return List containing the details of the current analysis. The structure
#'of this list is the same as the structure of \code{state$NCA$anas} in the output of
#'\code{NCA_fetch_state()}.
#'@example inst/test_apps/NCA_funcs.R
NCA_fetch_current_ana = function(state){
# Current analysis ID
ana_id = state[["NCA"]][["current_ana"]]
# Current analysis
ana = state[["NCA"]][["anas"]][[ana_id]]
ana}
#'@export
#'@title Fetches PKNCA Metadata
#'@description Compiles Metadata from PKNCA
#'@return Dataframe containing PKCNA metadata for NCA parameters.
#'@examples
#' PKNCA_meta = NCA_fetch_PKNCA_meta()
#' utils::head(PKNCA_meta)
NCA_fetch_PKNCA_meta = function(){
res = list()
param_spec = PKNCA::get.interval.cols()
param_df = NULL
for(pname in names(param_spec)){
param_df = rbind(param_df,
data.frame(parameter = pname,
unit_type = param_spec[[pname]]$unit_type,
pretty_name = param_spec[[pname]]$pretty_name,
data_type = param_spec[[pname]]$datatype,
desc = param_spec[[pname]]$desc)
)
}
res = list(parameters = param_df)
res}
#'@export
#'@title Applies Route Mapping to Dataset
#'@description Used to convert nonstandard dose route values (i.e. "IV") to
#'standard values ("intravascular").
#'@param route_map List with names corresponding to the route replacement and
#' a vector of regular expressions to match.
#'@param route_col Column name with the route data.
#'@param DS Dataframe containing the dataset.
#'@return Dataset with the route mapping applied.
#'@examples
#' if(system.file(package="readxl") !=""){
#' library(readxl)
#' #loading a dataset
#' data_file = system.file(package="formods","test_data","TEST_DATA.xlsx")
#' myDS = readxl::read_excel(path=data_file, sheet="DATA")
#'
#' route_map = list(
#' intravascular = c("^(?i)iv$"),
#' extravascular = c("^(?i)sc$", "^(?i)oral")
#' )
#'
#' utils::head(myDS[["ROUTE"]])
#'
#' myDS = apply_route_map(route_map = route_map,
#' route_col = "ROUTE",
#' DS = myDS)
#'
#' utils::head(myDS[["ROUTE"]])
#'}
apply_route_map = function(route_map = list(),
route_col = NULL,
DS = NULL){
for(new_route in names(route_map)){
evalstr =
paste0(
"DS = ",
"dplyr::mutate(DS, ",route_col,"=",
" ifelse(stringr::str_detect(pattern = paste0(route_map[[new_route]], collapse='|'), ",
" string = ", route_col,"),",
" new_route,", route_col,"))"
)
eval(parse(text=evalstr))
}
DS}
#'@export
#'@title Fetches Details About Data Requirements
#'@description Use this to get information about data formats.
#'@param MOD_yaml_file Module configuration file with MC as main section.
#'@return List with details about the data formats
#'@examples
#' NCA_fetch_data_format()
NCA_fetch_data_format = function(
MOD_yaml_file = system.file(package="ruminate","templates","NCA.yaml")){
MC = yaml::read_yaml(MOD_yaml_file)
res = NULL
for(ridx in 1:length(MC[["MC"]][["data_format"]][["columns"]])){
entry = MC[["MC"]][["data_format"]][["columns"]][[ridx]][["entry"]]
res = rbind(res, as.data.frame(entry))
}
res}
#'@export
#'@title Fetches NCA Parameter Meta Information
#'@description This provides meta information about NCA parameters. This
#'includes parameter names, text descriptions, formatting (md and LaTeX).
#'@param MOD_yaml_file Module configuration file with MC as main section.
#'@return List with the following elements:
#' \itemize{
#' \item{choices:} List parameter choices grouped by values specified in the module configuration file.
#' \item{summary:} Data frame with meta data about the NCA parameters with
#' the following columns:
#' \itemize{
#' \item{parameter:} Name of parameter in PKNCA.
#' \item{text:} Name of parameter in plain text.
#' \item{md:} Parameter name formatted in Markdown.
#' \item{latex:} Parameter name formatted using LaTeX.
#' \item{description:} Verbose description in plain text for the parameter.
#' }
#'}
#'@examples
#' NCA_fetch_np_meta()
NCA_fetch_np_meta = function(
MOD_yaml_file = system.file(package="ruminate","templates","NCA.yaml")){
# Reading in the yaml file
MOD_config = yaml::read_yaml(MOD_yaml_file)
# This table summarizes the NCA parameters
np_summary = NULL
# This list contains the NCA parameter
# choices in the selection menu
np_choices = list()
# Default descriptors from PKNCA:
PKNCA_def = PKNCA::get.interval.cols()
for(nca_param in names(MOD_config[["MC"]][["nca_parameters"]])){
np_comps = MOD_config[["MC"]][["nca_parameters"]][[nca_param]]
if(is.null(PKNCA_def[[nca_param]][["pretty_name"]])){
latex_name = "no_name"
} else {
latex_name = PKNCA_def[[nca_param]][["pretty_name"]]
}
# This should catch any typos in the YAML file:
if(nca_param %in% names(PKNCA_def)){
# Null values for description and text indicate that we want
# to use the default values from PKNCA
if(is.null(np_comps[["description"]])){
np_comps[["description"]] = PKNCA_def[[nca_param]][["desc"]]
}
if(is.null(np_comps[["text"]])){
np_comps[["text"]] = latex_name
}
# Updating the choices list
np_choices[[ np_comps[["group"]] ]][[ np_comps[["text"]] ]] = nca_param
# Updating the summary table
np_summary =
rbind(np_summary,
data.frame(
parameter = nca_param,
text = np_comps[["text"]],
md = np_comps[["md"]],
latex = latex_name,
description = np_comps[["description"]])
)
} else {
msg = paste0("NCA: Parameter specified in YAML is not a valid PKNCA parameter: ", nca_param)
if(system.file(package="cli")==""){
message(msg)
} else {
FM_message(msg, entry_type="danger")
}
}
}
res = list(choices = np_choices,
summary = np_summary)
res}
#'@title Adds Analysis Interval to Current Analysis
#'@description Takes the start time, stop time, and NCA parameters and adds
#'them to the intervals table
#'@param state NCA state from \code{NCA_fetch_state()}
#'@param interval_start Interval start time (numeric).
#'@param interval_stop Interval stop time (numeric).
#'@param nca_parameters list of NCA parameters in the interval
#'@return State with interval added to the current analysis.
NCA_add_int = function(state, interval_start, interval_stop, nca_parameters){
# This is a summary table of the nca parameters with the
# PKNCA parameter name ("parameter") and a textual description ("text")
np_summary = state[["NCA"]][["nca_parameters"]][["summary"]]
# Pulling out the rows for the currently selected parameters:
np_summary = np_summary[np_summary[["parameter"]] %in% nca_parameters, ]
params_string = paste0(nca_parameters, collapse = ",")
names_string = paste0(np_summary[["text"]], collapse = ", ")
# Pulling out the current analysis
current_ana = NCA_fetch_current_ana(state)
# This determines if the new interval already exists:
int_exists = FALSE
if(!is.null(current_ana[["intervals"]])){
if(any((current_ana[["intervals"]][["start"]] == interval_start) &
(current_ana[["intervals"]][["stop"]] == interval_stop))){
int_exists = TRUE
}
}
# This adds a new interval:
if(int_exists){
# If the interval exists we replace the values
int_ridx = which(c((current_ana[["intervals"]][["start"]] == interval_start) & (current_ana[["intervals"]][["stop"]] == interval_stop)))
# Now we update just the parameters:
current_ana[["intervals"]][int_ridx, "np_actual"] = params_string
current_ana[["intervals"]][int_ridx, "np_text" ] = names_string
formods::FM_le(state, "NCA_add_int: update")
} else {
# If the interval does not exist we add a new one:
current_ana[["intervals"]] =
rbind( current_ana[["intervals"]],
data.frame("start" = interval_start,
"stop" = interval_stop,
"np_actual" = params_string,
"np_text" = names_string,
"delete" = FALSE))
formods::FM_le(state, "NCA_add_int: append")
}
# Saving the current analysis with the interval added/updated
state = NCA_set_current_ana(state, current_ana)
state}
#'@export
#'@title Processes Current Analysis to be Run
#'@description Takes the current analysis and checks different aspects to for
#'any issues to make sure it's good to go.
#'@param state NCA state from \code{NCA_fetch_state()}
#'@return Current analysis list with isgood and msgs set
#'@example inst/test_apps/NCA_funcs.R
NCA_process_current_ana = function(state){
omsgs = c()
amsgs = c()
isgood = TRUE
current_ana = NCA_fetch_current_ana(state)
# Analysis Dataset
ds = state[["NCA"]][["DSV"]][["ds"]][[current_ana[["ana_dsview"]]]]
#---------------------------------------------
# Checking the NCA options
for(nca_opt in names(current_ana[["nca_config"]])){
opt_value = current_ana[["nca_config"]][[nca_opt]][["value"]]
opt_type = current_ana[["nca_config"]][[nca_opt]][["type"]]
opt_label = current_ana[["nca_config"]][[nca_opt]][["label"]]
opt_pknca = current_ana[["nca_config"]][[nca_opt]][["pknca_option"]]
# First we check all of the numeric types
if(opt_type == "numeric"){
opt_value_proc = as.numeric(as.character(opt_value))
if(is.na(opt_value_proc)){
isgood = FALSE
omsgs = c(omsgs, paste0(opt_label, " (", nca_opt, ") should be numeric (found:", opt_value, ")." ))
} else {
# Storing the pocessed value as _the_ value. This will ensure that
# numbers stored as text are actually numbers now:
current_ana[["nca_config"]][[nca_opt]][["value"]] = opt_value_proc
# Checking specific numeric boundaries: positive numbers
if(opt_pknca %in% c("adj.r.squared.factor", "min.span.ratio")){
if(opt_value_proc < 0 ){
isgood = FALSE
omsgs = c(omsgs, paste0(opt_label, " [", nca_opt, "] should be a positive number (found:", opt_value, ")." ))
}
}
# Checking specific numeric boundaries: positive integers
if(opt_pknca %in% c("min.hl.points")){
if(opt_value_proc < 0 | (as.integer(opt_value_proc)-opt_value_proc) != 0){
isgood = FALSE
omsgs = c(omsgs, paste0(opt_label, " [", nca_opt, "] should be a positive integer (found:", opt_value, ")" ))
}
}
# Checking specific numeric boundaries: [0,1]
if(opt_pknca %in% c("max.missing", "min.hl.r.squared")){
# max_missing is a fraction and should be between 0 and 1
if(opt_value_proc < 0 | opt_value_proc > 1){
isgood = FALSE
omsgs = c(omsgs, paste0(opt_label, " [", nca_opt, "] should be between 0 and 1 (found:", opt_value, ")." ))
}
}
# Checking specific numeric boundaries: percentage
if(opt_pknca %in% c("max.aucinf.pext")){
if(opt_value_proc < 0 | opt_value_proc > 100){
isgood = FALSE
omsgs = c(omsgs, paste0(opt_label, " [", nca_opt, "] should be a percentage 0 and 100 (found:", opt_value, ")." ))
}
}
}
} else if(opt_type == "mixed"){
# Mixed options can be strings or numbers so we calculate the
# numeric value here to use below
opt_value_num = as.numeric(as.character(opt_value))
opt_value_str = as.character(opt_value)
if(opt_pknca %in% c("conc.na")){
OPT_ERR = FALSE
# If it's not a valid character value we check the numeric value
if(!(opt_value_str %in% c("drop"))){
# Here we check to make sure it's not NA and then if it's positive
if(is.na(opt_value_num)){
OPT_ERR = TRUE
} else if(opt_value_num < 0){
OPT_ERR = TRUE
}
if(OPT_ERR){
isgood = FALSE
omsgs = c(omsgs, paste0(opt_label, " [", nca_opt, '] should be "drop" or a positive numeric value (found:', opt_value, ")." ))
} else {
# Storing the processed numeric value as _the_ value.
current_ana[["nca_config"]][[nca_opt]][["value"]] = opt_value_num
}
} else {
# Storing the processed character value as _the_ value.
current_ana[["nca_config"]][[nca_opt]][["value"]] = opt_value_str
}
}
if(opt_pknca %in% c("conc.blq$first", "conc.blq$middle", "conc.blq$last")){
OPT_ERR = FALSE
# If it's not a valid character value we check the numeric value
if(!(opt_value_str %in% c("drop", "keep"))){
# Here we check to make sure it's not NA and then if it's positive
if(is.na(opt_value_num)){
OPT_ERR = TRUE
} else if(opt_value_num < 0){
OPT_ERR = TRUE
}
if(OPT_ERR){
isgood = FALSE
omsgs = c(omsgs, paste0(opt_label, " [", nca_opt, '] should be "drop", "keep" or a positive numeric value (found:', opt_value, ")." ))
} else {
# Storing the processed numeric value as _the_ value.
current_ana[["nca_config"]][[nca_opt]][["value"]] = opt_value_num
}
} else {
# Storing the processed character value as _the_ value.
current_ana[["nca_config"]][[nca_opt]][["value"]] = opt_value_str
}
}
} else if(opt_type == "character"){
if(opt_pknca %in% c("auc.method")){
if(!(opt_value %in% c("lin up/log down", "linear"))){
isgood = FALSE
omsgs = c(omsgs, paste0(opt_label, " [", nca_opt, '] should be either "lin up/log down" or "linear" (found:', opt_value, ")." ))
}
}
}
}
#---------------------------------------------
# Checking the analysis components
# Check interval start/stop
# JMH, BILL should I check for multiple instances of the same interval
# here?
if(is.null(current_ana[["intervals"]])){
isgood = FALSE
amsgs = c(amsgs, paste0("No intervals have been defined."))
}
# First we look at the numeric columns
num_cols = c("col_conc", "col_time", "col_ntime", "col_dose")
if(current_ana[["col_dur"]] != "N/A"){
num_cols = c(num_cols, "col_dur")
}
for(col_name in num_cols){
col_vals = ds[["DS"]][[ current_ana[[col_name]] ]]
if(is.numeric(col_vals)){
# I'm assuming that the duration column shouldn't have any NA values.
if(col_name %in% c("col_dur")){
if(any(is.na(current_ana[[col_name]]))){
isgood = FALSE
amsgs = c(amsgs, paste0("Column: ", current_ana[[col_name]], " should not have NA values."))
}
}
} else {
isgood = FALSE
amsgs = c(amsgs, paste0("Column: ", current_ana[[col_name]], " is not numeric."))
}
}
# Checking route information:
# Applying the route mapping
route_map = state[["MC"]][["detect_route"]]
DS_routed = apply_route_map(route_map=route_map, route_col=current_ana[["col_route"]], DS = ds[["DS"]])
# These are acceptable routes
OK_ROUTES = c("intravascular", "extravascular")
# Checking for broken routes
if( any(!(DS_routed[[current_ana[["col_route"]]]] %in% OK_ROUTES))){
isgood = FALSE
amsgs = c(amsgs, paste0("Route column, ", current_ana[["col_route"]], ", should be either: ", paste0(OK_ROUTES, collapse = ", ")))
}
# Checking column specifications for uniqueness. We need
# only 1 observation for each TIME, GROUP, ANALYTE combination
unique_cols = c()
# The time, cycle and id columns are required:
if(current_ana[["col_time"]] != ""){
unique_cols = c(unique_cols, current_ana[["col_time"]] )
}
if(current_ana[["col_id"]] != ""){
unique_cols = c(unique_cols, current_ana[["col_id"]] )
}
# Group can be empty as well
if(current_ana[["col_group"]] != ""){
unique_cols = c(unique_cols, current_ana[["col_group"]] )
}
# EVID can be empty as well
if(current_ana[["col_evid"]] != ""){
unique_cols = c(unique_cols, current_ana[["col_evid"]] )
}
# Cycle can be empty as well
if(current_ana[["col_cycle"]] != ""){
unique_cols = c(unique_cols, current_ana[["col_cycle"]] )
}
# analyte is select 1 so if it's not used it will be N/A
if(current_ana[["col_analyte"]] != "N/A"){
unique_cols = c(unique_cols, current_ana[["col_analyte"]] )
}
tmp_ds = ds[["DS"]] |>
dplyr::group_by_at(unique_cols) |>
dplyr::mutate(NUNIQUE = length(!!as.name(current_ana[["col_id"]])))
if(any(tmp_ds[["NUNIQUE"]]> 1)){
isgood = FALSE
amsgs = c(amsgs, paste0("The combination of ",
state[["MC"]][["labels"]][["select_ana_col_id"]], ", ",
state[["MC"]][["labels"]][["select_ana_col_time"]], ", ",
state[["MC"]][["labels"]][["select_ana_col_analyte"]], ", and ",
state[["MC"]][["labels"]][["select_ana_col_group"]],
" columns must be unique."))
amsgs = c(amsgs, paste0("This can commonly happen when you have multiple analytes and forgot to specify the analyte column. "))
amsgs = c(amsgs, paste0("Current values are:"))
amsgs = c(amsgs, paste0(" ", state[["MC"]][["labels"]][["select_ana_col_id"]], ": ", current_ana[["col_id"]] ))
amsgs = c(amsgs, paste0(" ", state[["MC"]][["labels"]][["select_ana_col_time"]], ": ", current_ana[["col_time"]] ))
amsgs = c(amsgs, paste0(" ", state[["MC"]][["labels"]][["select_ana_col_analyte"]], ": ", current_ana[["col_analyte"]] ))
amsgs = c(amsgs, paste0(" ", state[["MC"]][["labels"]][["select_ana_col_group"]], ": ", paste0(current_ana[["col_group"]], collapse="\n") ))
}
#---------------------------------------------
# Saving the status and messages
current_ana[["isgood"]] = isgood
current_ana[["msgs"]] = c(amsgs, omsgs)
current_ana}
#'@export
#'@title Builds NCA Code from ui Elements
#'@description Takes the current analysis in the state object and creates the
#'code to run the analysis
#'@param state NCA state from \code{NCA_fetch_state()}
#' JMH update the return list below
#'@return NCA state with the NCA for the current analysis built.
#'@examples
#'# Module IDs
#'id = "NCA"
#'id_UD = "UD"
#'id_DW = "DW"
#'id_ASM = "ASM"
#'
#'# We need a module variables to be defined
#'sess_res = NCA_test_mksession(session=list(),
#' id = id,
#' id_UD = id_UD,
#' id_DW = id_DW,
#' id_ASM = id_ASM,
#' full_session=FALSE)
#'
#'state = sess_res$state
#'
#'state = nca_builder(state)
nca_builder = function(state){
isgood = TRUE
cmd = c()
msgs = c()
objs = list()
code = ""
code_ana_only = ""
code_previous = ""
code_tb_ind_obs = ""
code_tb_ind_params = ""
code_fg_ind_obs = ""
# Checking and retrieving the current analysis
current_ana = NCA_process_current_ana(state)
# These are the object names that will be generated with the code
nca_ds_object_name = paste0(current_ana[["id"]], "_DS")
nca_rm_object_name = paste0(current_ana[["id"]], "_route_map")
nca_drec_object_name = paste0(current_ana[["id"]], "_dose_rec")
nca_ints_object_name = paste0(current_ana[["id"]], "_intervals")
nca_dose_object_name = paste0(current_ana[["id"]], "_dose")
nca_data_object_name = paste0(current_ana[["id"]], "_data")
nca_conc_object_name = paste0(current_ana[["id"]], "_conc")
nca_res_object_name = paste0(current_ana[["id"]], "_res")
nca_units_object_name = paste0(current_ana[["id"]], "_units")
nca_fg_ind_obs_object_name = paste0(current_ana[["id"]], "_figure_ind_obs")
nca_tb_ind_obs_object_name = paste0(current_ana[["id"]], "_table_ind_obs")
nca_tb_ind_params_object_name = paste0(current_ana[["id"]], "_table_ind_params")
# We only proceed if were able to process the
# current analysis successfully
if(current_ana[["isgood"]]){
# Pulling out all the column information to
# use in the command construction below
col_id = current_ana[["col_id"]]
col_conc = current_ana[["col_conc"]]
col_dose = current_ana[["col_dose"]]
col_dur = current_ana[["col_dur"]]
col_analyte = current_ana[["col_analyte"]]
col_route = current_ana[["col_route"]]
col_time = current_ana[["col_time"]]
col_ntime = current_ana[["col_ntime"]]
col_group = current_ana[["col_group"]]
col_evid = current_ana[["col_evid"]]
col_cycle = current_ana[["col_cycle"]]
# Dose extraction
dose_from = current_ana[["dose_from"]]
#--------------------------
# plus columns
plus_cols = c()
# Adding the optional grouping columns
if(col_group != ""){
plus_cols = c(plus_cols,
col_group)
}
# ID is last
plus_cols = c(plus_cols, col_id)
# JMH dose_rec_fix delete
# #--------------------------
# # These are the columns to keep in the
# # dosing records below:
# dose_select_cols = c(
# col_id,
# col_time,
# col_ntime,
# col_dose,
# col_route)
# if(col_group != ""){
# dose_select_cols = c(dose_select_cols, col_group)
# }
# if(col_dur != "N/A"){
# dose_select_cols = c(dose_select_cols, col_dur)
# }
# if(col_analyte != "N/A"){
# dose_select_cols = c(dose_select_cols, col_analyte)
# }
#--------------------------
# Converting sampling into boolean
if(current_ana[["sampling"]] == "sparse"){
is_sparse = TRUE
}else{
is_sparse = FALSE
}
#--------------------------
# Pulling out the dataset for this analysis
ds_object_name = current_ana[["ana_dsview"]]
ds = state[["NCA"]][["DSV"]][["ds"]][[ ds_object_name ]]
#--------------------------
# Adding the text description of the analysis
cmd = c(cmd, "", FM_build_comment(2, current_ana[["key"]]))
#--------------------------
# Defining the pknca options.
# These are the options that control PKNCA
blq_cmd = c(
" conc.blq = list(",
paste0(" first = ", autocast(current_ana[["nca_config"]][["conc_blq_first"]] [["value"]]), ","),
paste0(" middle = ", autocast(current_ana[["nca_config"]][["conc_blq_middle"]][["value"]]), ","),
paste0(" last = ", autocast(current_ana[["nca_config"]][["conc_blq_last"]] [["value"]])),
" )"
)
cmd = c(cmd,
"# Setting the NCA options",
"PKNCA::PKNCA.options(")
for(nca_opt in names( current_ana[["nca_config"]])){
# We process all of the options except the blq values
# because they are added separately because
# BILL MADE THEM BEHAVE DIFFERENTLY THAN THE OTHERS! :)
if(!(nca_opt %in%
c("conc_blq_first",
"conc_blq_middle",
"conc_blq_last"))){
pknca_option = current_ana[["nca_config"]][[nca_opt]][["pknca_option"]]
nca_opt_value = current_ana[["nca_config"]][[nca_opt]] [["value"]]
nca_opt_type = current_ana[["nca_config"]][[nca_opt]] [["type"]]
if(nca_opt_type %in% c("character", "mixed")){
nca_opt_value = autocast(nca_opt_value)
}
cmd = c(cmd,
paste0(" ", pknca_option, " = ", nca_opt_value, ",")
)
}
}
# lastly we append the blq options.
cmd = c(cmd,
blq_cmd,
")"
)
#--------------------------
# Defining the dataset
cmd = c(cmd, "# Creating a copy of the source dataset to use below")
cmd = c(cmd, paste0(nca_ds_object_name, " = ", ds_object_name))
# If we have a route mapping in the module yaml file
# we construct the code here to apply that.
if(is.list(state[["MC"]][["detect_route"]])){
cmd = c(cmd, "")
cmd = c(cmd, "# Applying route mapping")
cmd = c(cmd, paste0(nca_rm_object_name, " = list("))
rmaps = names(state[["MC"]][["detect_route"]])
for(rmap_idx in 1:length(rmaps)){
rmap_txt =paste0(" ",rmaps[[rmap_idx]],'=c("',
paste0(state[["MC"]][["detect_route"]][[ rmaps[[rmap_idx]] ]] , collapse = '", "'),
'")')
# we have to add commas to each list element
# definition except for the last one.
if(rmap_idx < length(rmaps)){
rmap_txt =paste0(rmap_txt, ",")
}
cmd = c(cmd, rmap_txt)
}
cmd = c(cmd, " )")
cmd = c(cmd, "")
cmd = c(cmd, paste0(nca_ds_object_name,
" = apply_route_map(route_map=", nca_rm_object_name, ", ",
' route_col = "', current_ana[["col_route"]], '", ',
' DS = ', nca_ds_object_name, ")"))
}
# We're going to walk through each column. If it's defined and in the
# dataset then we will include it in the assignment:
all_cols = c("col_id",
"col_dose",
"col_dur",
"col_analyte",
"col_route",
"col_time",
"col_ntime",
"col_group",
"col_evid",
"col_cycle")
col_args = c()
for(cname in all_cols){
# This checks to see if all the columns are defined:
if(all(get(cname) %in% names(ds[["DS"]]))){
col_args = c(col_args,
paste0(' ', cname, ' = c("', paste0(get(cname),collapse='", "'), '"),')
)
}
}
# Creating dosing records
cmd = c( cmd,
paste0(nca_drec_object_name, " = dose_records_builder( "),
paste0( ' NCA_DS = ', nca_ds_object_name, ',' ),
col_args,
paste0( ' dose_from = "', dose_from , '")[["dose_rec"]]' ))
# Constructing dose_obj
cmd=c(cmd,
"",
"# NCA dosing object",
paste0(nca_dose_object_name, " = ",
"PKNCA::PKNCAdose(",
nca_drec_object_name,", ",
col_dose, "~",col_time,"|",
paste(plus_cols, collapse="+"), ", ",
'route = "', col_route, '"',
")"
)
)
# If we dose from rows we need to strip those out
if(dose_from == "rows"){
cmd=c(cmd,
"",
"# Redusing the NCA dataset to just the observations",
paste0(nca_ds_object_name, " = dplyr::filter(", nca_ds_object_name, ", EVID == 0)")
)
}
# Constructing conc_obj
col_dur_component = NULL
if(col_dur != "N/A"){
col_dur_component = paste0(', duration = "', col_dur, '"')
}
col_analyte_component = NULL
if(col_analyte != "N/A"){
col_analyte_component =paste0("/",col_analyte)
}
cmd=c(cmd,
"",
"# NCA concentration object",
paste0(
nca_conc_object_name, " = ",
"PKNCA::PKNCAconc(",
nca_ds_object_name, ",",
col_conc, "~",col_time,"|",
paste(plus_cols, collapse="+"),
col_analyte_component,
", ",
'time.nominal = "',col_ntime,'", ',
'sparse = ', is_sparse,
col_dur_component,
")"
)
)
# Building out the units component
if(current_ana[["include_units"]]){
cmd=c(cmd,
"",
"# NCA units table",
paste0(
nca_units_object_name, " = ",
"PKNCA::pknca_units_table(",
'concu = "', current_ana[["units_conc"]], '", ',
'doseu = "', current_ana[["units_dose"]], '", ',
'amountu = "', current_ana[["units_amt"]], '", ',
'timeu = "', current_ana[["units_time"]], '"',
")"
)
)
}
#--------------------------
# Creating the intervals:
# First we collect all of the parameters we want to collect
nca_params_found = c()
for(intidx in 1:nrow(current_ana[["intervals"]])){
params_from_str =
stringr::str_split(
string = current_ana[["intervals"]][intidx, ][["np_actual"]],
pattern = "," ,
simplify = TRUE)
nca_params_found = c(nca_params_found, params_from_str)
}
# This removes duplicates
nca_params_found = unique(nca_params_found)
# This will build the components of the intervals data frame:
int_df_comp = list()
for(intidx in 1:nrow(current_ana[["intervals"]])){
int_df_comp[["start"]] = c( int_df_comp[["start"]], toString(current_ana[["intervals"]][intidx, ][["start"]]))
int_df_comp[["end"]] = c( int_df_comp[["end"]], toString(current_ana[["intervals"]][intidx, ][["stop"]]))
# These are the parameters for the current interval:
params_from_str =
stringr::str_split(
string = current_ana[["intervals"]][intidx, ][["np_actual"]],
pattern = "," ,
simplify = TRUE)
# Now we loop through
for(param in nca_params_found){
if(param %in% params_from_str){
int_df_comp[[param]] = c( int_df_comp[[param]], "TRUE")
} else {
int_df_comp[[param]] = c( int_df_comp[[param]], "FALSE")
}
}
}
cmd = c(cmd,
"",
"# Dataframe containing the analysis intervals",
paste0(nca_ints_object_name, " = "),
" data.frame("
)
comps = names(int_df_comp)
last_comp = rev(comps)[1]
for(comp in comps){
if(comp != last_comp){
comma_str = ","
} else {
comma_str = ""
}
cmd = c(cmd,
paste0(" ",comp,"=c(",paste0(int_df_comp[[comp]], collapse=", "), ")", comma_str)
)
}
cmd = c(cmd,
" )"
)
#--------------------------
# Creating the data object
PKNCAdata_args = c(
paste0(" data.conc = ", nca_conc_object_name),
paste0(" data.dose = ", nca_dose_object_name),
paste0(" intervals = ", nca_ints_object_name)
)
if(current_ana[["include_units"]]){
PKNCAdata_args = c(
PKNCAdata_args,
paste0(" units = ", nca_units_object_name)
)
}
cmd = c(cmd,
"",
"# Pulling everything together to create the data object.",
paste0(
nca_data_object_name, " = " ,
"PKNCA::PKNCAdata(",
"",
paste0(PKNCAdata_args, collapse = ",\n"),
")"
)
)
# Running the NCA
cmd = c(cmd,
"",
"# Running the NCA",
paste0(
nca_res_object_name, " = ",
"PKNCA::pk.nca(",
nca_data_object_name,
")"
)
)
# code for figures and tables
# JMH add other UI optoins to function calls here:
code_fg_ind_obs = c(
"",
"# Generating figures of indiviudal profiles",
paste0(nca_fg_ind_obs_object_name,
" = mk_figure_ind_obs(",
nca_res_object_name, ", ",
"nfrows = ", current_ana$fg_ind_obs_nrow, ", ",
"nfcols = ", current_ana$fg_ind_obs_ncol, ", ",
"log_scale = ", current_ana$fg_ind_obs_logy,
")"))
code_tb_ind_obs = c(
"",
"# Generating tables of individual profiles",
paste0(nca_tb_ind_obs_object_name, " = mk_table_ind_obs("),
paste0(' nca_res = ', nca_res_object_name,','),
" obnd = rpt,",
paste0(' notes_detect = c("', paste0(names(state[["MC"]][["reporting"]][["notes"]]), collapse='", "'), '"), '),
paste0(' not_sampled = "', state[["MC"]][["reporting"]][["not_sampled"]], '",'),
paste0(' blq = "', state[["MC"]][["reporting"]][["blq"]], '",'),
paste0(' digits = ', state[["MC"]][["reporting"]][["digits"]]),
")")
code_tb_ind_params = c(
"",
"# Generating tables of individual NCA parameters",
paste0(nca_tb_ind_params_object_name, " = mk_table_nca_params("),
paste0(" nca_res = ", nca_res_object_name, ", "),
" obnd = rpt, ",
paste0(' notes_detect = c("', paste0(names(state[["MC"]][["reporting"]][["notes"]]), collapse='", "'), '"), '),
" nps = NCA_nps, ",
paste0(' text_format = "', state[["MC"]][["reporting"]][["text_format"]] ,'",'),
paste0(' not_calc = "', state[["MC"]][["reporting"]][["not_calc"]] ,'",'),
paste0(' infinity = "', state[["MC"]][["reporting"]][["infinity"]] ,'",'),
paste0(" digits = ", state[["MC"]][["reporting"]][["digits"]] ,','),
paste0(' mult_str = "', state[["MC"]][["reporting"]][["mult_str"]] ,'")'))
# Working out the little code elements:
code_ana_only = paste(cmd, collapse="\n")
code_fg_ind_obs = paste(code_fg_ind_obs, collapse="\n")
code_tb_ind_obs = paste(code_tb_ind_obs, collapse="\n")
code_tb_ind_params = paste(code_tb_ind_params, collapse="\n")
code_previous = ds[["code"]]
code = paste(code_previous,
code_ana_only,
code_fg_ind_obs,
code_tb_ind_obs,
code_tb_ind_params,
collapse="\n")
} else {
isgood = FALSE
}
# Creating the stand-alone code:
nps_def = 'NCA_nps = NCA_fetch_np_meta()[["summary"]]'
mod_deps = state[["NCA"]][["mod_deps"]]
code_sa = c(mod_deps$package_code,
"",
"# Metadata about NCA parameters",
nps_def,
"",
"# Report object used for creating tables below",
'rpt = onbrand::read_template(',
' template = file.path(system.file(package = "onbrand"), "templates", "report.docx"),',
' mapping = file.path(system.file(package = "onbrand"), "templates", "report.yaml")',
')',
"",
code)
# saving any messages:
msgs = c(msgs, current_ana[["msgs"]])
state = formods::FM_set_ui_msg(state, msgs)
# Saving the state information
current_ana[["isgood"]] = isgood
current_ana[["code"]] = code
current_ana[["code_sa"]] = code_sa
current_ana[["code_components"]] = list(
code_previous = code_previous,
code_ana_only = code_ana_only,
code_fg_ind_obs = code_fg_ind_obs,
code_tb_ind_obs = code_tb_ind_obs,
code_tb_ind_params = code_tb_ind_params
)
current_ana[[ "objs" ]][[ "ds" ]][[ "name" ]] = nca_ds_object_name
current_ana[[ "objs" ]][[ "rm" ]][[ "name" ]] = nca_rm_object_name
current_ana[[ "objs" ]][[ "drec" ]][[ "name" ]] = nca_drec_object_name
current_ana[[ "objs" ]][[ "ints" ]][[ "name" ]] = nca_ints_object_name
current_ana[[ "objs" ]][[ "dose" ]][[ "name" ]] = nca_dose_object_name
current_ana[[ "objs" ]][[ "data" ]][[ "name" ]] = nca_data_object_name
current_ana[[ "objs" ]][[ "conc" ]][[ "name" ]] = nca_conc_object_name
current_ana[[ "objs" ]][[ "res" ]][[ "name" ]] = nca_res_object_name
current_ana[[ "objs" ]][[ "fg_ind_obs" ]][[ "name" ]] = nca_fg_ind_obs_object_name
current_ana[[ "objs" ]][[ "tb_ind_obs" ]][[ "name" ]] = nca_tb_ind_obs_object_name
current_ana[[ "objs" ]][[ "tb_ind_params"]][[ "name" ]] = nca_tb_ind_params_object_name
# If we don't include units then the object wont be available, so we only
# add this conditionally:
if(current_ana[["include_units"]]){
current_ana[[ "objs" ]][[ "units" ]][[ "name" ]] = nca_units_object_name
} else {
current_ana[[ "objs" ]][[ "units" ]] = NULL
}
# Storing the current ana with the updated data:
state = NCA_set_current_ana(state, current_ana)
state}
#'@export
#'@title Runs NCA for the Current Analysis
#'@description Takes the current state and runs the current analysis in that
#'state.
#'@param state NCA state from \code{NCA_fetch_state()}
#'@param components List of components to run. By default it will run all of
#'the following. If you just need to regenerate a figure based on the current
#'nca results you can just specify that component. These are the valid
#'components:
#' \itemize{
#' \item{nca:} Run NCA analysis
#' \item{fg_ind_obs:} Build the figure(s) with the indiviudal observations.
#' \item{tb_ind_obs:} Build the table(s) with the indiviudal observations.
#' \item{tb_ind_params:} Build the table(s) with the indiviudal parameters.
#'}
#'@return List with the following components:
#' \itemize{
#' \item{isgood:} Return status of the function.
#' \item{msgs:} Error messages if any issues were encountered.
#' \item{nca_res:} PKNCA results if run was successful.
#'}
#'@examples
#'# We need a state object to use below
#'sess_res = NCA_test_mksession(session=list(), full_session=FALSE)
#'state = sess_res$state
#'
#'state = run_nca_components(state, components="tb_ind_params")
run_nca_components = function(
state,
components=c("nca",
"fg_ind_obs",
"tb_ind_obs",
"tb_ind_params")){
# Generating code. The following will be added
# to the current analysis
# - code and code components
# - exit status of generation
# - any messages that were generated
state = nca_builder(state)
#valid_components = c("nca", "fg_ind_obs", "tb_ind_obs", "tb_ind_params")
# Pulling out the current analysis to use and update below
current_ana = NCA_fetch_current_ana(state)
# Short name for objects created when running NCA.
# These are all of the possible names:
obs_sns_nca = c("res", "drec", "rm", "ints",
"dose", "data", "conc", "units")
# Sometimes only a subset are generated. For example when units is
# unchecked. So this will only keep those that exist for this analysis:
obs_sns_nca = obs_sns_nca[obs_sns_nca %in% names(current_ana[["objs"]])]
# Messages to pass back to the user
msgs = c()
# If current_ana is bad then something in the nca_builder() failed.
# We want to pass those back to the user.
if(current_ana[["isgood"]]){
# Pulling out the dataset for the analysis
dsview = current_ana[["ana_dsview"]]
DS = state[["NCA"]][["DSV"]][["ds"]][[dsview]][["DS"]]
#---------------------------------------------
# Running NCA
if("nca" %in% components){
if(current_ana[["isgood"]]){
# Source to run
cmd = current_ana[["code_components"]][["code_ana_only"]]
# NCA environment environment:
tc_env = list()
tc_env[[dsview]] = DS
tc_env[["rpt"]] = state[["NCA"]][["docx_rpt"]]
tc_env[["NCA_nps"]] = state[["NCA"]][["nca_parameters"]][["summary"]]
# Creating the vector of object names to capture:
capture = c()
for(obs_sn in obs_sns_nca){
capture = c(
capture,
current_ana[["objs"]][[obs_sn]][["name"]]
)
}
# Running the analysis and trapping any errors
nca_run_res = formods::FM_tc(cmd, tc_env, capture)
# Capturing the exit status
if(nca_run_res[["isgood"]]){
# Pulling out the capture objects and saving them
# to the current analysis
for(obs_sn in obs_sns_nca){
current_ana[["objs"]][[obs_sn]][["value"]] =
nca_run_res[["capture"]][[ current_ana[["objs"]][[obs_sn]][["name"]] ]]
}
} else {
# If the run failed we capture the error messages to be passed back to the
# user:
msgs = c(msgs, nca_run_res[["msgs"]] )
# We flag the analysis as bad:
current_ana[["isgood"]] = FALSE
}
}
}
#---------------------------------------------
# This list maps the component name to the key
# with the code for that component
fig_tabs = list("fg_ind_obs" = list(code = "code_fg_ind_obs",
current = "curr_fg_ind_obs",
list_name = "figures"),
"tb_ind_obs" = list(code ="code_tb_ind_obs",
current ="curr_tb_ind_obs",
list_name = "tables"),
"tb_ind_params" = list(code ="code_tb_ind_params",
current ="curr_tb_ind_params",
list_name = "tables"))
for(fig_tab in names(fig_tabs)){
if(current_ana[["isgood"]]){
if(fig_tab %in% components){
# Figure or table generation code:
cmd = current_ana[["code_components"]][[ fig_tabs[[fig_tab]][["code"]] ]]
# Object name created to capture:
capture = current_ana[["objs"]][[fig_tab]][["name"]]
# In the environment environment we define the dataset,
# the report template, the nca parameters summary(nps),
# as the objects created in the NCA analysis:
tc_env = list()
tc_env[[dsview]] = DS
tc_env[["rpt"]] = state[["NCA"]][["docx_rpt"]]
tc_env[["NCA_nps"]] = state[["NCA"]][["nca_parameters"]][["summary"]]
for(obs_sn in obs_sns_nca){
tc_env[[ current_ana[["objs"]][[obs_sn]][["name"]] ]] =
current_ana[["objs"]][[obs_sn]][["value"]]
}
# Running the table or figure generation code:
nca_run_res = formods::FM_tc(cmd, tc_env, capture)
# Capturing the results. There are two points of failure here. One
# is that the code can fail to execute. That should mark the current
# analysis as bad and pass those failures on to the user.
if(nca_run_res[["isgood"]]){
# Pulling out the captured object
tmp_res = nca_run_res[["capture"]][[ current_ana[["objs"]][[fig_tab]][["name"]] ]]
# This pulls out any names for figures, tables, etc:
list_names = names(tmp_res[[ fig_tabs[[fig_tab]][["list_name"]] ]])
# We store the result for the current component
current_ana[["objs"]][[fig_tab]][["value"]] = tmp_res
# There should be at least one element here:
if(!is.null(list_names)){
if(!(current_ana[[ fig_tabs[[fig_tab]][["current"]] ]] %in% list_names)){
current_ana[[ fig_tabs[[fig_tab]][["current"]] ]] = list_names[1]
}
} else {
# The second point of failure is that the component simply has
# no figures, tables, etc. This might mean that there are none
# that are valid for this current component. So for that we just
# set a message so if that component is selected it says there
# isn't anything to show:
# If we don't see an element not we set the list name to null
current_ana[["objs"]][[fig_tab]][["value"]][[
fig_tabs[[fig_tab]][["list_name"]] ]] = NULL
# We also attach a message to be returned to the user
current_ana[["objs"]][[fig_tab]][["value"]][["msgs"]] = c(
current_ana[["objs"]][[fig_tab]][["value"]][["msgs"]],
paste0("No ", fig_tabs[[fig_tab]][["list_name"]],
" elements found when generating: ", fig_tab)
)
}
} else {
# If the run failed we capture the error messages to be passed back to the
# user:
msgs = c(msgs, nca_run_res[["msgs"]] )
# We flag the analysis as bad:
current_ana[["isgood"]] = FALSE
}
}
}
# If we encounter a failure anywhere above we attach a generic message
# about the current figure or table
if(!current_ana[["isgood"]]){
err_msgs = paste0("Unable to create: ", fig_tab, " see above for details.")
msgs = c(msgs, err_msgs)
}
}
} else {
msgs = c(msgs, current_ana[["msgs"]] )
}
#If there is something wrong we set that in the messages
if(!current_ana[["isgood"]]){
state = formods::FM_set_ui_msg(state, msgs)
FM_le(state, msgs, entry_type="danger")
}
# Setting the analysis checksum based on the objs portion.
current_ana[["checksum"]] = digest::digest(current_ana[["objs"]], algo=c("md5"))
# Saving any changes to the analysis
state = NCA_set_current_ana(state, current_ana)
# Creating a checksum for the entire module:
all_checksum = ":"
for(ana_id in names(state[["NCA"]][["anas"]])){
all_checksum = paste0(all_checksum, ana_id, ":", state[["NCA"]][["anas"]][[ana_id]][["checksum"]], ":")
}
state[["NCA"]][["checksum"]] = digest::digest(all_checksum, algo=c("md5"))
FM_le(state, paste0("module checksum updated:", state[["NCA"]][["checksum"]]))
state}
#'@export
#'@title Creates Tables of Individual Observations from PKNCA Result
#'@description Takes the output of PKNCA and creates a tabular view of the
#'individual observation data. This can be spread out of over several tables
#'(pages) if necessary.
#'@param nca_res Output of PKNCA.
#'@param obnd onbrand reporting object.
#'@param not_sampled Character string to use for missing data when pivoting.
#'@param blq Character string to use to indicate data below the level of quantification (value of 0 in the dataset).
#'@param digits Number of significant figures to report (set to \code{NULL} to disable rounding)
#'@param text_format Either \code{"md"} for markdown or \code{"text"} (default) for plain text.
#'@param max_width Maximum width of the final table in inches (A value of \code{NULL} will use 100 inches).
#'@param max_height Maximum height of the final table in inches (A value of \code{NULL} will use 100 inches).
#'@param max_col Maximum number of columns to have on a page. Spillover will be wrapped to multiple pages.
#'@param max_row Maximum number of rows to have on a page. Spillover will hang over the side of the page..
#'@param notes_detect Vector of strings to detect in output tables (example \code{c("NC", "BLQ")}).
#'@param rows_by Can be either "time" or "id". If it is "time", there will be a
#'column for time and separate column for each subject ID. If rows_by is set
#'to "id" there will be a column for ID and a column for each individual time.
#'@return List containing the following elements
#'\itemize{
#' \item{isgood:} Boolean indicating the exit status of the function.
#' \item{one_table:} Dataframe of the entire table with the first lines containing the header.
#' \item{one_body:} Dataframe of the entire table (data only).
#' \item{one_header:} Dataframe of the entire header (row and body, no data).
#' \item{tables:} Named list of tables. Each list element is of the output
#' \item{msgs:} Vector of text messages describing any errors that were found.
#' format from \code{\link[onbrand]{build_span}}.
#'}
#'@examples
#'id = "NCA"
#'id_UD = "UD"
#'id_DW = "DW"
#'id_ASM = "ASM"
#'
#'# We need a state variable to be define
#' sess_res = NCA_test_mksession(session=list(),
#' id = id,
#' id_UD = id_UD,
#' id_DW = id_DW,
#' id_ASM = id_ASM,
#' full_session=FALSE)
#'
#'state = sess_res$state
#'
#'# Pulls out the active analysis
#'current_ana = NCA_fetch_current_ana(state)
#'
#'# This is the raw PKNCA output
#'pknca_res = NCA_fetch_ana_pknca(state, current_ana)
#'
#'# Building the figure
#'mk_res = mk_table_ind_obs(nca_res = pknca_res)
#'mk_res$tables[["Table 1"]]$ft
mk_table_ind_obs = function(
nca_res ,
obnd = NULL,
not_sampled = "NS",
blq = "BLQ",
digits = 3,
text_format = "text",
max_height = 7,
max_width = 6.5,
max_row = NULL,
max_col = 9,
notes_detect = NULL,
rows_by = "time"){
# Extracting the needed column names:
col_id = nca_res[["data"]][["conc"]][["columns"]][["subject"]]
col_time = nca_res[["data"]][["conc"]][["columns"]][["time"]]
col_conc = nca_res[["data"]][["conc"]][["columns"]][["concentration"]]
col_analyte = nca_res[["data"]][["conc"]][["columns"]][["groups"]][["group_analyte"]]
# Plucking out the units for time and conc
time_units = ""
conc_units = ""
if(!is.null(nca_res[["data"]][["units"]])){
# Perhaps there is a better way to extract these things but this is the
# most obvious to me :)
time_units = nca_res[["data"]][["units"]][nca_res[["data"]][["units"]][["PPTESTCD"]] == "start", ][["PPORRESU"]]
conc_units = nca_res[["data"]][["units"]][nca_res[["data"]][["units"]][["PPTESTCD"]] == "cmax", ][["PPORRESU"]]
}
# Retaining only the needed columns
cols_keep = c(col_id, col_time, col_analyte, col_conc)
# These are the columns that contain the
# row headers for the table
# This is the original dataset along with what looks like
# some extra columns added by PKNCA
all_data = dplyr::as_tibble(as.data.frame(nca_res[["data"]][["conc"]])) |>
dplyr::select(dplyr::all_of(cols_keep)) |>
dplyr::rename(CONC = dplyr::all_of(col_conc))|>
dplyr::rename(TIME = dplyr::all_of(col_time))|>
dplyr::rename(ID = dplyr::all_of(col_id))
# BILL how does PKNCA handle units with multiple analytes?
# If we have an analyte column we rename it:
row_common_head = NULL
#row_header_cols = c()
#row_header_label = c()
#row_header_lengths = c()
units_data = c()
# Applying significant digits
if(!is.null(digits)){
# For concentration data it is pretty
# straight forward
all_data[["CONC"]] = as.character(signif(all_data[["CONC"]], digits))
all_data[["TIME"]] = as.character(floor(all_data[["TIME"]]) + signif(all_data[["TIME"]] %% 1, digits))
} else {
all_data[["CONC"]] = as.character(all_data[["CONC"]])
all_data[["TIME"]] = as.character(all_data[["TIME"]])
}
# Replacing all BLQ and NA values with the appropriate text
all_data[is.na(all_data[["CONC"]]), ][["CONC"]] = not_sampled
all_data[all_data[["CONC"]] == "0", ][["CONC"]] = blq
if(rows_by == "time"){
if(is.null(row_common_head)){
row_common_head = data.frame(TIME="Time")
} else {
row_common_head = cbind(row_common_head,
data.frame(TIME="Time"))
}
# row_header_cols = c("TIME", row_header_cols)
# row_header_label = c("Time", row_header_label)
# row_header_lengths = c( 1, row_header_lengths)
if(time_units == ""){
units_data = c(units_data, "")
} else {
units_data = c(units_data, paste0("(", time_units,")"))
}
col_header_label = "Concentration ===CONCUNITS=== by ID"
all_data = tidyr::pivot_wider(all_data, names_from="ID", values_from="CONC", values_fill=not_sampled)
} else if(rows_by == "id"){
if(is.null(row_common_head)){
row_common_head = data.frame(ID="ID")
} else {
row_common_head = cbind(row_common_head,
data.frame(ID="ID"))
}
# row_header_cols = c("ID", row_header_cols)
# row_header_label = c("ID", row_header_label)
# row_header_lengths = c( 1, row_header_lengths)
if(time_units == ""){
units_data = c(units_data, "")
} else {
units_data = c(units_data, "--")
}
col_header_label = "Concentration ===CONCUNITS=== by ID Observation Time ===TIMEUNITS==="
all_data = tidyr::pivot_wider(all_data, names_from="TIME", values_from="CONC", values_fill=not_sampled)
}
if(length(col_analyte) == 1){
all_data = dplyr::rename(all_data, ANALYTE=col_analyte) |>
dplyr::arrange(!!as.name("ANALYTE"), !!as.name("TIME"))
if(is.null(row_common_head)){
row_common_head = data.frame(ANALYTE="Analyte")
} else {
row_common_head = cbind(row_common_head,
data.frame(ANALYTE="Analyte"))
}
analyte_units = " "
units_data = c(units_data, analyte_units)
}
if(conc_units == ""){
col_header_label = stringr::str_replace(col_header_label, "===CONCUNITS===", "")
} else {
col_header_label = stringr::str_replace(col_header_label, "===CONCUNITS===", paste0("(", conc_units, ")"))
}
if(time_units == ""){
col_header_label = stringr::str_replace(col_header_label, "===TIMEUNITS===", "")
} else {
col_header_label = stringr::str_replace(col_header_label, "===TIMEUNITS===", paste0("(", time_units, ")"))
}
# Splitting the data into header columns and observations
row_common = dplyr::select(all_data, dplyr::all_of(names(row_common_head)))
table_body = dplyr::select(all_data, -dplyr::all_of(names(row_common_head)))
# This converts everything to text:
table_body = dplyr::mutate_all(table_body, as.character)
table_body_head = NULL
for(tmpID in names(table_body)){
if(is.null(table_body_head)){
table_body_head = eval(parse(text=paste0('dplyr::tibble("', tmpID,'" = c("', col_header_label, '", tmpID))')))
} else {
table_body_head[[tmpID]] = c(col_header_label, tmpID)
}
}
# We need to attach the units to the rows as well:
row_common_head = rbind(row_common_head, units_data)
stres = onbrand::span_table(
table_body = table_body,
row_common = row_common,
table_body_head = table_body_head,
row_common_head = row_common_head,
obnd = obnd,
header_format = text_format,
max_width = max_width,
max_height = max_height,
max_row = max_row,
max_col = max_col,
notes_detect = notes_detect)
res = list(
#all_data = all_data,
isgood = stres[["isgood"]],
one_table = stres[["one_table"]],
one_header = stres[["one_header"]],
one_body = stres[["one_body"]],
tables = stres[["tables"]],
msgs = stres[["msgs"]]
)
res}
#'@export
#'@title Creates Figures of Individual Observations from PKNCA Result
#'@description Takes the output of PKNCA and creates `ggplot` figures faceted
#'by subject id highlighting of certain NCA aspects (e.g. points used for half-life)
#'@param nca_res Output of PKNCA.
#'@param OBS_LAB Label of the observation axis with optional ===CONCUNITS=== placeholder for units.
#'@param TIME_LAB Label of the time axis with optional ===TIMEUNITS=== placeholder for units.
#'@param OBS_STRING Label for observation data.
#'@param BLQ_STRING Label for BLQ data.
#'@param NA_STRING Label for missing data.
#'@param log_scale Boolean variable to control y-scale (\code{TRUE}: Log 10, \code{FALSE}: linear).
#'@param scales String to determine the scales used when faceting. Can be either \code{"fixed"}, \code{"free"}, \code{"free_x"}, or \code{"free_y"}.
#'@param nfrows Number of facet rows per page.
#'@param nfcols Number of facet cols per page.
#'@return List containing the element \code{figures} which is a list of figure
#' pages (\code{"Figure 1"}, \code{"Figure 2"}, etc.). Each of these is
#' a also a list containing two elements:
#'\itemize{
#' \item{gg:} A ggplot object for that page.
#' \item{notes:} Placeholder for future notes, but NULL now.
#'}
#'@examples
#'id = "NCA"
#'id_UD = "UD"
#'id_DW = "DW"
#'id_ASM = "ASM"
#'
#'# We need a state variable to be define
#' sess_res = NCA_test_mksession(session=list(),
#' id = id,
#' id_UD = id_UD,
#' id_DW = id_DW,
#' id_ASM = id_ASM,
#' full_session=FALSE)
#'
#'state = sess_res$state
#'
#'# Pulls out the active analysis
#'current_ana = NCA_fetch_current_ana(state)
#'
#'# This is the raw PKNCA output
#'pknca_res = NCA_fetch_ana_pknca(state, current_ana)
#'
#'# Building the figure
#'mk_res = mk_figure_ind_obs(nca_res = pknca_res)
#'mk_res$figures$Figure_1$gg
mk_figure_ind_obs = function(
nca_res ,
OBS_LAB = "Concentration ===CONCUNITS===",
TIME_LAB = "Time ===TIMEUNITS===",
OBS_STRING = "Observation",
BLQ_STRING = "BLQ",
NA_STRING = "Missing",
log_scale = TRUE,
scales = "fixed",
nfrows = 4,
nfcols = 3){
# Plucking out the units for time and conc
time_units = ""
conc_units = ""
if(!is.null(nca_res[["data"]][["units"]])){
# Perhaps there is a better way to extract these things but this is the
# most obvious to me :)
time_units = nca_res[["data"]][["units"]][nca_res[["data"]][["units"]][["PPTESTCD"]] == "start", ][["PPORRESU"]]
conc_units = nca_res[["data"]][["units"]][nca_res[["data"]][["units"]][["PPTESTCD"]] == "cmax", ][["PPORRESU"]]
}
if(conc_units == ""){
OBS_LAB = stringr::str_replace(OBS_LAB, "===CONCUNITS===", "")
} else {
OBS_LAB = stringr::str_replace(OBS_LAB, "===CONCUNITS===", paste0("(", conc_units, ")"))
}
if(time_units == ""){
TIME_LAB = stringr::str_replace(TIME_LAB, "===TIMEUNITS===", "")
} else {
TIME_LAB = stringr::str_replace(TIME_LAB, "===TIMEUNITS===", paste0("(", time_units, ")"))
}
col_id = nca_res[["data"]][["conc"]][["columns"]][["subject"]]
col_time = nca_res[["data"]][["conc"]][["columns"]][["time"]]
col_conc = nca_res[["data"]][["conc"]][["columns"]][["concentration"]]
col_group = nca_res[["data"]][["conc"]][["columns"]][["groups"]][["group_vars"]]
col_analyte = nca_res[["data"]][["conc"]][["columns"]][["groups"]][["group_analyte"]]
# Retaining only the needed columns
cols_keep = unique(c(col_id, col_time, col_conc, col_group, col_analyte))
# If this value is NULL it will be set to the lowest value for that
# individual
# This is the original dataset along with what looks like
# some extra columns added by PKNCA
all_data = dplyr::as_tibble(as.data.frame(nca_res[["data"]][["conc"]])) |>
dplyr::select(dplyr::all_of(cols_keep)) |>
dplyr::rename(CONC = dplyr::all_of(col_conc)) |> # Renaming columns to standard values
dplyr::rename(TIME = dplyr::all_of(col_time)) |>
# dplyr::rename(ID = dplyr::all_of(col_id)) |>
dplyr::group_by(!!as.name(col_group)) |>
dplyr::mutate(NONOBS = min(.data[["CONC"]][.data[["CONC"]]>0 &
!is.na(.data[["CONC"]])])) |> # Creating a concentration for non-observations (0 and NA below)
dplyr::ungroup() |>
dplyr::mutate(PKNCA_DATA_TYPE = OBS_STRING) |> # This sets all data types to "Observation":w
dplyr::mutate(PKNCA_DATA_TYPE = ifelse(.data[["CONC"]]==0, # Setting the BLQ Flag
BLQ_STRING,
.data[["PKNCA_DATA_TYPE"]])) |>
dplyr::mutate(PKNCA_DATA_TYPE = ifelse(is.na(.data[["CONC"]]), # Setting the Missing Flag
NA_STRING,
.data[["PKNCA_DATA_TYPE"]])) |>
dplyr::mutate(CONC = ifelse(is.na(.data[["CONC"]]), # Setting missing values to values for plotting
.data[["NONOBS"]],
.data[["CONC"]])) |>
dplyr::mutate(CONC = ifelse(.data[["CONC"]] == 0, # Setting missing values to values for plotting
.data[["NONOBS"]],
.data[["CONC"]]))
# Subjects remaining to plot
subs_left = unique(all_data[[col_id]])
# Number of subjects per plot:
subs_pp = nfrows*nfcols
# This is a list where we'll store the figures
figures = list()
if(length(col_analyte) > 0){
col_group_all = c(col_group, col_analyte)
} else {
col_group_all = c(col_group)
}
# Constructing the mutate command based on the col_group_all above
mucmd = c(
"all_data = dplyr::mutate(all_data, GROUP_ALL = paste0(",
paste(col_group_all, collapse=",':',"),
"))"
)
eval(parse(text=paste0(mucmd, collapse="")))
fig_idx=1
while(length(subs_left) > 0){
fig_key = paste0("Figure_", fig_idx)
# Figuring out how many subjects to plot on the
# current figure
if(length(subs_left) < subs_pp){
last_sub = length(subs_left)
} else {
last_sub = subs_pp
}
subs_current = subs_left[c(1:last_sub)]
# This dataset contains the subset of the current subjects for plotting.
plot_ds = dplyr::filter(all_data, .data[[col_id]] %in% subs_current)
p = ggplot2::ggplot(data = plot_ds)
p = p + ggplot2::geom_line( ggplot2::aes(x=.data[["TIME"]],
y=.data[["CONC"]],
group=.data[["GROUP_ALL"]]),
linetype='dashed', color='grey')
if(length(col_analyte) == 1){
# If there is an analyte we set the shape based on the analyte column
p = p + ggplot2::geom_point(ggplot2::aes(x = .data[["TIME"]],
y = .data[["CONC"]],
shape = !!as.name(col_analyte),
group = .data[["GROUP_ALL"]],
color = .data[["PKNCA_DATA_TYPE"]]))
} else {
p = p + ggplot2::geom_point(ggplot2::aes(x = .data[["TIME"]],
y = .data[["CONC"]],
group = .data[["GROUP_ALL"]],
color = .data[["PKNCA_DATA_TYPE"]]))
}
p = p + ggplot2::facet_wrap(.~.data[[col_id]], ncol=nfcols, nrow=nfrows, scales=scales)
p = p + ggplot2::theme_light()
if(log_scale){
p = p + ggplot2::scale_y_log10()
}
p = p + ggplot2::xlab(TIME_LAB)
p = p + ggplot2::ylab(OBS_LAB)
p = p + ggplot2::labs(color="Data Type")
p = p + ggplot2::theme(legend.position="bottom")
figures[[fig_key]]$gg = p
figures[[fig_key]]$notes = NULL
# Removing the plotted subjects from the list
subs_left = subs_left[!(subs_left %in% subs_current)]
fig_idx = fig_idx+1
}
res = list(
figures = figures
)
res}
#'@export
#'@title Fetches the Current Analysis Object
#'@description Takes the current state and object type and returns the
#'currently selected object. For example if you have specified figure, it will
#'look at the output figure selected and the figure number of that figure and
#'return the ggplot object for that.
#'by subject id highlighting of certain NCA aspects (e.g. points used for half-life)
#'@param state NCA state from \code{NCA_fetch_state()}
#'@param obj_type Type of object to return (either "table" or "figure").
#'@return List with a format that depends on the obj_type.
#' For figures:
#'\itemize{
#' \item{ggplot:} ggplot object of the figure.
#' \item{isgood:} Return status of the function.
#' \item{msgs:} Messages to be passed back to the user.
#'}
#' For tables:
#'\itemize{
#' \item{df:} Dataframe of the current table.
#' \item{ft:} Flextable object of the current table.
#' \item{notes:} Any table notes to be included.
#' \item{isgood:} Return status of the function.
#' \item{msgs:} Messages to be passed back to the user.
#'}
#'@examples
#'# We need a state object to use below
#'sess_res = NCA_test_mksession(session=list(), full_session=FALSE)
#'state = sess_res$state
#'
#' # Current active table:
#' res = NCA_fetch_current_obj(state, "table")
#' res$ft
#'
#' # Current active figure:
#' res = NCA_fetch_current_obj(state, "figure")
#' res$ggplot
NCA_fetch_current_obj = function(state, obj_type){
obj = list()
isgood = TRUE
msgs = c()
obj_types = c("figure", "table")
if(obj_type %in% obj_types){
current_ana = NCA_fetch_current_ana(state)
if(current_ana[["isgood"]]){
if(obj_type == "figure"){
# We process this based on the fig_view
if( current_ana[["fig_view"]] == "fg_ind_obs"){
# This is the current facet page selected in the interface:
curr_fg_ind_obs = current_ana[["curr_fg_ind_obs"]]
if( curr_fg_ind_obs %in%
names(current_ana[["objs"]][["fg_ind_obs"]][["value"]][["figures"]])){
# Pulling out the ggplot object
obj[["ggplot"]] = current_ana[["objs"]][["fg_ind_obs"]][["value"]][["figures"]][[ curr_fg_ind_obs ]][["gg"]]
} else {
# This can happen when you are switching between a faceting that has
# more facets than the one you currently have. So if you go from a
# 1x1 facet and have figure 20 selected and then you switch to a
# 2x3. Then figure 20 doesn't exist any longer.
# In that case we just return the first value:
new_fg_ind_obs =names(current_ana[["objs"]][["fg_ind_obs"]][["value"]][["figures"]])[1]
obj[["ggplot"]] = current_ana[["objs"]][["fg_ind_obs"]][["value"]][["figures"]][[ new_fg_ind_obs ]][["gg"]]
}
} else {
isgood = FALSE
msgs = paste0("Unknown figure output: ", current_ana[["fig_view"]])
obj[["ggplot"]] = formods::FM_mk_error_fig(msgs)
}
}
if(obj_type == "table"){
# We process this based on the tab_view
# Individual observations:
if( current_ana[["tab_view"]] == "tb_ind_obs"){
# This is the current table page selected in the interface:
curr_tb_ind_obs = current_ana[["curr_tb_ind_obs"]]
if( curr_tb_ind_obs %in%
names(current_ana[["objs"]][["tb_ind_obs"]][["value"]][["tables"]])){
# Pulling out the current table object
obj = current_ana[["objs"]][["tb_ind_obs"]][["value"]][["tables"]][[ curr_tb_ind_obs ]]
} else {
# In that case we just return the first value:
new_tb_ind_obs =names(current_ana[["objs"]][["tb_ind_obs"]][["value"]][["tables"]])[1]
obj = current_ana[["objs"]][["tb_ind_obs"]][["value"]][["tables"]][[ new_tb_ind_obs ]]
}
# NCA raw:
} else if( current_ana[["tab_view"]] == "tb_nca_raw"){
# The raw output is just pulled from the raw results:
obj[["df"]] = as.data.frame(current_ana[["objs"]][["res"]][["value"]])
obj[["ft"]] = flextable::flextable(as.data.frame(current_ana[["objs"]][["res"]][["value"]]))
obj[["notes"]] = ""
# Table of individual NCA parameters
} else if( current_ana[["tab_view"]] == "tb_ind_params"){
# This is the current table page selected in the interface:
curr_tb_ind_params = current_ana[["curr_tb_ind_params"]]
if( curr_tb_ind_params %in%
names(current_ana[["objs"]][["tb_ind_params"]][["value"]][["tables"]])){
# Pulling out the current table object
obj = current_ana[["objs"]][["tb_ind_params"]][["value"]][["tables"]][[ curr_tb_ind_params ]]
} else {
# In that case we just return the first value:
new_tb_ind_params =names(current_ana[["objs"]][["tb_ind_params"]][["value"]][["tables"]])[1]
obj = current_ana[["objs"]][["tb_ind_params"]][["value"]][["tables"]][[ new_tb_ind_params ]]
}
# Summary of NCA Parameters
} else if( current_ana[["tab_view"]] == "tb_sum_params"){
# JMH add NCA parameters summary view
isgood = FALSE
msgs = paste0("Placeholder for table not yet defined: ", current_ana[["tab_view"]])
} else{
isgood = FALSE
msgs = paste0("Unknown table output: ", current_ana[["tab_view"]])
}
}
}
} else {
isgood = FALSE
msgs = c(msgs, paste0("Unknown object type: ", obj_type))
}
# Appending msgs and isgood status
obj[["isgood"]] = isgood
obj[["msgs"]] = msgs
obj}
#'@export
#'@title Create Tabular Output from PKNCA Results
#'@description Create paginated tables from PKNCA to use in reports and Shiny
#'apps.
#'@param nca_res Output of PKNCA.
#'@param type Type of table to generate. Can be either \code{"individual"} or \code{"summary"]}.
#'@param grouping How to group columns in tables. Can be either \code{"interval"} or \code{"parameter"]}.
#'@param not_calc Text string to replace NA values with to indicated values were not calculated.
#'@param mult_str Text string to replace * values in units.
#'@param infinity Text string to replace infinity in time intervals in column headers.
#'@param obnd onbrand reporting object.
#'@param nps NCA parameter summary table with the following columns.
#' \itemize{
#' \item{parameter:} PKNCA Paramter name.
#' \item{text:} Name used in text output.
#' \item{md:} Name used markdown output.
#' \item{latex:} Name used in latex output.
#' \item{description:} Verbose textual description of the parameter.
#' }
#'@param digits Number of significant figures to report (set to \code{NULL} to disable rounding)
#'@param text_format Either \code{"md"} for markdown or \code{"text"} (default) for plain text.
#'@param notes_detect Vector of strings to detect in output tables (example \code{c("NC", "BLQ")}).
#'@param max_width Maximum width of the final table in inches (A value of \code{NULL} will use 100 inches).
#'@param max_height Maximum height of the final table in inches (A value of \code{NULL} will use 100 inches).
#'@param max_col Maximum number of columns to have on a page. Spillover will be wrapped to multiple pages.
#'@param max_row Maximum number of rows to have on a page. Spillover will hang over the side of the page..
#'@return list containing the following elements
#'\itemize{
#' \item{raw_nca:} Raw PKNCA output.
#' \item{isgood:} Boolean indicating the exit status of the function.
#' \item{one_table:} Dataframe of the entire table with the first lines containing the header.
#' \item{one_body:} Dataframe of the entire table (data only).
#' \item{one_header:} Dataframe of the entire header (row and body, no data).
#' \item{tables:} Named list of tables. Each list element is of the output
#' \item{msgs:} Vector of text messages describing any errors that were found.
#' format from \code{\link[onbrand]{build_span}}.
#'}
#'@examples
#'id = "NCA"
#'id_UD = "UD"
#'id_DW = "DW"
#'id_ASM = "ASM"
#'
#'# We need a state variable to be define
#' sess_res = NCA_test_mksession(session=list(),
#' id = id,
#' id_UD = id_UD,
#' id_DW = id_DW,
#' id_ASM = id_ASM,
#' full_session=FALSE)
#'
#'state = sess_res$state
#'
#'# Pulls out the active analysis
#'current_ana = NCA_fetch_current_ana(state)
#'
#'# This is the raw PKNCA output
#'pknca_res = NCA_fetch_ana_pknca(state, current_ana)
#'
#'# Parameter reporting details from the ruminate configuration
#'nps = state[["NCA"]][["nca_parameters"]][["summary"]]
#'
#'# Building the figure
#'mk_res = mk_table_nca_params(nca_res = pknca_res, nps=nps, digits=3)
#'mk_res$tables[["Table 1"]]$ft
mk_table_nca_params = function(
nca_res ,
type = "individual",
grouping = "interval",
not_calc = "NC",
obnd = NULL,
nps = NULL,
mult_str = "*",
# JMH make sure this is used as intended below
infinity = "inf",
digits = NULL,
text_format = "text",
notes_detect = NULL,
max_height = 7,
max_width = 6.5,
max_row = NULL,
max_col = NULL){
# Pulling out the different pieces from the PKNCA object
raw_nca = as.data.frame(nca_res)
intervals = nca_res[["data"]][["intervals"]]
# Extracting the needed column names:
col_id = nca_res[["data"]][["conc"]][["columns"]][["subject"]]
col_group = c(nca_res[["data"]][["conc"]][["columns"]][["groups"]][["group_vars"]],
nca_res[["data"]][["conc"]][["columns"]][["groups"]][["group_analyte"]])
# This holds a summary of the interval information. Essentially it contains
# any parameter name where there was a request output (for any interval):
int_sum = c()
ints_all = names(intervals)[!(names(intervals) %in% c("start", "end"))]
for(iname in ints_all){
if(any(intervals[[iname]])){
int_sum = c(int_sum, iname)
}
}
# These are just the NCA data the user requested:
nca_data = dplyr::filter(raw_nca, .data[["PPTESTCD"]] %in% int_sum)
# Determining if we have multiple dose data or not:
if(unique(length(nca_data[["DOSE_NUM"]])) > 1){
IS_MD = TRUE
} else{
IS_MD = FALSE
}
# Determining if we have units
if(is.null(nca_res[["data"]][["units"]])){
HAS_UNITS = FALSE
} else{
HAS_UNITS = TRUE
}
# Applying significant digits
if(!is.null(digits)){
nca_data[["PPORRES"]] = signif(digits=digits, nca_data[["PPORRES"]])
}
int_temp = "[===START===,===END===]"
nca_data = nca_data |>
dplyr::mutate(range = int_temp) |>
dplyr::mutate(range = stringr::str_replace(
string = .data[["range"]],
pattern = "===START===",
replacement = as.character(.data[["start"]]))) |>
dplyr::mutate(range = stringr::str_replace(
string = .data[["range"]],
pattern = "===END===",
replacement = as.character(.data[["end"]]))) |>
dplyr::mutate(range = stringr::str_replace(
string = .data[["range"]],
pattern = "Inf",
replacement = infinity))
if(type == "summary"){
# JMH create summary table here
}
if(type == "indiviudal"){
# NAs come from parameters that were not calculated for whatever reason.
# Having NAs pop up in reports is kind of sloppy so here we replace them
# with the user-specified value:
nca_data = nca_data |>
dplyr::mutate(PPORRES =as.character(.data[["PPORRES"]])) |>
dplyr::mutate(PPORRES = ifelse(.data[["PPORRES"]] == "NA",
not_calc,
.data[["PPORRES"]] ))
}
# We're going to group by everything except the id
rpt_name_group = c(col_group[!(col_group %in% col_id)])
nca_data = dplyr::mutate(nca_data,
pnames=paste0(.data[["PPTESTCD"]],
":",
.data[["range"]]))
# We're separating out the data from the other elements of the table
# like parameter names, intervals, etc so we'll have two different
# objects:
# - tdata:
# Data frame with the actual data to be reported.
# - nca_data:
# This has the same information in long format and can be
# used to look up things like units when constructing the
# headers for reporting.
# ID isn't present in sparse sampling
col_keep = c()
if(col_id %in% names(nca_data)){
col_keep = c(col_keep, col_id)
}
col_keep = c(col_keep, rpt_name_group, "pnames", "PPORRES")
tdata = nca_data |>
dplyr::mutate(PPORRES = ifelse(is.na(.data[["PPORRES"]]), not_calc, .data[["PPORRES"]])) |>
dplyr::select(dplyr::all_of(col_keep)) |>
tidyr::pivot_wider(names_from="pnames",
values_from="PPORRES")
# Creating a lookup table to group output and create headers
col_lookup = nca_data |>
dplyr::group_by(.data[["pnames"]]) |>
dplyr::filter(row_number() == 1) |>
dplyr::rename(parameter = "PPTESTCD")
col_lookup_keep = c("range", "pnames", "parameter")
if(HAS_UNITS){
col_lookup_keep = c(col_lookup_keep, "units")
col_lookup = dplyr::rename(col_lookup, units="PPORRESU")
}
# This is lookup with information from the dataset:
col_lookup = dplyr::select(col_lookup,dplyr::all_of(col_lookup_keep))
# Now we need to merge in the column names used for reporting:
nps_found =
dplyr::filter(nps, .data[["parameter"]] %in% col_lookup[["parameter"]]) |>
dplyr::right_join(col_lookup, by=c("parameter"="parameter"))
if(grouping == "interval"){
if(text_format == "md"){
nps_found = dplyr::arrange(nps_found, .data[["range"]], .data[["md"]])
} else {
nps_found = dplyr::arrange(nps_found, .data[["range"]], .data[["text"]])
}
}
if(grouping == "parameter"){
if(text_format == "md"){
nps_found = dplyr::arrange(nps_found, .data[["md"]], .data[["range"]])
} else {
nps_found = dplyr::arrange(nps_found, .data[["text"]], .data[["range"]])
}
}
# ID isn't present in sparse sampling
col_keep_id = c()
if(col_id %in% names(nca_data)){
col_keep_id = col_id
}
# Now we reorder the columns of tdata according to the grouping above:
tdata = dplyr::select(tdata,
dplyr::all_of(c(col_keep_id, rpt_name_group, nps_found[["pnames"]])))
# Rows that are common for each table:
row_common = dplyr::select(tdata, dplyr::all_of(c(col_keep_id, rpt_name_group)))
# This is an edge case from sparse sampling where there is one profile. For
# sparse sampling there is no ID and if there is only one group then then
# there is no common row. In this instance we have to create one in case it
# spills over onto multiple pages.
if(ncol(row_common) == 0){
ROW = "Row"
row_common =
dplyr::tibble(!!ROW := 1:nrow(tdata))
}
# The table body
table_body = dplyr::select(tdata, dplyr::all_of((nps_found[["pnames"]])))
# Identifies which of the common rows to highlight.
table_body_head = c()
row_common_head = c()
# here we're repalcing the multiplication sign in the units with
# whatever is in the mult_str:
if(HAS_UNITS){
nps_found[["units"]] = stringr::str_replace(
string = nps_found[["units"]],
pattern = "\\*",
replacement = mult_str)
}
# Here we pull out the headers based on the text format specieid
if(text_format == "md"){
pheader_names = nps_found[["md"]]
} else {
pheader_names = nps_found[["text"]]
}
# Headers are calculated differently with and without units:
if(HAS_UNITS){
table_body_head = matrix(
data = c(pheader_names, nps_found[["units"]], nps_found[["range"]]),
byrow = TRUE,
ncol = nrow(nps_found))
row_common_head = matrix(
data = c(names(row_common), rep("", ncol(row_common)*2)),
byrow = TRUE,
ncol = ncol(row_common) )
} else {
table_body_head = matrix(
data = c(pheader_names, nps_found[["range"]]),
byrow = TRUE,
ncol = nrow(nps_found))
row_common_head = matrix(
data = c(names(row_common), rep("", ncol(row_common))),
byrow = TRUE,
ncol = ncol(row_common) )
}
stres = onbrand::span_table(
table_body = table_body,
row_common = row_common,
table_body_head = table_body_head,
row_common_head = row_common_head,
obnd = obnd,
header_format = text_format,
max_width = max_width,
max_height = max_height,
max_row = max_row,
max_col = max_col,
notes_detect = notes_detect)
res = list(
raw_nca = raw_nca,
isgood = stres[["isgood"]],
one_table = stres[["one_table"]],
one_header = stres[["one_header"]],
one_body = stres[["one_body"]],
tables = stres[["tables"]],
msgs = stres[["msgs"]]
)
res}
#'@export
#'@title Populate Session Data for Module Testing
#'@description Populates the supplied session variable for testing.
#'@param session Shiny session variable (in app) or a list (outside of app)
#'@param id An ID string that corresponds with the ID used to call the modules UI elements
#'@param id_UD An ID string that corresponds with the ID used to call the UD modules UI elements
#'@param id_DW An ID string that corresponds with the ID used to call the DW modules UI elements
#'@param id_ASM An ID string that corresponds with the ID used to call the ASM modules UI elements
#'@param full_session Boolean to indicate if the full test session should be created (default \code{TRUE}).
#'@return list with the following elements
#' \itemize{
#' \item{isgood:} Boolean indicating the exit status of the function.
#' \item{session:} The value Shiny session variable (in app) or a list (outside of app) after initialization.
#' \item{input:} The value of the shiny input at the end of the session initialization.
#' \item{state:} App state.
#' \item{rsc:} The \code{react_state} components.
#'}
#'@examples
#'sess_res = NCA_test_mksession(session=list(), full_session=FALSE)
NCA_test_mksession = function(session, id = "NCA", id_UD="UD", id_DW="DW", id_ASM="ASM", full_session=TRUE){
isgood = TRUE
rsc = NULL
input = list()
# Populating the session with UD and DW components
sess_res = formods::DW_test_mksession(session=session, id=id_DW, id_UD = id_UD)
if(!("ShinySession" %in% class(session))){
session = sess_res[["session"]]
}
# When we dont want a full session we want to shrink the dataset to this
# will be faster on the CRAN win-builder system:
if(!full_session){
all_ids = unique(session[["userData"]][["FM"]][["FM_DW"]][["DW"]][["views"]][["view_7"]][["WDS"]][["ID"]])
nkeep = 3
if(length(all_ids) > nkeep){
keep_ids = all_ids[1:nkeep]
}else{
keep_ids = all_ids
}
bool_keep = session[["userData"]][["FM"]][["FM_DW"]][["DW"]][["views"]][["view_7"]][["WDS"]][["ID"]] %in% keep_ids
session[["userData"]][["FM"]][["FM_DW"]][["DW"]][["views"]][["view_7"]][["WDS"]] =
session[["userData"]][["FM"]][["FM_DW"]][["DW"]][["views"]][["view_7"]][["WDS"]][bool_keep, ]
}
# Pulling out the react state components
rsc = sess_res$rsc
react_state = rsc
# YAML files for the fetch calls below
FM_yaml_file = system.file(package = "formods", "templates", "formods.yaml")
MOD_yaml_file = system.file(package = "ruminate", "templates", "NCA.yaml")
# Creating an empty state object
state = NCA_fetch_state(id = id,
input = input,
session = session,
FM_yaml_file = FM_yaml_file,
MOD_yaml_file = MOD_yaml_file,
id_ASM = id_ASM,
id_UD = id_UD,
id_DW = id_DW,
react_state = react_state)
#------------------------------------
# First First dose PK only with BQL values
current_ana = NCA_fetch_current_ana(state)
# Setting the dataset:
current_ana[["ana_dsview"]] = "DW_myDS_7"
# Defining the columns
current_ana[["col_id"]] = "ID"
current_ana[["col_time"]] = "TIME_DY"
current_ana[["col_ntime"]] = "NTIME_DY"
current_ana[["col_conc"]] = "DV"
current_ana[["col_evid"]] = "EVID"
current_ana[["col_dose"]] = "DOSE"
current_ana[["col_route"]] = "ROUTE"
current_ana[["col_cycle"]] = "DOSE_NUM"
current_ana[["col_analyte"]] = "N/A"
current_ana[["col_dur"]] = "N/A"
# Defining where how dosing should be found:
current_ana[["dose_from"]] = "cols"
# Setting the caption/analysis key
current_ana[["key"]] = "PK NCA Analysis Example"
# This will update the changes to the current analysis:
state = NCA_set_current_ana(state, current_ana)
# This will load the scenario
state = NCA_load_scenario(state, "sd_iv")
# And then this will run the intervals in the scenario:
state = run_nca_components(state)
#------------------------------------
# First First dose PK/PD with BQL values
# Create a new analysis
if(full_session){
state = NCA_new_ana(state)
current_ana = NCA_fetch_current_ana(state)
# Setting the dataset:
current_ana[["ana_dsview"]] = "DW_myDS_6"
# Setting the caption/analysis key
current_ana[["key"]] = "PK/PD NCA Analysis Example"
# Defining the columns
current_ana[["col_id"]] = "ID"
current_ana[["col_time"]] = "TIME_DY"
current_ana[["col_ntime"]] = "NTIME_DY"
current_ana[["col_conc"]] = "DV"
current_ana[["col_dose"]] = "DOSE"
current_ana[["col_evid"]] = "EVID"
current_ana[["col_route"]] = "ROUTE"
current_ana[["col_cycle"]] = "DOSE_NUM"
current_ana[["col_analyte"]] = "CMT" #Analyte
current_ana[["col_dur"]] = "N/A" #Duration
# Defining where how dosing should be found:
current_ana[["dose_from"]] = "cols"
# This will update the changes to the current analysis:
state = NCA_set_current_ana(state, current_ana)
# This will load the scenario
state = NCA_load_scenario(state, "sd_iv")
# And then this will run the intervals in the scenario:
state = run_nca_components(state)
}
#------------------------------------
# This functions works both in a shiny app and outside of one
# if we're in a shiny app then the 'session' then the class of
# session will be a ShinySession. Otherwise it'll be a list if
# we're not in the app (ie just running test examples) then
# we need to set the state manually
if(("ShinySession" %in% class(session))){
FM_set_mod_state(session, id, state)
} else {
session = FM_set_mod_state(session, id, state)
}
# Required for proper reaction:
#rsc[[id]] = list(FG = list(checksum=state[["FG"]][["checksum"]]))
res = list(
isgood = isgood,
session = session,
input = input,
state = state,
rsc = rsc
)
res}
#'@title Loads Pre-Defined Scenario
#'@description Loads a pre-defined analysis scneario from the NCA YAML config
#'file.
#'@param state NCA state from \code{NCA_fetch_state()}
#'@param ana_scenario Short name of the analysis scenario to load from the config file.
#'@return NCA state object with the scenario loaded and relevant notifications
#'set.
NCA_load_scenario = function(state, ana_scenario){
formods::FM_le(state, paste0("loading analysis scenario: ", ana_scenario))
scenario_def = state[["MC"]][["ana_scenarios"]][[ana_scenario]]
# Pulling out the current analysis
current_ana = NCA_fetch_current_ana(state)
# Overwriting the scenario components in the current analysis
current_ana[["nca_parameters"]] = scenario_def[["nca_parameters"]]
current_ana[["sampling"]] = scenario_def[["sampling"]]
# Removing any previous intervals
current_ana[["intervals"]] = NULL
# Storing any changes here:
state = NCA_set_current_ana(state, current_ana)
# The current analysis will be further updated internally
# in NCA_add_init()
for(int_idx in 1:length(scenario_def[["intervals"]])){
scenario_row = scenario_def[["intervals"]][[int_idx]]
interval_start = as.numeric(as.character(scenario_row$row[["start"]]))
interval_stop = as.numeric(as.character(scenario_row$row[["stop"]]))
nca_parameters = scenario_row$row[["nca_parameters"]]
state = NCA_add_int(state=state,
interval_start = interval_start,
interval_stop = interval_stop,
nca_parameters = nca_parameters)
}
notify_text = paste0("Scenario: ", state[["MC"]][["ana_scenarios"]][[current_ana[["ana_scenario"]]]][["description"]])
state = FM_set_notification(state, notify_text, "NCA scenario set", "info")
state}
#'@export
#'@title Builds Dose Records Dataframe
#'@description Takes information about columns in dataset and constructs the
#'dosing records.
#'@param NCA_DS Dataset containing dosing records.
#'@param dose_from Method of dose extraction either "cols" or "rows".
#'@param col_id Name of column with subject ID.
#'@param col_time Name of column with time since first dose.
#'@param col_ntime Name of column with time since the last dose (required with \code{dose_from="cols"}).
#'@param col_route Name of column with route information.
#'@param col_dose Name of column with last dose given.
#'@param col_cycle Name of column with dose cycle (required with \code{dose_from="cols"}).
#'@param col_dur Name of column with dose duration.
#'@param col_evid Name of column with event ID (required with \code{dose_from="rows"}).
#'@param col_analyte Name of column with analyte (optional).
#'@param col_group Names of columns with grouping information (optionl).
#'@return list containing the following elements
#'\itemize{
#' \item{isgood:} Return status of the function.
#' \item{msgs:} Messages to be passed back to the user.
#' \item{dose_rec:}
#'}
#'@examples
#'
#'if(system.file(package="readxl") !=""){
#'library(dplyr)
#'library(readxl)
#'library(stringr)
#'
#'# Example data file:
#'data_file = system.file(package="formods","test_data","TEST_DATA.xlsx")
#'
#'# Dataset formatted to extract dosing from columns
#'DS_cols = readxl::read_excel(path=data_file, sheet="DATA") |>
#' dplyr::filter(EVID == 0) |>
#' dplyr::filter(DOSE %in% c(3)) |>
#' dplyr::filter(str_detect(string=Cohort, "^MD")) |>
#' dplyr::filter(CMT == "C_ng_ml")
#'
#'drb_res = dose_records_builder(
#' NCA_DS = DS_cols,
#' dose_from = "cols",
#' col_id = "ID",
#' col_time = "TIME_DY",
#' col_ntime = "NTIME_DY",
#' col_route = "ROUTE",
#' col_cycle = "DOSE_NUM",
#' col_dose = "DOSE",
#' col_group = "Cohort")
#'
#' utils::head(drb_res$dose_rec)
#'
#'# Dataset formatted to extract dosing from rows (records)
#'DS_rows = readxl::read_excel(path=data_file, sheet="DATA") |>
#' dplyr::filter(DOSE %in% c(3)) |>
#' dplyr::filter(str_detect(string=Cohort, "^MD")) |>
#' dplyr::filter(CMT %in% c("Ac", "C_ng_ml"))
#'
#'drb_res = dose_records_builder(
#' NCA_DS = DS_rows,
#' dose_from = "rows",
#' col_id = "ID",
#' col_time = "TIME_DY",
#' col_ntime = "NTIME_DY",
#' col_route = "ROUTE",
#' col_dose = "AMT",
#' col_evid = "EVID",
#' col_group = "Cohort")
#'
#' utils::head(drb_res$dose_rec)
#'}
dose_records_builder = function(
NCA_DS = NULL,
dose_from = NULL,
col_id = NULL,
col_time = NULL,
col_ntime = NULL,
col_route = NULL,
col_dose = NULL,
col_cycle = NULL,
col_dur = NULL,
col_evid = NULL,
col_analyte = NULL,
col_group = NULL){
isgood = TRUE
msgs = c()
dose_rec = NULL
# These columns are required generally
required_cols = c(
"col_id",
"col_time",
"col_route",
"col_dose")
other_cols = c(
"col_group",
"col_dur",
"col_analyte")
# Checking user input
# Dose from:
dose_from_allowed = c("rows", "cols")
if(is.null(dose_from)){
msgs = c(msgs, "must specify dose_from")
isgood = FALSE
} else {
if(dose_from %in% dose_from_allowed){
# We append other required columns based on
# how dosing records are to be determined:
if(dose_from == "cols"){
required_cols = c(required_cols, "col_ntime", "col_cycle")
} else if(dose_from == "rows"){
required_cols = c(required_cols, "col_evid")
}
}else{
msgs = c(msgs, "dose_from invalid must be one of:")
msgs = c(msgs, paste0(" ", paste0(dose_from_allowed, collapse=", ")))
isgood = FALSE
}
}
# Next we check the required columns
if(isgood){
for(cname in required_cols){
if(is.null(get(cname))){
isgood = FALSE
msgs = c(msgs, paste0("required column >", cname, "< not specified"))
} else if(!(get(cname) %in% names(NCA_DS))) {
isgood = FALSE
msgs = c(msgs, paste0("required column >", cname, "< not found in dataset"))
}
}
}
# This constructs the dosing records:
if(isgood){
# These are the subset of columns that are kept in the
# dose records data frame:
dose_select_cols = c(
col_id,
col_time,
col_dose,
col_route)
# Appending optional columns if they were specified
if(!is.null(col_group)){
if(col_group != ""){
dose_select_cols = c(dose_select_cols, col_group)
}
}
if(!is.null(col_dur)){
if(col_dur != "N/A"){
dose_select_cols = c(dose_select_cols, col_dur)
}
}
if(!is.null(col_analyte)){
if(col_analyte != "N/A"){
dose_select_cols = c(dose_select_cols, col_analyte)
}
}
if(dose_from == "cols"){
#--------------------------
# columns are used for grouping when finding
# unique dose columns
unique_dose = c()
# Adding the optional grouping columns
if(!is.null(col_group)){
if(col_group != ""){
unique_dose = c(unique_dose,
col_group)
}
}
# Adding the cycle and ID columns:
unique_dose = c(unique_dose, col_cycle, col_id)
dose_rec =
dplyr::group_by(NCA_DS, dplyr::across(dplyr::all_of(c(unique_dose)))) |> # Pulling out one row for
dplyr::filter(row_number() == 1) |> # each dosing record
dplyr::ungroup() |>
dplyr::mutate(!! col_time := .data[[col_time]] - .data[[col_ntime]]) |> # Calculating the dose time from on the nominal offset
dplyr::select( dplyr::all_of(dose_select_cols))
} else if(dose_from == "rows"){
# Pulling out all of the columns where EVID is 1
dose_rec =
dplyr::filter(NCA_DS,.data[[col_evid]] == 1) |> # EVID =1 for dosing records
dplyr::select( dplyr::all_of(dose_select_cols))
}
}
if(!isgood){
msgs = c(msgs, "dose_records_builder()")
}
res = list(isgood = isgood,
msgs = msgs,
dose_rec = dose_rec)
res}
#'@export
#'@title Fetch Analysis Dataset
#'@description Fetches the dataset used for the specified analysis
#'@param state NCA state from \code{NCA_fetch_state()}
#'@param current_ana Current value in the analysis
#'@return Dataset from the \code{ds} field of FM_fetch_ds()
#'@example inst/test_apps/NCA_funcs.R
NCA_fetch_ana_ds = function(state, current_ana){
ds = NULL
dsview = current_ana[["ana_dsview"]]
if(is.null(dsview)){
FM_le(state = state,
paste0("Unable to find dsview >", dsview ,"< for the current analysis"),
entry_type = "danger")
} else {
ds = state[["NCA"]][["DSV"]][["ds"]][[dsview]][["DS"]]
}
ds}
#'@export
#'@title Fetch PKNCA Results Object
#'@description Fetches the PKNCA output for a specified analysis
#'@param state NCA state from \code{NCA_fetch_state()}
#'@param current_ana Current value in the analysis
#'@return Dataset from the \code{ds} field of FM_fetch_ds()
#'@example inst/test_apps/NCA_funcs.R
NCA_fetch_ana_pknca = function(state, current_ana){
pknca_res = current_ana[["objs"]][["res"]][["value"]]
pknca_res}
#'@export
#'@title Fetch PKNCA Results Object
#'@description Fetches the PKNCA output for a specified analysis
#'@param state NCA state from \code{NCA_fetch_state()}
#'@param ana_id Analysis ID to make active.
#'@return State with the analysis ID made active.
#' JMH add to example script below
#'@example inst/test_apps/NCA_funcs.R
NCA_mkactive_ana = function(state, ana_id){
state[["NCA"]][["current_ana"]] = state[["NCA"]][["ui"]][["select_current_ana"]]
# Column values are found based on heuristics that include the current
# value in the ui. This will overwrite the current ui column values tracked with
# those for the current analysis.
current_ana = NCA_fetch_current_ana(state)
col_uis = names(state[["NCA"]][["ui"]])
col_uis = col_uis[ stringr::str_detect(col_uis, "^select_ana_col") ]
for(col_ui in col_uis){
ana_name = state[["NCA"]][["ui_ana_map"]][[col_ui]]
state[["NCA"]][["ui"]][[col_ui]] = current_ana[[ana_name]]
}
#state = NCA_set_current_ana(state, current_ana)
state}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.