Skip to content

Commit

Permalink
Merge pull request #172 from pharmaverse/enhancement/run-app-via-pack…
Browse files Browse the repository at this point in the history
…age-installation2

Enhancement/run app via package installation
  • Loading branch information
m-kolomanski authored Jan 24, 2025
2 parents 1793136 + bc95a6f commit 5048ec0
Show file tree
Hide file tree
Showing 17 changed files with 149 additions and 171 deletions.
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ When the change is done, pull request is open and the description is filled, ple
#### For reviewers
When reviewing a pull request, please do try to follow the [conventional comments](https://conventionalcomments.org/) guidelines. Ideas and labels described in that convention can be very helpful in getting your thoughts across and facilitate meaningful cooperation. That said, they are not applicable in every circumstance and you are free to do whatever you feel is suitable, as long as it aims to provide valid discussion.

# Beware
- The package is split into two parts: the R package and a shiny application. Logic code, which is useful on its own and can be easily run via the console should be placed in the `R/` directory. Code that is strictly related to **Shiny** application, especially code that generates some interface elements, should be placed in `inst/shiny/` folder.
- The package requires some dependencies for which there are no explicit `@import` statements in the `NAMESPACE` file. This is because some of those functions are not used in the **package** itself, but rather in the **Shiny application**. Please beware of this situation when managing the package dependencies - some functions might be used in the app, even though they are not verbosely imported.

# In-depth guides
Here are some useful links with in-depth documentation regarding specific parts of the pacakage and how to utilise in-build tools to extend the capabilities of the application:

Expand Down
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: aNCA
Title: (Pre-)Clinical NCA in a Dynamic Shiny App
Version: 0.0.0.9000
Version: 0.0.0.9001
Authors@R: c(
person("Ercan", "Suekuer", , "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0009-0001-1626-1526")),
Expand Down
55 changes: 3 additions & 52 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ export(apply_filters)
export(apply_labels)
export(as_factor_preserve_label)
export(calculate_summary_stats)
export(check_slope_rule_overlap)
export(create_start_impute)
export(export_cdisc)
export(filter_breaks)
export(filter_slopes)
export(flexible_violinboxplot)
export(format_pkncaconc_data)
export(format_pkncadata_intervals)
Expand All @@ -26,105 +29,53 @@ export(parse_annotation)
export(parse_tlg_definitions)
export(pivot_wider_pknca_results)
export(pkcg01)
export(pptestcd_dict)
export(run_app)
export(set_empty_label)
import(bslib)
import(dplyr)
import(forcats)
import(ggplot2)
import(haven)
import(nestcolor)
import(plotly)
import(shiny)
import(tidyr)
importFrom(DT,DTOutput)
importFrom(DT,datatable)
importFrom(DT,formatStyle)
importFrom(DT,renderDataTable)
importFrom(DT,styleEqual)
importFrom(PKNCA,PKNCA.options)
importFrom(PKNCA,PKNCAconc)
importFrom(PKNCA,PKNCAdata)
importFrom(PKNCA,PKNCAdose)
importFrom(PKNCA,pk.calc.c0)
importFrom(PKNCA,pk.nca)
importFrom(PKNCA,pknca_units_table)
importFrom(checkmate,assert_numeric)
importFrom(dplyr,across)
importFrom(dplyr,arrange)
importFrom(dplyr,case_when)
importFrom(dplyr,distinct)
importFrom(dplyr,filter)
importFrom(dplyr,group_by)
importFrom(dplyr,left_join)
importFrom(dplyr,mutate)
importFrom(dplyr,n)
importFrom(dplyr,pull)
importFrom(dplyr,rename)
importFrom(dplyr,rename_with)
importFrom(dplyr,rowwise)
importFrom(dplyr,select)
importFrom(dplyr,slice)
importFrom(dplyr,summarise)
importFrom(dplyr,ungroup)
importFrom(dplyr,where)
importFrom(ggh4x,scale_y_facet)
importFrom(ggplot2,aes)
importFrom(ggplot2,facet_wrap)
importFrom(ggplot2,geom_errorbar)
importFrom(ggplot2,geom_line)
importFrom(ggplot2,geom_point)
importFrom(ggplot2,ggplot)
importFrom(ggplot2,ggplot_build)
importFrom(ggplot2,ggplot_gtable)
importFrom(ggplot2,labs)
importFrom(ggplot2,scale_x_continuous)
importFrom(glue,glue)
importFrom(grid,convertUnit)
importFrom(htmlwidgets,JS)
importFrom(logger,log_debug)
importFrom(logger,log_error)
importFrom(logger,log_fatal)
importFrom(logger,log_info)
importFrom(logger,log_trace)
importFrom(logger,log_warn)
importFrom(magrittr,`%>%`)
importFrom(plotly,event_data)
importFrom(plotly,plotlyOutput)
importFrom(plotly,plotly_build)
importFrom(plotly,renderPlotly)
importFrom(purrr,imap)
importFrom(reactable,colDef)
importFrom(reactable,getReactableState)
importFrom(reactable,reactable)
importFrom(reactable,reactableOutput)
importFrom(reactable,reactableTheme)
importFrom(reactable,renderReactable)
importFrom(reactable.extras,dropdown_extra)
importFrom(reactable.extras,text_extra)
importFrom(rio,export_list)
importFrom(rlang,sym)
importFrom(rmarkdown,render)
importFrom(scales,breaks_log)
importFrom(scales,label_log)
importFrom(shinyBS,bsModal)
importFrom(shinyFiles,shinyDirChoose)
importFrom(shinyWidgets,dropdown)
importFrom(shinyWidgets,pickerInput)
importFrom(shinyWidgets,switchInput)
importFrom(shinyWidgets,updatePickerInput)
importFrom(shinycssloaders,withSpinner)
importFrom(shinyjqui,orderInput)
importFrom(shinyjqui,updateOrderInput)
importFrom(stats,sd)
importFrom(stringi,stri_rand_strings)
importFrom(tern,g_ipp)
importFrom(tidyr,pivot_longer)
importFrom(tidyr,pivot_wider)
importFrom(tools,file_ext)
importFrom(units,set_units)
importFrom(utils,read.csv)
importFrom(utils,write.csv)
importFrom(yaml,read_yaml)
importFrom(zip,zipr)
54 changes: 25 additions & 29 deletions R/export_cdisc.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,6 @@
#'
#' @import dplyr
#' @export


# Define the unique combinations
pptestcd_dict <- setNames(
c(
"Total CL Obs by F", "Time of Last Nonzero Conc", "Max Conc", "Vz Obs by F", "AUC Infinity Obs",
"Last Nonzero Conc", "Time of CMAX", "R Squared", "R Squared Adjusted", "Max Conc Norm by Dose",
"AUC to Last Nonzero Conc Norm by Dose", "Lambda z", "AUC to Last Nonzero Conc",
"Half-Life Lambda z", "Number of points used for Lambda z", "Last Nonzero Conc Predicted",
"Span Ratio", "Lambda z lower limit (time)",

# Manually filled
"Trough Concentration", "Average Concentration", "AUC Infinity Predicted",
"AUMC Infinity Observed", "AUC Percent Extrapolated Observed",
"AUC Percent Extrapolated Predicted", "Clearance Observed",
"Clearance Predicted", "Mean Residence Time Intravenous Observed",
"Volume of Distribution Observed",
"Steady-State Volume of Distribution Intravenous Observed",
"AUC Infinity Observed Dose-Normalized", "Maximum Concentration Dose-Normalized"
),
c("CLFO", "TLST", "CMAX", "VZFO", "AUCIFO", "CLST", "TMAX", "R2", "R2ADJ", "CMAXD", "AUCLSTD",
"LAMZ", "AUCLST", "LAMZHL", "LAMZNPT", "CLSTP", "LAMZSPNR", "LAMZLL",
"CTROUGH", "CAV", "AUCIFP", "AUMCINF.OBS", "AUCPEO", "AUCPEP", "CL.OBS", "CL.PRED",
"MRT.IV.OBS", "VZ.OBS", "VSS.IV.OBS", "AUCINF.OBS.DN", "CMAX.DN"
)
)


export_cdisc <- function(res_nca) {
if (FALSE) {
# uncomment in case of more added variables
Expand Down Expand Up @@ -192,7 +164,7 @@ export_cdisc <- function(res_nca) {
PPENINT = ifelse(end != Inf, end, NA)
) %>%
# Map PPTEST CDISC descriptions using PPTESTCD CDISC names
mutate(PPTEST = pptestcd_dict[PPTESTCD]) %>%
mutate(PPTEST = .pptestcd_dict[PPTESTCD]) %>%
group_by(USUBJID) %>%
mutate(PPSEQ = if ("PCSEQ" %in% names(.)) PCSEQ else row_number()) %>%
ungroup()
Expand All @@ -214,3 +186,27 @@ export_cdisc <- function(res_nca) {

return(list(pp = pp, adpp = adpp))
}

.pptestcd_dict <- setNames(
c(
"Total CL Obs by F", "Time of Last Nonzero Conc", "Max Conc", "Vz Obs by F", "AUC Infinity Obs",
"Last Nonzero Conc", "Time of CMAX", "R Squared", "R Squared Adjusted", "Max Conc Norm by Dose",
"AUC to Last Nonzero Conc Norm by Dose", "Lambda z", "AUC to Last Nonzero Conc",
"Half-Life Lambda z", "Number of points used for Lambda z", "Last Nonzero Conc Predicted",
"Span Ratio", "Lambda z lower limit (time)",

# Manually filled
"Trough Concentration", "Average Concentration", "AUC Infinity Predicted",
"AUMC Infinity Observed", "AUC Percent Extrapolated Observed",
"AUC Percent Extrapolated Predicted", "Clearance Observed",
"Clearance Predicted", "Mean Residence Time Intravenous Observed",
"Volume of Distribution Observed",
"Steady-State Volume of Distribution Intravenous Observed",
"AUC Infinity Observed Dose-Normalized", "Maximum Concentration Dose-Normalized"
),
c("CLFO", "TLST", "CMAX", "VZFO", "AUCIFO", "CLST", "TMAX", "R2", "R2ADJ", "CMAXD", "AUCLSTD",
"LAMZ", "AUCLST", "LAMZHL", "LAMZNPT", "CLSTP", "LAMZSPNR", "LAMZLL",
"CTROUGH", "CAV", "AUCIFP", "AUMCINF.OBS", "AUCPEO", "AUCPEP", "CL.OBS", "CL.PRED",
"MRT.IV.OBS", "VZ.OBS", "VSS.IV.OBS", "AUCINF.OBS.DN", "CMAX.DN"
)
)
2 changes: 0 additions & 2 deletions R/imports.R

This file was deleted.

73 changes: 44 additions & 29 deletions R/run_app.R
Original file line number Diff line number Diff line change
@@ -1,32 +1,47 @@
#' Run the Shiny app
#'
#' List of functions imported for the shiny application.
#' When adding new imports, please keep the alphabetical order, at lest for packages.
#'
#' @import shiny
#' @import bslib
#' @importFrom dplyr mutate filter select group_by summarise pull arrange ungroup
#' @importFrom dplyr rename_with across case_when left_join rename
#' @importFrom DT DTOutput renderDataTable datatable formatStyle styleEqual
#' @importFrom ggplot2 ggplot geom_errorbar geom_point geom_line labs aes facet_wrap
#' @importFrom htmlwidgets JS
#' @importFrom PKNCA PKNCAconc PKNCAdose PKNCAdata pk.nca PKNCA.options pknca_units_table
#' @importFrom plotly plotlyOutput renderPlotly plotly_build event_data
#' @importFrom reactable reactable reactableOutput renderReactable colDef reactableTheme
#' @importFrom reactable getReactableState
#' @importFrom reactable.extras text_extra dropdown_extra
#' @importFrom rio export_list
#' @importFrom rmarkdown render
#' @importFrom shinyBS bsModal
#' @importFrom shinycssloaders withSpinner
#' @importFrom shinyFiles shinyDirChoose
#' @importFrom shinyjqui orderInput updateOrderInput
#' @importFrom shinyWidgets dropdown pickerInput switchInput updatePickerInput
#' @importFrom stringi stri_rand_strings
#' @importFrom tools file_ext
#' @importFrom utils read.csv write.csv
#' @importFrom zip zipr
#' @param ... Arguments passed to `shiny::runApp()`
#' @export
run_app <- function() {
shiny::runApp(system.file("shiny", package = "aNCA"))
run_app <- function(...) {
require(aNCA)

require(bslib)
require(checkmate)
require(dplyr)
require(DT)
require(forcats)
require(ggh4x)
require(ggplot2)
require(glue)
require(haven)
require(htmlwidgets)
require(logger)
require(magrittr)
require(nestcolor)
require(PKNCA)
require(plotly)
require(purrr)
require(reactable)
require(reactable.extras)
require(rio)
require(rmarkdown)
require(scales)
require(shiny)
require(shinyBS)
require(shinycssloaders)
require(shinyFiles)
require(shinyjqui)
require(shinyjs)
require(shinyWidgets)
require(stats)
require(stringi)
require(stringr)
require(tern)
require(tidyr)
require(tools)
require(utils)
require(units)
require(rlang)
require(yaml)
require(zip)
shiny::runApp(system.file("shiny", package = "aNCA"), ...)
}
9 changes: 5 additions & 4 deletions R/utils-slope_selector.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#' @returns Original dataset, with `is.included.hl`, `is.excluded.hl` and `exclude_half.life`
#' columns modified in accordance to the provided slope filters.
#' @importFrom dplyr filter group_by mutate
#'
.filter_slopes <- function(data, slopes, profiles) {
#' @export
filter_slopes <- function(data, slopes, profiles) {
if (is.null(data) || is.null(data$conc) || is.null(data$conc$data))
stop("Please provide valid data.")

Expand All @@ -39,7 +39,7 @@
# Go over all rules and check if there is no overlap - if there is, edit accordingly
slopes <- purrr::reduce(
split(slopes, seq_len(nrow(slopes))),
.f = ~ .check_slope_rule_overlap(.x, .y, .keep = TRUE)
.f = ~ check_slope_rule_overlap(.x, .y, .keep = TRUE)
)
}

Expand Down Expand Up @@ -86,7 +86,8 @@
#' that the user wants to remove rule if new range already exists in the dataset.
#' If TRUE, in that case full range will be kept.
#' @returns Data frame with full ruleset, adjusted for new rules.
.check_slope_rule_overlap <- function(existing, new, .keep = FALSE) {
#' @export
check_slope_rule_overlap <- function(existing, new, .keep = FALSE) {
# check if any rule already exists for specific patient and profile #
existing_index <- which(
existing$TYPE == new$TYPE &
Expand Down
32 changes: 23 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,33 @@ This application enables users to upload their datasets and perform Non-Compartm
* **Save your analysis settings** and reupload them later to keep on analysing!

## Installation
To install the application, clone the repository and load it locally using the following commands in your terminal:
``` sh
git clone https://github.com/pharmaverse/aNCA.git # Clone the repository
### Via pak (recommended)
We recommend using [pak](https://github.com/r-lib/pak) for package installation, along with all system dependencies. If you do not have `pak` available, you will need to set it up first:
```R
install.packages("pak")
```
You can then run the application from the R console anytime. Just make sure first your working directory is set to the aNCA folder:
``` r
# install devtools if not present
if (!requireNamespace('devtools', quietly = TRUE)) install.packages('devtools')
devtools::load_all() # load all dependencies
aNCA::run_app() # run the application
then you can install [aNCA](.) by running:
```R
pak::pak("pharmaverse/aNCA")
```
in your R console.

### Via cloning the repository (for contributors)
Alternatively, you can set up the package by cloning the repository through your terminal/shell:
```bash
git clone https://github.com/pharmaverse/aNCA.git
```
and then loading it directly using [devtools](https://github.com/r-lib/devtools) in your IDE (e.g. RStudio) console:
```R
devtools::load_all()
```

## Quick start
To run the application, simply invoke:
```R
aNCA::run_app()
```

The testing data will be automatically loaded upon application startup. You can provide your own dataset in the **data** tab. Here you can also specify pre-processing filters.

In the **NCA** tab, start off by loading the pre-processed data using *Submit* button. You will also need to choose dose number in the *Settings*. Then, you will be able to run the NCA analysis. From there, you can also specify different analysis options, like applying flag rule sets and selecting slopes.
Expand Down
2 changes: 2 additions & 0 deletions inst/WORDLIST
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ cmax
codebase
csv
customizable
devtools
df
ggplot
ggplots
lastdose
nca
pak
pharmacokinetic
pkcg
pknca
Expand Down
Loading

0 comments on commit 5048ec0

Please sign in to comment.