From 43dffa90b9204b141938b837083481d4ed147504 Mon Sep 17 00:00:00 2001 From: Matthew Phelps Date: Mon, 18 Mar 2024 11:16:54 +0100 Subject: [PATCH 1/4] Feature/build_fixes (#4) * Add dummy function to import data.table for unit-tests. Probably a cleaner waer way to do this * Fix broken unit test in QA vignette * Update results data model vignette * Merge branch 'dev' into feature/build_fixes * Fix R CMD checks --- .Rbuildignore | 7 ++ .gitignore | 2 + DESCRIPTION | 18 ++- NAMESPACE | 2 +- R/dummy_fn.R | 9 ++ R/mk_adae.R | 15 --- man/dummy_fn.Rd | 14 +++ man/mk_adae_demo.Rd | 17 --- tests/testthat/_snaps/mild_ae_by_sex.md | 48 +++++--- tests/testthat/binary_type_2.R | 2 +- tests/testthat/test-binary_type_2.R | 1 - tests/testthat/test-demographics.R | 15 ++- tests/testthat/test-empty_strata_level.R | 2 +- tests/testthat/test-mild_ae_by_sex.R | 10 +- .../testthat/test-validate_aesev_aesoc_sex.R | 19 ++- vignettes/ep_spec_adam.Rmd | 111 ------------------ vignettes/ep_spec_adam_data.Rmd | 4 +- vignettes/example_ep_spec.Rmd | 15 ++- vignettes/methods_criteria.Rmd | 1 - vignettes/ramnog.Rmd | 28 ++--- vignettes/results_datamodel.Rmd | 10 +- vignettes/validation.Rmd | 36 ++++-- 22 files changed, 157 insertions(+), 229 deletions(-) create mode 100644 R/dummy_fn.R delete mode 100644 R/mk_adae.R create mode 100644 man/dummy_fn.Rd delete mode 100644 man/mk_adae_demo.Rd delete mode 100644 vignettes/ep_spec_adam.Rmd diff --git a/.Rbuildignore b/.Rbuildignore index 56888db..003509f 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,3 +1,10 @@ ^ramnog\.Rproj$ ^\.Rproj\.user$ ^LICENSE\.md$ +^README.Rmd +^_pkgdown.yml +^docs +^.vscode +^.github +^.githooks +^.pre-commit-config.yaml diff --git a/.gitignore b/.gitignore index 7670a95..268ae55 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .Rproj.user inst/doc docs/ +launch.json +.Rhistory diff --git a/DESCRIPTION b/DESCRIPTION index ce5970d..427d467 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -10,20 +10,26 @@ Description: What the package does (one paragraph). License: MIT + file LICENSE Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.0 +RoxygenNote: 7.3.1 Imports: + data.table (>= 1.14.2), +Suggests: chef, chefCriteria, chefStats, - data.table (>= 1.14.2), -Suggests: knitr, + targets, + usethis, rmarkdown, testthat (>= 3.0.0), - kableExtra (>= 1.4) + kableExtra (>= 1.4), + testr, + tidyr, + pharmaverseadam +Config/testthat/edition: 3 Remotes: + hta-pharma/chefStats, hta-pharma/chef, hta-pharma/chefCriteria, - hta-pharma/chefStats -Config/testthat/edition: 3 + matthew-phelps/testr VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index d01f28a..b9d5109 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,4 +1,4 @@ # Generated by roxygen2: do not edit by hand -export(mk_adae_demo) +export(dummy_fn) import(data.table) diff --git a/R/dummy_fn.R b/R/dummy_fn.R new file mode 100644 index 0000000..0756249 --- /dev/null +++ b/R/dummy_fn.R @@ -0,0 +1,9 @@ +#' Title +#' @description exists only to import data.table +#' @return Nothing. +#' @export +#' +#' @import data.table +dummy_fn <- function(){ + +} diff --git a/R/mk_adae.R b/R/mk_adae.R deleted file mode 100644 index 84c86f2..0000000 --- a/R/mk_adae.R +++ /dev/null @@ -1,15 +0,0 @@ -#' Demo function to make ADAE data for validation purposes -#' -#' @param study_metadata -#' -#' @return data.table -#' @export -#' @import data.table -mk_adae_demo <- function(study_metadata) { - adsl <- pharmaverseadam::adsl |> data.table::setDT() - adae <- pharmaverseadam::adae |> data.table::setDT() - adae_out <- - merge(adsl, adae[, c(setdiff(names(adae), names(adsl)), "USUBJID"), with = - F], by = "USUBJID", all = TRUE) - adae_out[TRT01A %in% c('Placebo', 'Xanomeline High Dose'), ] -} diff --git a/man/dummy_fn.Rd b/man/dummy_fn.Rd new file mode 100644 index 0000000..1c12ffb --- /dev/null +++ b/man/dummy_fn.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/dummy_fn.R +\name{dummy_fn} +\alias{dummy_fn} +\title{Title} +\usage{ +dummy_fn() +} +\value{ +Nothing. +} +\description{ +exists only to import data.table +} diff --git a/man/mk_adae_demo.Rd b/man/mk_adae_demo.Rd deleted file mode 100644 index 76a32f8..0000000 --- a/man/mk_adae_demo.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/mk_adae.R -\name{mk_adae_demo} -\alias{mk_adae_demo} -\title{Demo function to make ADAE data for validation purposes} -\usage{ -mk_adae_demo(study_metadata) -} -\arguments{ -\item{study_metadata}{} -} -\value{ -data.table -} -\description{ -Demo function to make ADAE data for validation purposes -} diff --git a/tests/testthat/_snaps/mild_ae_by_sex.md b/tests/testthat/_snaps/mild_ae_by_sex.md index f2257cd..5387ea3 100644 --- a/tests/testthat/_snaps/mild_ae_by_sex.md +++ b/tests/testthat/_snaps/mild_ae_by_sex.md @@ -1,13 +1,14 @@ # Complex pipeline runs without errors Code - ep_stat[, .(stat_filter, endpoint_group_filter, label, description, qualifiers, - value)] + ep_stat[, .(stat_filter, endpoint_group_filter, stat_result_label, + stat_result_description, stat_result_qualifiers, stat_result_value)] Output stat_filter + 1: TOTAL_ == "total" & TRT01A == "Placebo" - 2: TOTAL_ == "total" & TRT01A == "Xanomeline High Dose" - 3: TOTAL_ == "total" & TRT01A == "Placebo" + 2: TOTAL_ == "total" & TRT01A == "Placebo" + 3: TOTAL_ == "total" & TRT01A == "Xanomeline High Dose" 4: TOTAL_ == "total" & TRT01A == "Xanomeline High Dose" 5: SEX == "F" & TRT01A == "Placebo" --- @@ -17,6 +18,7 @@ 4277: 4278: endpoint_group_filter + 1: AESOC == "GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS" & AESEV == "MILD" 2: AESOC == "GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS" & AESEV == "MILD" 3: AESOC == "GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS" & AESEV == "MILD" @@ -28,16 +30,30 @@ 4276: AESOC == "EAR AND LABYRINTH DISORDERS" & AESEV == "SEVERE" 4277: AESOC == "NEOPLASMS BENIGN, MALIGNANT AND UNSPECIFIED (INCL CYSTS AND POLYPS)" & AESEV == "SEVERE" 4278: AESOC == "NEOPLASMS BENIGN, MALIGNANT AND UNSPECIFIED (INCL CYSTS AND POLYPS)" & AESEV == "SEVERE" - label description qualifiers value - 1: E Number of events 36 - 2: E Number of events 75 - 3: N Number of subjects 86 - 4: N Number of subjects 72 - 5: E Number of events 18 - --- - 4274: P-value interaction not conducted NA - 4275: P-value interaction not conducted NA - 4276: P-value interaction not conducted NA - 4277: P-value interaction not conducted NA - 4278: P-value interaction not conducted NA + stat_result_label stat_result_description + + 1: E Number of events + 2: N Number of subjects + 3: E Number of events + 4: N Number of subjects + 5: E Number of events + --- + 4274: P-value interaction not conducted + 4275: P-value interaction not conducted + 4276: P-value interaction not conducted + 4277: P-value interaction not conducted + 4278: P-value interaction not conducted + stat_result_qualifiers stat_result_value + + 1: 36 + 2: 86 + 3: 75 + 4: 72 + 5: 18 + --- + 4274: NA + 4275: NA + 4276: NA + 4277: NA + 4278: NA diff --git a/tests/testthat/binary_type_2.R b/tests/testthat/binary_type_2.R index 7ac42e7..750dbe6 100644 --- a/tests/testthat/binary_type_2.R +++ b/tests/testthat/binary_type_2.R @@ -23,7 +23,7 @@ test_that("Binary outcomes of type 2 work", { mk_adam_fn = list(mk_adae), ) # ACT --------------------------------------------------------------------- - browser() + targets::tar_make() targets::tar_load(ep_stat) diff --git a/tests/testthat/test-binary_type_2.R b/tests/testthat/test-binary_type_2.R index e340007..3f2dd53 100644 --- a/tests/testthat/test-binary_type_2.R +++ b/tests/testthat/test-binary_type_2.R @@ -27,6 +27,5 @@ test_that("multiplication works", { # ACT --------------------------------------------------------------------- targets::tar_make() targets::tar_load(ep_stat) - browser() }) diff --git a/tests/testthat/test-demographics.R b/tests/testthat/test-demographics.R index 8956a8d..6c73876 100644 --- a/tests/testthat/test-demographics.R +++ b/tests/testthat/test-demographics.R @@ -44,6 +44,7 @@ test_that("Demographics work with other endpoints", { mk_adam_fn = list(mk_adae, mk_advs), ) # ACT --------------------------------------------------------------------- + targets::tar_make() targets::tar_load(ep_stat) @@ -54,7 +55,7 @@ test_that("Demographics work with other endpoints", { actual <- ep_stat[endpoint_group_filter == "AESOC == \"SOCIAL CIRCUMSTANCES\" & AESEV == \"SEVERE\"" & fn_name == "RR" & - stat_filter == "SEX == \"F\""& label == "RR", value] + stat_filter == "SEX == \"F\"" & stat_result_label == "RR", "stat_result_value"] x1 <- x[SEX == "F" & SAFFL == "Y"] x1[AESOC == "SOCIAL CIRCUMSTANCES" & AESEV == "SEVERE", event := TRUE] @@ -65,12 +66,16 @@ test_that("Demographics work with other endpoints", { c <- 0.5 # No outcome, not exposed d <- 53.5 # No outcome, not exposed expected <- (a / sum(a, b)) / (c / sum(c, d)) - expect_identical(actual, expected) + expect_identical(actual$stat_result_value, expected) # Spot check the Demographic stats x <- mk_advs() + a <- + ep_stat[stat_result_qualifiers == "SEX" & + stat_result_label == "n_missing"] |> data.table::setorder(stat_filter) + expected <- x[is.na(SEX), .N, by = .(TRT01A)] |> data.table::setorder(TRT01A) - a <- ep_stat[qualifiers=="SEX"&label=="n_missing"] |> setorder(stat_filter) - expected <- x[is.na(SEX), .N, by=.(TRT01A)] |> setorder(TRT01A) - expect_equal(a$value, expected$N) + expect_equal(a$stat_result_value |> as.integer(), as.integer(expected$N)) }) + + diff --git a/tests/testthat/test-empty_strata_level.R b/tests/testthat/test-empty_strata_level.R index d0090b5..bd4768c 100644 --- a/tests/testthat/test-empty_strata_level.R +++ b/tests/testthat/test-empty_strata_level.R @@ -44,6 +44,6 @@ test_that("stat funtion that produces a 0 returns result ", actual <- - ep_stat[grepl("Placebo", stat_filter), value] + ep_stat[grepl("Placebo", stat_filter), stat_result_value] expect_equal(actual, 0) }) diff --git a/tests/testthat/test-mild_ae_by_sex.R b/tests/testthat/test-mild_ae_by_sex.R index 966373c..6732615 100644 --- a/tests/testthat/test-mild_ae_by_sex.R +++ b/tests/testthat/test-mild_ae_by_sex.R @@ -34,13 +34,13 @@ test_that("Complex pipeline runs without errors", targets::tar_make() # EXPECT ------------------------------------------------------------------ - x <- targets::tar_meta() %>% data.table::as.data.table() + x <- targets::tar_meta() |> data.table::as.data.table() targets::tar_load(ep_stat) expect_true(all(is.na(x$error))) expect_snapshot(ep_stat[, .(stat_filter, endpoint_group_filter, - label, - description, - qualifiers, - value)]) + stat_result_label, + stat_result_description, + stat_result_qualifiers, + stat_result_value)]) }) diff --git a/tests/testthat/test-validate_aesev_aesoc_sex.R b/tests/testthat/test-validate_aesev_aesoc_sex.R index 151c4da..d0b8d56 100644 --- a/tests/testthat/test-validate_aesev_aesoc_sex.R +++ b/tests/testthat/test-validate_aesev_aesoc_sex.R @@ -35,7 +35,6 @@ test_that("Validate statistics - complex endpoint specification", ) } - chef::use_chef( pipeline_dir = "pipeline", r_functions_dir = "R/", @@ -44,17 +43,17 @@ test_that("Validate statistics - complex endpoint specification", mk_adam_fn = list(mk_adae), mk_criteria_fn = list(crit_endpoint, crit_sga, crit_sgd) ) + # ACT --------------------------------------------------------------------- targets::tar_make() targets::tar_load(ep_stat) # EXPECT ------------------------------------------------------------------ - x <- mk_adae() actual <- ep_stat[endpoint_group_filter == "AESOC == \"SOCIAL CIRCUMSTANCES\" & AESEV == \"SEVERE\"" & fn_name == "RR" & - stat_filter == "SEX == \"F\"" &label == "RR", value] + stat_filter == "SEX == \"F\"" & stat_result_label == "RR", stat_result_value] x1 <- x[SEX == "F" & SAFFL == "Y"] x1[AESOC == "SOCIAL CIRCUMSTANCES" & AESEV == "SEVERE", event := TRUE] @@ -71,7 +70,7 @@ test_that("Validate statistics - complex endpoint specification", ep_stat[endpoint_group_filter == "AESOC == \"SOCIAL CIRCUMSTANCES\" & AESEV == \"SEVERE\"" & fn_name == "OR" & stat_filter == "SEX == \"F\"" & - label == "OR", value] + stat_result_label == "OR", stat_result_value] expected <- (a / b) / (c / d) expect_identical(actual, expected) }) @@ -114,7 +113,6 @@ test_that("Valide stats when one strata level is not found", ) } - chef::use_chef( pipeline_dir = "pipeline", r_functions_dir = "R/", @@ -123,6 +121,7 @@ test_that("Valide stats when one strata level is not found", mk_adam_fn = list(mk_adae), mk_criteria_fn = list(crit_endpoint, crit_sga, crit_sgd) ) + # ACT --------------------------------------------------------------------- targets::tar_make() targets::tar_load(ep_stat) @@ -133,7 +132,7 @@ test_that("Valide stats when one strata level is not found", ep_stat[endpoint_group_filter == "AESEV == \"SEVERE\"" & fn_name == "RR" & stat_filter == "SEX == \"F\"" & - label == "RR", value] + stat_result_label == "RR", stat_result_value] x1 <- x[SEX == "F" & SAFFL == "Y"] x1[, event := FALSE] x1[AESEV == "SEVERE", event := TRUE] |> setorder(-event) @@ -158,10 +157,10 @@ test_that("Valide stats when one strata level is not found", # Numeber of Events actual <- - ep_stat[endpoint_group_filter == "AESEV == \"SEVERE\"" & - fn_name == "E" & - strata_var == "SEX"] + ep_stat[ep_stat$endpoint_group_filter == "AESEV == \"SEVERE\"" & + ep_stat$fn_name == "E" & + ep_stat$strata_var == "SEX"] expected <- x1[(event), .N, by = .(TRT01A)][order(TRT01A)][, as.double(N)] - expect_identical(actual$value, expected) + expect_identical(actual$stat_result_value, expected) }) diff --git a/vignettes/ep_spec_adam.Rmd b/vignettes/ep_spec_adam.Rmd deleted file mode 100644 index 756fa52..0000000 --- a/vignettes/ep_spec_adam.Rmd +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: "ADaM Data" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{ADaM Data} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -``` - -# Overview - -Each endpoint needs to be generated from a single analysis data set containing information from one or more ADaM data sets. Each analysis data set is created by a custom ADaM function written by the trial programmer that is referenced in the endpoint specification via the `data_prepare` parameter. The ADaM function contains instructions to what ADaM data sets to join, how to join, and what custom variables e.g., new groupings, to create (if any). - -There are three requirements for the ADaM function: - -1. It must have exactly one input argument `study_metadata` which is an endpoint specification parameter, preferably a 1-element list, that contains any relevant information about the study that may be used to read the ADaM data sets. If no such information is needed, then leave `study_metadata` unused in the function and set it as an empty `list()` in the endpoint specification. -2. It must each return a `data.table` object. If you do not work in `data.table`, you can do this by converting your `tibble` or `data.frame` object to a `data.table` object at the end of the function via `data.table::as.data.table(my_data_frame)`. -3. The returned table must contain all the ADAM variables (and derived variables) that are mentioned in the endpoint specification and also the subject ID variable `USUBJID`. - -In summary, the analysis data set generation is controlled with the following two parameters in the endpoint specification: - -* **data_prepare**: Reference to a custom function that returns a single consolidated analysis table that contains all ADaM data needed in the endpoint. -* **study_metadata**: Object containing study specifics that are relevant for reading the ADAM data. Must be parsed as the input to the ADaM and ADSL functions. May be empty if not needed. - -# Examples - -##### Ex 1.1 - -Here is an example of an ADAM function that first reads the `ADSL` data table from {pharmaverseadam}, filters it down to two treatment arms, and enriches it with a derived variable. Then it merges the enriched ADSL with ADAE from {pharmaverseadam} and return a single table with all the ADaM information from `ADSL` and `ADAE`: - -```{r, eval = FALSE} -# Example of ADaM function that merges information from ADSL and ADAE -mk_adam_ex1_1 <- function(study_metadata) { - - # Read ADSL from {pharmaverseadam} - adsl <- data.table::as.data.table(pharmaverseadam::adsl) - - # Filter treatment arms - adsl <- adsl[adsl$TRT01A %in% c('Placebo', 'Xanomeline High Dose')] - - # New derived ADSL variable - adsl[, AGEGR2 := data.table::fcase(AGE < 70, "AGE < 70", - AGE >= 70, "AGE >= 70")] - - # Read ADAE from {pharmaverseadam} - adae <- data.table::as.data.table(pharmaverseadam::adae) - - # Merge ADSL and ADAE - adae_out <- - merge(adsl, adae[, c(setdiff(names(adae), names(adsl)), "USUBJID"), with = - F], by = "USUBJID", all = TRUE) - return(adae_out) -} -``` - -##### Ex 1.2 - -You might also have cases where information from several ADAM tables are required in your endpoint. Here is an example that returns the same ADaM information as the example above with the addition of the baseline body weight extracted from `ADVS`. So information from three ADaM tables are merged and returned in a single analysis data set: - -```{r, eval = FALSE} -# Example of ADaM function that merges information from three ADaM tables -mk_adam_ex1_2 <- function(study_metadata) { - - # Read ADSL from {pharmaverseadam} - adsl <- data.table::as.data.table(pharmaverseadam::adsl) - - # Filter treatment arms - adsl <- adsl[adsl$TRT01A %in% c('Placebo', 'Xanomeline High Dose')] - - # New derived ADSL variable - adsl[, AGEGR2 := data.table::fcase(AGE < 70, "AGE < 70", - AGE >= 70, "AGE >= 70")] - - # Read ADAE from {pharmaverseadam} - adae <- data.table::as.data.table(pharmaverseadam::adae) - - # Read ADVS from {pharmaverseadam} - advs <- data.table::as.data.table(pharmaverseadam::advs) - - # Identify baseline body weight - advs_bw <- advs[advs$PARAMCD == "WEIGHT" & advs$VISIT == "BASELINE"] - - # Create new variable bw_baseline - advs_bw[["bw_baseline"]] <- advs_bw[["AVAL"]] - - # Merge ADSL, ADAE and baseline body weight from ADVS - ax_out <- - merge(adsl, adae[, c(setdiff(names(adae), names(adsl)), "USUBJID"), with = F], - by = "USUBJID", all.x = TRUE) %>% - merge(., advs_bw[, c("bw_baseline", "USUBJID")], by = "USUBJID", all.x = TRUE) - - return(ax_out) -} -``` - -#### Ex 1.3 - -The ADaM functions, once defined, need to be linked to the corresponding endpoint specifications via the data_prepare parameter. The creation of each endpoint specification is facilitated by the mk_endpoint_str function wherein this data_prepare parameter is established. In the following example, the `mk_adam_ex1_2` function is utilized to produce the analysis data intended for an endpoint. -```{r, eval=FALSE} -# Example of endpoint specification of ADaM function. -# The dots must be replaced with other required parameters. -ep_spec_ex1_3 <- chef::mk_endpoint_str(data_prepare = mk_adam_ex1_2, - ...) -``` diff --git a/vignettes/ep_spec_adam_data.Rmd b/vignettes/ep_spec_adam_data.Rmd index 756fa52..c7b08cd 100644 --- a/vignettes/ep_spec_adam_data.Rmd +++ b/vignettes/ep_spec_adam_data.Rmd @@ -93,8 +93,8 @@ mk_adam_ex1_2 <- function(study_metadata) { # Merge ADSL, ADAE and baseline body weight from ADVS ax_out <- merge(adsl, adae[, c(setdiff(names(adae), names(adsl)), "USUBJID"), with = F], - by = "USUBJID", all.x = TRUE) %>% - merge(., advs_bw[, c("bw_baseline", "USUBJID")], by = "USUBJID", all.x = TRUE) + by = "USUBJID", all.x = TRUE) |> + merge(x=_, advs_bw[, c("bw_baseline", "USUBJID")], by = "USUBJID", all.x = TRUE) return(ax_out) } diff --git a/vignettes/example_ep_spec.Rmd b/vignettes/example_ep_spec.Rmd index 51e4876..26f49e1 100644 --- a/vignettes/example_ep_spec.Rmd +++ b/vignettes/example_ep_spec.Rmd @@ -1,12 +1,12 @@ --- -title: "Endpoint catalog" +title: "Endpoint Catalog" resource_files: - vignettes/figures output: rmarkdown::html_vignette: toc: false vignette: > - %\VignetteIndexEntry{Endpoint catalog} + %\VignetteIndexEntry{Endpoint Catalog} %\VignetteEncoding{UTF-8} %\VignetteEngine{knitr::rmarkdown} editor_options: @@ -15,7 +15,6 @@ editor_options: --- ```{r, include = FALSE} -library(magrittr) library(ramnog) library(testthat) library(data.table) @@ -407,13 +406,13 @@ mk_adlb <- function(study_metadata) { )] # Read ADLB - adlb <- data.table::as.data.table(pharmaverseadam::adlb) %>% - .[.[["PARAMCD"]] == "SODIUM" & - .[["AVISIT"]] %in% c("Baseline", "Week 8", "Week 16"), ] + adlb_0 <- data.table::as.data.table(pharmaverseadam::adlb) + adlb_1 <- adlb_0[adlb_0[["PARAMCD"]] == "SODIUM" & + adlb_0[["AVISIT"]] %in% c("Baseline", "Week 8", "Week 16"), ] adlb2 <- - merge(adlb, - adlb[adlb$AVISIT == "Baseline", c("USUBJID", "AVAL")], + merge(adlb_1, + adlb_1[adlb_1$AVISIT == "Baseline", c("USUBJID", "AVAL")], by = "USUBJID", all.x = TRUE ) diff --git a/vignettes/methods_criteria.Rmd b/vignettes/methods_criteria.Rmd index b05d21d..dd0269f 100644 --- a/vignettes/methods_criteria.Rmd +++ b/vignettes/methods_criteria.Rmd @@ -13,7 +13,6 @@ editor_options: --- ```{r, include = FALSE} -library(magrittr) knitr::opts_chunk$set( collapse = TRUE, comment = "#>" diff --git a/vignettes/ramnog.Rmd b/vignettes/ramnog.Rmd index 6d68636..8280616 100644 --- a/vignettes/ramnog.Rmd +++ b/vignettes/ramnog.Rmd @@ -1,8 +1,8 @@ --- -title: "Quick start" +title: "Quick Start" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{ramnog} + %\VignetteIndexEntry{Quick Start} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -139,14 +139,14 @@ Our goal for this analysis is to count the number of events experiencing an even Now that all the inputs are defined, we can run the pipeline. This is achieved by a call to `tar_make()` from the {targets} package. ```{r,eval=FALSE} -tar_make() +targets::tar_make() ``` Targets will show you which steps in the pipeline are executed and how long each step took: ```{r, echo=FALSE} setwd(tmp_dir) # Do not run, only needed to get the markdown file to run -tar_make() +targets::tar_make() ``` @@ -154,7 +154,7 @@ tar_make() Then, to see the results, you load the cached step of the pipeline corresponding to the results. In our case it will be `ep_stat`, so to load it into the sessions as an object we call ```{r, eval=FALSE} -tar_load(ep_stat) +targets::tar_load(ep_stat) ``` @@ -172,10 +172,10 @@ ep_stat[, .( treatment_refval, strata_var, stat_filter, - label, - description, - qualifiers, - value + stat_result_label, + stat_result_description, + stat_result_qualifiers, + stat_result_value )] |> head() ``` @@ -183,16 +183,16 @@ ep_stat[, .( ```{r, echo=FALSE} setwd(tmp_dir) # Do not run, only needed to get the markdown file to run -tar_load(ep_stat) +targets::tar_load(ep_stat) ep_stat[, .( treatment_var, treatment_refval, strata_var, stat_filter, - label, - description, - qualifiers, - value + stat_result_label, + stat_result_description, + stat_result_qualifiers, + stat_result_value )] |> head() ``` diff --git a/vignettes/results_datamodel.Rmd b/vignettes/results_datamodel.Rmd index 971203e..8f952cf 100644 --- a/vignettes/results_datamodel.Rmd +++ b/vignettes/results_datamodel.Rmd @@ -217,7 +217,7 @@ The table below describes all the columns in the output table. Note that informa Indices (rows) in the analysis data included in the stratum. - Level 6: Statistics + Level 6: Statistics `stat_result_description` char Description of the statistics (returned from statistical function). @@ -225,7 +225,12 @@ The table below describes all the columns in the output table. Note that informa `stat_result_label` char - Label to the statistical value (returned from statistical function). + Label to the statistics (returned from statistical function). + + + `stat_result_qualifiers` + char + Qualifiers to the statistics (returned from statistical function). `stat_result_value` @@ -234,3 +239,4 @@ The table below describes all the columns in the output table. Note that informa + diff --git a/vignettes/validation.Rmd b/vignettes/validation.Rmd index dd84668..faaebd3 100644 --- a/vignettes/validation.Rmd +++ b/vignettes/validation.Rmd @@ -1,8 +1,8 @@ --- -title: "Validation" +title: "Quality control for ramnog ecosystem" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Validation} + %\VignetteIndexEntry{Quality control for ramnog ecosystem} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -19,6 +19,7 @@ library(ramnog) library(testthat) library(data.table) library(chef) +library(testr) library(chefStats) ``` @@ -47,20 +48,27 @@ For example, below is the unit test to ensure the results of an endpoint definit Example of integration test using {testthat} framework ```{r} -test_that("Valide stats when one strata level is not found", +testthat::test_that("Valide stats when one strata level is not found", { # SETUP ------------------------------------------------------------------- testr::create_local_project() - + mk_adae <- function(study_metadata) { + adsl <- pharmaverseadam::adsl |> data.table::setDT() + adae <- pharmaverseadam::adae |> data.table::setDT() + adae_out <- + merge(adsl, adae[, c(setdiff(names(adae), names(adsl)), "USUBJID"), with = + F], by = "USUBJID", all = TRUE) + adae_out[TRT01A %in% c('Placebo', 'Xanomeline High Dose'),] + } mk_ep_def <- function() { - ep <- chef::mk_endpoint_str( + chef::mk_endpoint_str( study_metadata = list(), pop_var = "SAFFL", pop_value = "Y", treatment_var = "TRT01A", treatment_refval = "Xanomeline High Dose", stratify_by = list(c("SEX")), - data_prepare = ramnog::mk_adae_demo, + data_prepare = mk_adae, endpoint_label = "A", custom_pop_filter = "SEX == 'F'", group_by = list(list(AESEV = c())), @@ -75,28 +83,27 @@ test_that("Valide stats when one strata level is not found", ) } - chef::use_chef( pipeline_dir = "pipeline", r_functions_dir = "R/", pipeline_id = "01", mk_endpoint_def_fn = mk_ep_def, - mk_adam_fn = list(mk_adae_demo) + mk_adam_fn = list(mk_adae) ) # ACT --------------------------------------------------------------------- targets::tar_make() targets::tar_load(ep_stat) # EXPECT ------------------------------------------------------------------ - browser() - x <- mk_adae_demo() + # Manually calculated expected results + x <- mk_adae(study_metadata = NULL) # Relative Risk actual <- ep_stat[endpoint_group_filter == "AESEV == \"SEVERE\"" & fn_name == "RR" & - stat_filter == "SEX == \"F\"" & label == "RR", value] + stat_filter == "SEX == \"F\"" & stat_result_label == "RR", stat_result_value] x1 <- x[SEX == "F" & SAFFL == "Y"] x1[, event := FALSE] - x1[AESEV == "SEVERE", event := TRUE] |> setorder(-event) + x1[AESEV == "SEVERE", event := TRUE] |> data.table::setorder(-event) x1_unique <- unique(x1, by = "USUBJID", fromLast = FALSE) two_by_two <- @@ -132,7 +139,10 @@ test_that("Valide stats when one strata level is not found", strata_var == "SEX"] expected <- x1[(event), .N, by = .(TRT01A)][order(TRT01A)][, as.double(N)] - expect_identical(actual$value, expected) + expect_identical(actual$stat_result_value, expected) }) ``` + +## CI/CD +To be added From f36544c08f1f0b85a6b98b71cc5acae7ec0c8cf0 Mon Sep 17 00:00:00 2001 From: Matthew Phelps Date: Mon, 18 Mar 2024 15:00:46 +0100 Subject: [PATCH 2/4] Feature/depl_website (#5) * Try to get website deployed * Test if using usethis::use_pkgdown_github_pages() worked --- .Rbuildignore | 5 +++ .github/workflows/Release-package.yaml | 22 ++++++++++++ .github/workflows/pkgdown.yaml | 48 ++++++++++++++++++++++++++ .gitignore | 1 + DESCRIPTION | 1 + _pkgdown.yml | 28 ++++----------- 6 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/Release-package.yaml create mode 100644 .github/workflows/pkgdown.yaml diff --git a/.Rbuildignore b/.Rbuildignore index 003509f..7fa3ec9 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -8,3 +8,8 @@ ^.github ^.githooks ^.pre-commit-config.yaml +RELEASE_BODY\.txt +^\.github$ +^_pkgdown\.yml$ +^docs$ +^pkgdown$ diff --git a/.github/workflows/Release-package.yaml b/.github/workflows/Release-package.yaml new file mode 100644 index 0000000..260b16a --- /dev/null +++ b/.github/workflows/Release-package.yaml @@ -0,0 +1,22 @@ + on: + push: + branches: main + pull_request: + branches: main + workflow_dispatch: + + name: Release Package + + jobs: + build: + name: RMD Build and check + uses: ./.github/workflows/R-CMD-check.yaml + docs: + needs: build + name: Build and Deploy Docs + uses: ./.github/workflows/pkgdown.yaml + release: + needs: [build, docs] + name: Release + if: github.event_name != 'pull_request' + uses: ./.github/workflows/release.yaml \ No newline at end of file diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml new file mode 100644 index 0000000..a7276e8 --- /dev/null +++ b/.github/workflows/pkgdown.yaml @@ -0,0 +1,48 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + release: + types: [published] + workflow_dispatch: + +name: pkgdown + +jobs: + pkgdown: + runs-on: ubuntu-latest + # Only restrict concurrency for non-PR jobs + concurrency: + group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::pkgdown, local::. + needs: website + + - name: Build site + run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) + shell: Rscript {0} + + - name: Deploy to GitHub pages 🚀 + if: github.event_name != 'pull_request' + uses: JamesIves/github-pages-deploy-action@v4.5.0 + with: + clean: false + branch: gh-pages + folder: docs diff --git a/.gitignore b/.gitignore index 268ae55..3e202f3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ inst/doc docs/ launch.json .Rhistory +docs diff --git a/DESCRIPTION b/DESCRIPTION index 427d467..457cc89 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -33,3 +33,4 @@ Remotes: hta-pharma/chefCriteria, matthew-phelps/testr VignetteBuilder: knitr +URL: https://hta-pharma.github.io/ramnog/ diff --git a/_pkgdown.yml b/_pkgdown.yml index b9ad023..ef8c868 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -1,16 +1,10 @@ -url: ~ +url: https://hta-pharma.github.io/ramnog/ template: bootstrap: 5 - - - articles: - - title: Overview navbar: Overview - contents: - - ep_overview - + contents: ep_overview - title: Endpoint Population and Outcome Specification navbar: Endpoint Population and Outcome Specification contents: @@ -20,29 +14,21 @@ articles: - ep_spec_event_def - ep_spec_strata_def - ep_spec_label - - title: Endpoint Statistics navbar: Endpoint Statistics - contents: - - starts_with('methods_') - + contents: starts_with('methods_') - title: Endpoint Results navbar: Endpoint Results - contents: - - starts_with("results") - + contents: starts_with("results") - title: Endpoint Examples navbar: Endpoint Examples - contents: - - starts_with("example_") - + contents: starts_with("example_") - title: Debugging navbar: Debugging - contents: - - debugging - + contents: debugging - title: Development navbar: Development contents: - starts_with("dev") - validation + From 3e4118fa10cbe1e345f44099f80eb9c072ce1120 Mon Sep 17 00:00:00 2001 From: Matthew Phelps Date: Mon, 18 Mar 2024 15:30:34 +0100 Subject: [PATCH 3/4] Bug/fix_pages (#7) * Remove workflow that should not have been included * Updating pkgdown yaml to try and get it to publish --- .github/workflows/Release-package.yaml | 22 ---------------- .github/workflows/pkgdown.yaml | 36 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 22 deletions(-) delete mode 100644 .github/workflows/Release-package.yaml diff --git a/.github/workflows/Release-package.yaml b/.github/workflows/Release-package.yaml deleted file mode 100644 index 260b16a..0000000 --- a/.github/workflows/Release-package.yaml +++ /dev/null @@ -1,22 +0,0 @@ - on: - push: - branches: main - pull_request: - branches: main - workflow_dispatch: - - name: Release Package - - jobs: - build: - name: RMD Build and check - uses: ./.github/workflows/R-CMD-check.yaml - docs: - needs: build - name: Build and Deploy Docs - uses: ./.github/workflows/pkgdown.yaml - release: - needs: [build, docs] - name: Release - if: github.event_name != 'pull_request' - uses: ./.github/workflows/release.yaml \ No newline at end of file diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index a7276e8..8b951ee 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -39,6 +39,7 @@ jobs: run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) shell: Rscript {0} +# If not pull request a brand new webpage is deployed - name: Deploy to GitHub pages 🚀 if: github.event_name != 'pull_request' uses: JamesIves/github-pages-deploy-action@v4.5.0 @@ -46,3 +47,38 @@ jobs: clean: false branch: gh-pages folder: docs + + # If pull request the webpage is deployed inside a dev/"PR number" folder for review + + - name: Add pkgdown PR Comment + uses: marocchino/sticky-pull-request-comment@v2 + if: github.event_name == 'pull_request' + with: + recreate: true + header: pkgdown + message: | + # Github pages + Review the pkgdown webpage for the PR [here](https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/dev/${{ github.event.pull_request.number }}) + + - name: Copy page to temp folder + if: github.event_name == 'pull_request' + run: | + mkdir -p /home/runner/work/dev + cp -r ./docs/* /home/runner/work/dev + + - name: Check out gh-pages branch + if: github.event_name == 'pull_request' + uses: actions/checkout@v4 + with: + ref: gh-pages + + - name: Copy and push to gh-pages + if: github.event_name == 'pull_request' + run: | + mkdir -p dev/${{ github.event.pull_request.number }} + cp -r /home/runner/work/dev/* ./dev/${{ github.event.pull_request.number }} + git config --global user.email "actions-robot@novonordisk.com" + git config --global user.name "Actions Robot From Github Actions" + git add . + git commit -m "Update gh pages from the PR" + git push \ No newline at end of file From 9c7247e1d988f0090f27ca7c8d3466bb1c046bba Mon Sep 17 00:00:00 2001 From: Matthew Phelps Date: Mon, 18 Mar 2024 15:59:29 +0100 Subject: [PATCH 4/4] Trying to get github pages working --- .github/workflows/pkgdown.yaml | 37 +--------------------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 8b951ee..ac85d16 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -4,7 +4,7 @@ on: push: branches: [main, master] pull_request: - branches: [main, master] + branches: [main, master, dev] release: types: [published] workflow_dispatch: @@ -39,7 +39,6 @@ jobs: run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) shell: Rscript {0} -# If not pull request a brand new webpage is deployed - name: Deploy to GitHub pages 🚀 if: github.event_name != 'pull_request' uses: JamesIves/github-pages-deploy-action@v4.5.0 @@ -48,37 +47,3 @@ jobs: branch: gh-pages folder: docs - # If pull request the webpage is deployed inside a dev/"PR number" folder for review - - - name: Add pkgdown PR Comment - uses: marocchino/sticky-pull-request-comment@v2 - if: github.event_name == 'pull_request' - with: - recreate: true - header: pkgdown - message: | - # Github pages - Review the pkgdown webpage for the PR [here](https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/dev/${{ github.event.pull_request.number }}) - - - name: Copy page to temp folder - if: github.event_name == 'pull_request' - run: | - mkdir -p /home/runner/work/dev - cp -r ./docs/* /home/runner/work/dev - - - name: Check out gh-pages branch - if: github.event_name == 'pull_request' - uses: actions/checkout@v4 - with: - ref: gh-pages - - - name: Copy and push to gh-pages - if: github.event_name == 'pull_request' - run: | - mkdir -p dev/${{ github.event.pull_request.number }} - cp -r /home/runner/work/dev/* ./dev/${{ github.event.pull_request.number }} - git config --global user.email "actions-robot@novonordisk.com" - git config --global user.name "Actions Robot From Github Actions" - git add . - git commit -m "Update gh pages from the PR" - git push \ No newline at end of file