From 060314d641a018a0de78914659f1f40cb6f7851c Mon Sep 17 00:00:00 2001 From: osenan Date: Thu, 12 Mar 2026 12:14:19 +0100 Subject: [PATCH 01/27] feat: add S3 method dispatch for picks or teal transform variables --- DESCRIPTION | 7 +- NAMESPACE | 2 + R/tm_g_ae_oview.R | 52 ++++- R/tm_g_ae_oview_picks.R | 376 +++++++++++++++++++++++++++++++++++++ R/utils.R | 23 +++ man/dot-picks_datanames.Rd | 19 ++ man/tm_g_ae_oview.Rd | 105 ++++++++++- man/tm_g_events_term_id.Rd | 93 ++++++++- 8 files changed, 649 insertions(+), 28 deletions(-) create mode 100644 R/tm_g_ae_oview_picks.R create mode 100644 man/dot-picks_datanames.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 27648b22..1f53643c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -37,6 +37,7 @@ Imports: teal.code (>= 0.7.0), teal.data (>= 0.8.0), teal.logger (>= 0.4.0), + teal.picks (>= 0.1.0), teal.reporter (>= 0.6.0), teal.widgets (>= 0.5.0), tern (>= 0.9.7), @@ -50,9 +51,11 @@ Suggests: withr (>= 3.0.0) Remotes: insightsengineering/osprey + insightsengineering/teal.picks@redesign_exptraction@main Config/Needs/verdepcheck: insightsengineering/osprey, rstudio/shiny, - insightsengineering/teal, insightsengineering/teal.slice, - insightsengineering/teal.transform, mllg/checkmate, tidyverse/dplyr, + insightsengineering/teal, insightsengineering/teal.picks, + insightsengineering/teal.slice, insightsengineering/teal.transform, + mllg/checkmate, tidyverse/dplyr, insightsengineering/formatters, tidyverse/ggplot2, r-lib/lifecycle, daroczig/logger, rstudio/shinyvalidate, insightsengineering/teal.code, insightsengineering/teal.logger, insightsengineering/teal.reporter, diff --git a/NAMESPACE b/NAMESPACE index 9d07d672..08caa331 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,7 @@ # Generated by roxygen2: do not edit by hand +S3method(tm_g_ae_oview,default) +S3method(tm_g_ae_oview,picks) export(label_aevar) export(plot_decorate_output) export(quick_filter) diff --git a/R/tm_g_ae_oview.R b/R/tm_g_ae_oview.R index 67126e8d..feb822b9 100644 --- a/R/tm_g_ae_oview.R +++ b/R/tm_g_ae_oview.R @@ -1,21 +1,27 @@ -#' Teal module for the `AE` overview +#' @title Teal module for the `AE` overview #' #' @description #' #' Display the `AE` overview plot as a shiny module #' +#' This is an S3 generic that dispatches on the class of `flag_var_anl`: +#' - [choices_selected][teal.transform::choices_selected()] dispatches to the +#' default method. +#' - [picks][teal.picks::picks()] dispatches to the picks method. +#' #' @inheritParams teal.widgets::standard_layout #' @inheritParams teal::module #' @inheritParams argument_convention -#' @param flag_var_anl ([`teal.transform::choices_selected`]) -#' `choices_selected` object with variables used to count adverse event +#' @param flag_var_anl Either a ([`teal.transform::choices_selected`]) +#' `choices_selected` object or a (`[picks][teal.picks::picks()]`) +#' object with variables used to count adverse event #' sub-groups (e.g. Serious events, Related events, etc.) -#' +#' @param dataname (`character(1)`) Name of the events dataset. Required when +#' using the default method with [choices_selected][teal.transform::choices_selected()]. +#' Ignored by the `.picks` method. #' @inherit argument_convention return #' @inheritSection teal::example_module Reporting #' -#' @export -#' #' @examples #' data <- teal_data() %>% #' within({ @@ -47,7 +53,7 @@ #' join_keys(data) <- default_cdisc_join_keys[names(data)] #' #' ADAE <- data[["ADAE"]] -#' +#' # Using default method (choices selected) #' app <- init( #' data = data, #' modules = modules( @@ -73,14 +79,40 @@ #' shinyApp(app$ui, app$server) #' } #' +#' @export tm_g_ae_oview <- function(label, - dataname, - arm_var, - flag_var_anl, + dataname = NULL, + arm_var = teal.picks::picks( + teal.picks::datasets(), + teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ) + ), + flag_var_anl = teal.picks::picks( + teal.picks::datasets(), + teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ) + ), fontsize = c(5, 3, 7), plot_height = c(600L, 200L, 2000L), plot_width = NULL, transformators = list()) { + UseMethod("tm_g_ae_oview", flag_var_anl) +} + +#' @rdname tm_g_ae_oview +#' @export +tm_g_ae_oview.default <- function(label, + dataname, + arm_var, + flag_var_anl, + fontsize = c(5, 3, 7), + plot_height = c(600L, 200L, 2000L), + plot_width = NULL, + transformators = list()) { message("Initializing tm_g_ae_oview") checkmate::assert_class(arm_var, classes = "choices_selected") checkmate::assert_class(flag_var_anl, classes = "choices_selected") diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R new file mode 100644 index 00000000..7fe88f5d --- /dev/null +++ b/R/tm_g_ae_oview_picks.R @@ -0,0 +1,376 @@ +#' @rdname tm_g_ae_oview +#' @examples +#' data <- teal_data() %>% +#' within({ +#' library(dplyr) +#' ADSL <- rADSL +#' ADAE <- rADAE +#' .add_event_flags <- function(dat) { +#' dat <- dat %>% +#' mutate( +#' TMPFL_SER = AESER == "Y", +#' TMPFL_REL = AEREL == "Y", +#' TMPFL_GR5 = AETOXGR == "5", +#' AEREL1 = (AEREL == "Y" & ACTARM == "A: Drug X"), +#' AEREL2 = (AEREL == "Y" & ACTARM == "B: Placebo") +#' ) +#' labels <- c( +#' "Serious AE", "Related AE", "Grade 5 AE", +#' "AE related to A: Drug X", "AE related to B: Placebo" +#' ) +#' cols <- c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2") +#' for (i in seq_along(labels)) { +#' attr(dat[[cols[i]]], "label") <- labels[i] +#' } +#' dat +#' } +#' ADAE <- .add_event_flags(ADAE) +#' }) +#' join_keys(data) <- default_cdisc_join_keys[names(data)] +#' ADAE <- data[["ADAE"]] +#' # Using the picks method +#' app <- init( +#' data = data, +#' modules = modules( +#' tm_g_ae_oview( +#' label = "AE Overview", +#' arm_var = teal.picks::picks( +#' teal.picks::datasets("ADAE"), +#' teal.picks::variables( +#' choices = tidyselect::starts_with("ACTARM"), +#' selected = "ACTARMCD" +#' ) +#' ), +#' flag_var_anl = teal.picks::picks( +#' teal.picks::datasets("ADAE"), +#' teal.picks::variables( +#' choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), +#' selected = "AEREL1" +#' ) +#' ), +#' plot_height = c(600, 200, 2000) +#' ) +#' ) +#' ) +#' if (interactive()) { +#' shinyApp(app$ui, app$server) +#' } +#' @export +tm_g_ae_oview.picks <- function(label, # nolint: object_name_linter + dataname = NULL, + arm_var = teal.picks::picks( + teal.picks::datasets(), + teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ) + ), + flag_var_anl = teal.picks::picks( + teal.picks::datasets(), + teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ) + ), + fontsize = c(5, 3, 7), + plot_height = c(600L, 200L, 2000L), + plot_width = NULL, + transformators = list()) { + message("Initializing tm_g_ae_oview") + + checkmate::assert_class(arm_var, "picks") + if (isTRUE(attr(arm_var$variables, "multiple"))) { + warning( + "`arm_var` accepts only a single variable selection. ", + "Forcing `teal.picks::variables(multiple)` to FALSE." + ) + attr(arm_var$variables, "multiple") <- FALSE + } + + checkmate::assert_class(flag_var_anl, "picks") + if (isTRUE(attr(flag_var_anl$variables, "multiple"))) { + warning( + "`flag_var_anl` accepts only a single variable selection. ", + "Forcing `teal.picks::variables(multiple)` to FALSE." + ) + attr(flag_var_anl$variables, "multiple") <- FALSE + } + + checkmate::assert( + checkmate::check_number(fontsize, finite = TRUE), + checkmate::assert( + combine = "and", + .var.name = "fontsize", + checkmate::check_numeric(fontsize, len = 3, any.missing = FALSE, finite = TRUE), + checkmate::check_numeric(fontsize[1], lower = fontsize[2], upper = fontsize[3]) + ) + ) + checkmate::assert_numeric(plot_height, len = 3, any.missing = FALSE, finite = TRUE) + checkmate::assert_numeric(plot_height[1], + lower = plot_height[2], upper = plot_height[3], + .var.name = "plot_height" + ) + checkmate::assert_numeric(plot_width, len = 3, any.missing = FALSE, null.ok = TRUE, finite = TRUE) + checkmate::assert_numeric( + plot_width[1], + lower = plot_width[2], upper = plot_width[3], null.ok = TRUE, .var.name = "plot_width" + ) + + args <- as.list(environment()) + + module( + label = label, + server = srv_g_ae_oview.picks, + server_args = args[names(args) %in% names(formals(srv_g_ae_oview.picks))], + ui = ui_g_ae_oview.picks, + ui_args = args[names(args) %in% names(formals(ui_g_ae_oview.picks))], + transformators = transformators, + datanames = .picks_datanames(list(arm_var, flag_var_anl)) + ) +} + +ui_g_ae_oview.picks <- function( # nolint: object_name_linter + id, + label = "Common AE", + dataname = NULL, + arm_var = teal.picks::picks( + teal.picks::datasets(), + teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ) + ), + flag_var_anl = teal.picks::picks( + teal.picks::datasets(), + teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ) + ), + fontsize = c(5, 3, 7) +) { + + ns <- NS(id) + teal.widgets::standard_layout( + output = teal.widgets::white_small_well( + plot_decorate_output(id = ns(NULL)) + ), + encoding = tags$div( + tags$label("Encodings", class = "text-primary"), + tags$div( + tags$strong("Arm variable"), + teal.picks::picks_ui(id = ns("arm_var"), picks = arm_var) + ), + tags$div( + tags$strong("Flag variables"), + teal.picks::picks_ui(id = ns("flag_var_anl"), picks = flag_var_anl) + ), + selectInput( + ns("arm_ref"), + "Control", + choices = NULL + ), + selectInput( + ns("arm_trt"), + "Treatment", + choices = NULL + ), + teal.widgets::panel_item( + "Confidence interval settings", + teal.widgets::optionalSelectInput( + ns("diff_ci_method"), + "Method for Difference of Proportions CI", + choices = ci_choices, + selected = ci_choices[1], + multiple = FALSE + ), + teal.widgets::optionalSliderInput( + ns("conf_level"), + "Confidence Level", + min = 0.5, + max = 1, + value = 0.95 + ) + ), + teal.widgets::optionalSelectInput( + ns("axis"), + "Axis Side", + choices = c("Left" = "left", "Right" = "right"), + selected = "left", + multiple = FALSE + ), + ui_g_decorate( + ns(NULL), + fontsize = fontsize, + titles = "AE Overview", + footnotes = "" + ) + ) + ) +} + +srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter + data, + arm_var, + flag_var_anl, + plot_height, + plot_width) { + checkmate::assert_class(data, "reactive") + checkmate::assert_class(isolate(data()), "teal_data") + + moduleServer(id, function(input, output, session) { + # Initialize picks selectors + selectors <- teal.picks::picks_srv( + picks = list( + arm_var = arm_var, + flag_var_anl = flag_var_anl + ), + data = data + ) + + # Merge datasets based on picks selections + merged <- teal.picks::merge_srv( + "merge", + data = data, + selectors = selectors, + output_name = "ANL" + ) + + teal.logger::log_shiny_input_changes(input, namespace = "teal.osprey") + + decorate_output <- srv_g_decorate( + id = NULL, plt = plot_r, + plot_height = plot_height, plot_width = plot_width + ) + font_size <- decorate_output$font_size + pws <- decorate_output$pws + + observeEvent(list(input$diff_ci_method, input$conf_level), { + req(!is.null(input$diff_ci_method) && !is.null(input$conf_level)) + diff_ci_method <- input$diff_ci_method + conf_level <- input$conf_level + updateTextAreaInput(session, + "foot", + value = sprintf( + "Note: %d%% CI is calculated using %s", + round(conf_level * 100), + name_ci(diff_ci_method) + ) + ) + }) + + observeEvent(selectors$arm_var(), { + arm_var_name <- selectors$arm_var()$variables$selected + arm_dataset <- selectors$arm_var()$datasets$selected + req(arm_var_name, arm_dataset) + + arm_data <- data()[[arm_dataset]] + choices <- levels(arm_data[[arm_var_name]]) + + if (length(choices) == 1) { + trt_index <- 1 + } else { + trt_index <- 2 + } + + updateSelectInput( + session, + "arm_ref", + selected = choices[1], + choices = choices + ) + updateSelectInput( + session, + "arm_trt", + selected = choices[trt_index], + choices = choices + ) + }) + + output_q <- shiny::debounce( + millis = 200, + r = reactive({ + qenv <- merged$data() + + arm_var_name <- selectors$arm_var()$variables$selected + arm_dataset <- selectors$arm_var()$datasets$selected + + teal.reporter::teal_card(qenv) <- + c( + teal.reporter::teal_card(qenv), + teal.reporter::teal_card("## Module's output(s)") + ) + qenv <- teal.code::eval_code(qenv, "library(dplyr)") + + ANL <- qenv[["ANL"]] + + arm_var_name <- merged$variables()$arm_var + flag_var_name <- merged$variables()$flag_var_anl + + teal::validate_has_data( + ANL, + min_nrow = 10, + msg = "Analysis data set must have at least 10 data points" + ) + + # Original variable name and dataset for arm_N calculation on the source dataset + arm_var_orig <- selectors$arm_var()$variables$selected + arm_dataset <- selectors$arm_var()$datasets$selected + flag_dataset <- selectors$flag_var_anl()$datasets$selected + + shiny::validate( + shiny::need( + length(flag_var_name) > 0, + "A Flag Variable needs to be selected." + ), + shiny::need( + length(arm_var_name) > 0, + "An Arm Variable needs to be selected." + ) + ) + + + validate(need( + input$arm_trt %in% ANL[[arm_var_name]] && input$arm_ref %in% ANL[[arm_var_name]], + "Treatment or Control not found in Arm Variable. Perhaps they have been filtered out?" + )) + q1 <- qenv %>% + teal.code::eval_code( + code = as.expression(c( + bquote(anl_labels <- formatters::var_labels(ANL, fill = FALSE)), + bquote( + flags <- ANL %>% + select(all_of(.(flag_var_name))) %>% + rename_at(.(flag_var_name), function(x) paste0(x, ": ", anl_labels[x])) + ) + )) + ) + + teal.reporter::teal_card(q1) <- c(teal.reporter::teal_card(q1), "### Plot") + teal.code::eval_code( + q1, + code = as.expression(c( + bquote( + plot <- osprey::g_events_term_id( + term = flags, + id = ANL$USUBJID, + arm = ANL[[.(arm_var_name)]], + arm_N = table(ANL[[.(arm_var_name)]]), + ref = .(input$arm_ref), + trt = .(input$arm_trt), + diff_ci_method = .(input$diff_ci_method), + conf_level = .(input$conf_level), + axis_side = .(input$axis), + fontsize = .(font_size()), + draw = TRUE + ) + ) + )) + ) + }) + ) + + plot_r <- reactive(output_q()[["plot"]]) + set_chunk_dims(pws, output_q) + }) +} diff --git a/R/utils.R b/R/utils.R index 1dfcf628..15580d15 100644 --- a/R/utils.R +++ b/R/utils.R @@ -239,3 +239,26 @@ set_chunk_dims <- function(pws, q_r, inner_classes = NULL) { q }) } + +#' Extract datanames from a list of picks objects +#' +#' @param x (`list`) list of picks objects (or NULLs) +#' @return `character` vector of unique datanames, or `"all"` if any picks +#' object uses dynamic dataset choices. +#' @keywords internal +.picks_datanames <- function(x) { + checkmate::assert_list(x, c("picks", "NULL")) + datanames_list <- lapply(x, function(x) { + if (is.character(x$datasets$choices)) { + x$datasets$choices + } else { + NULL + } + }) + + if (any(vapply(datanames_list, is.null, logical(1)))) { + "all" + } else { + unique(unlist(datanames_list)) + } +} diff --git a/man/dot-picks_datanames.Rd b/man/dot-picks_datanames.Rd new file mode 100644 index 00000000..31074c46 --- /dev/null +++ b/man/dot-picks_datanames.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{.picks_datanames} +\alias{.picks_datanames} +\title{Extract datanames from a list of picks objects} +\usage{ +.picks_datanames(x) +} +\arguments{ +\item{x}{(\code{list}) list of picks objects (or NULLs)} +} +\value{ +\code{character} vector of unique datanames, or \code{"all"} if any picks +object uses dynamic dataset choices. +} +\description{ +Extract datanames from a list of picks objects +} +\keyword{internal} diff --git a/man/tm_g_ae_oview.Rd b/man/tm_g_ae_oview.Rd index 375f1212..ef1f4935 100644 --- a/man/tm_g_ae_oview.Rd +++ b/man/tm_g_ae_oview.Rd @@ -1,10 +1,25 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tm_g_ae_oview.R +% Please edit documentation in R/tm_g_ae_oview.R, R/tm_g_ae_oview_picks.R \name{tm_g_ae_oview} \alias{tm_g_ae_oview} +\alias{tm_g_ae_oview.default} +\alias{tm_g_ae_oview.picks} \title{Teal module for the \code{AE} overview} \usage{ tm_g_ae_oview( + label, + dataname = NULL, + arm_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = + teal.picks::is_categorical(min.len = 2), selected = 1L)), + flag_var_anl = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices + = teal.picks::is_categorical(min.len = 2), selected = 1L)), + fontsize = c(5, 3, 7), + plot_height = c(600L, 200L, 2000L), + plot_width = NULL, + transformators = list() +) + +\method{tm_g_ae_oview}{default}( label, dataname, arm_var, @@ -14,22 +29,36 @@ tm_g_ae_oview( plot_width = NULL, transformators = list() ) + +\method{tm_g_ae_oview}{picks}( + label, + dataname = NULL, + arm_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = + teal.picks::is_categorical(min.len = 2), selected = 1L)), + flag_var_anl = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices + = teal.picks::is_categorical(min.len = 2), selected = 1L)), + fontsize = c(5, 3, 7), + plot_height = c(600L, 200L, 2000L), + plot_width = NULL, + transformators = list() +) } \arguments{ \item{label}{(\code{character(1)}) Label shown in the navigation item for the module or module group. For \code{modules()} defaults to \code{"root"}. See \code{Details}.} -\item{dataname}{(\code{character(1)})\cr -analysis data used in the teal module, needs to be -available in the list passed to the \code{data} argument of \code{\link[teal:init]{teal::init()}}.} +\item{dataname}{(\code{character(1)}) Name of the events dataset. Required when +using the default method with \link[teal.transform:choices_selected]{choices_selected}. +Ignored by the \code{.picks} method.} \item{arm_var}{(\code{choices_selected})\cr object with all available choices and the pre-selected option for variable names that can be used as \code{arm_var}. See \code{\link[teal.transform:choices_selected]{teal.transform::choices_selected()}} for details. Column \code{arm_var} in the \code{dataname} has to be a factor.} -\item{flag_var_anl}{(\code{\link[teal.transform:choices_selected]{teal.transform::choices_selected}}) -\code{choices_selected} object with variables used to count adverse event +\item{flag_var_anl}{Either a (\code{\link[teal.transform:choices_selected]{teal.transform::choices_selected}}) +\code{choices_selected} object or a (\verb{[picks][teal.picks::picks()]}) +object with variables used to count adverse event sub-groups (e.g. Serious events, Related events, etc.)} \item{fontsize}{(\code{numeric(1)} or \code{numeric(3)})\cr @@ -51,6 +80,13 @@ the \code{\link[teal:teal_modules]{teal::module()}} object. } \description{ Display the \code{AE} overview plot as a shiny module + +This is an S3 generic that dispatches on the class of \code{flag_var_anl}: +\itemize{ +\item \link[teal.transform:choices_selected]{choices_selected} dispatches to the +default method. +\item \link[teal.picks:picks]{picks} dispatches to the picks method. +} } \section{Reporting}{ @@ -99,7 +135,7 @@ data <- teal_data() \%>\% join_keys(data) <- default_cdisc_join_keys[names(data)] ADAE <- data[["ADAE"]] - +# Using default method (choices selected) app <- init( data = data, modules = modules( @@ -125,4 +161,59 @@ if (interactive()) { shinyApp(app$ui, app$server) } +data <- teal_data() \%>\% + within({ + library(dplyr) + ADSL <- rADSL + ADAE <- rADAE + .add_event_flags <- function(dat) { + dat <- dat \%>\% + mutate( + TMPFL_SER = AESER == "Y", + TMPFL_REL = AEREL == "Y", + TMPFL_GR5 = AETOXGR == "5", + AEREL1 = (AEREL == "Y" & ACTARM == "A: Drug X"), + AEREL2 = (AEREL == "Y" & ACTARM == "B: Placebo") + ) + labels <- c( + "Serious AE", "Related AE", "Grade 5 AE", + "AE related to A: Drug X", "AE related to B: Placebo" + ) + cols <- c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2") + for (i in seq_along(labels)) { + attr(dat[[cols[i]]], "label") <- labels[i] + } + dat + } + ADAE <- .add_event_flags(ADAE) + }) + join_keys(data) <- default_cdisc_join_keys[names(data)] + ADAE <- data[["ADAE"]] + # Using the picks method + app <- init( + data = data, + modules = modules( + tm_g_ae_oview( + label = "AE Overview", + arm_var = teal.picks::picks( + teal.picks::datasets("ADAE"), + teal.picks::variables( + choices = tidyselect::starts_with("ACTARM"), + selected = "ACTARMCD" + ) + ), + flag_var_anl = teal.picks::picks( + teal.picks::datasets("ADAE"), + teal.picks::variables( + choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), + selected = "AEREL1" + ) + ), + plot_height = c(600, 200, 2000) + ) + ) + ) +if (interactive()) { + shinyApp(app$ui, app$server) +} } diff --git a/man/tm_g_events_term_id.Rd b/man/tm_g_events_term_id.Rd index f7745d13..cab5ee5d 100644 --- a/man/tm_g_events_term_id.Rd +++ b/man/tm_g_events_term_id.Rd @@ -1,12 +1,28 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tm_g_events_term_id.R +% Please edit documentation in R/tm_g_events_term_id.R, +% R/tm_g_events_term_id_picks.R \name{tm_g_events_term_id} \alias{tm_g_events_term_id} +\alias{tm_g_events_term_id.default} +\alias{tm_g_events_term_id.picks} \title{Events by Term Plot Teal Module} \usage{ tm_g_events_term_id( - label, - dataname, + label = "Common AE", + dataname = NULL, + term_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = + teal.picks::is_categorical(min.len = 2), selected = 1L)), + arm_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = + teal.picks::is_categorical(min.len = 2), selected = 1L)), + fontsize = c(5, 3, 7), + plot_height = c(600L, 200L, 2000L), + plot_width = NULL, + transformators = list() +) + +\method{tm_g_events_term_id}{default}( + label = "Common AE", + dataname = NULL, term_var, arm_var, fontsize = c(5, 3, 7), @@ -14,17 +30,32 @@ tm_g_events_term_id( plot_width = NULL, transformators = list() ) + +\method{tm_g_events_term_id}{picks}( + label = "Common AE", + dataname = NULL, + term_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = + teal.picks::is_categorical(min.len = 2), selected = 1L)), + arm_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = + teal.picks::is_categorical(min.len = 2), selected = 1L)), + fontsize = c(5, 3, 7), + plot_height = c(600L, 200L, 2000L), + plot_width = NULL, + transformators = list() +) } \arguments{ \item{label}{(\code{character(1)}) Label shown in the navigation item for the module or module group. For \code{modules()} defaults to \code{"root"}. See \code{Details}.} -\item{dataname}{(\code{character(1)})\cr -analysis data used in the teal module, needs to be -available in the list passed to the \code{data} argument of \code{\link[teal:init]{teal::init()}}.} +\item{dataname}{(\code{character(1)}) Name of the events dataset. Required when +using the default method with \link[teal.transform:choices_selected]{choices_selected}. +Ignored by the \code{.picks} method.} -\item{term_var}{\link[teal.transform:choices_selected]{teal.transform::choices_selected} object with all available choices -and pre-selected option names that can be used to specify the term for events} +\item{term_var}{A variable selection object. Either a +\code{\link[teal.transform:choices_selected]{teal.transform::choices_selected()}} object (dispatches to the \code{.default} +method) or a \code{\link[teal.picks:picks]{teal.picks::picks()}} object (dispatches to the \code{.picks} +method).} \item{arm_var}{(\code{choices_selected})\cr object with all available choices and the pre-selected option for variable @@ -49,7 +80,14 @@ To learn more check \code{vignette("transform-input-data", package = "teal")}.} the \code{\link[teal:teal_modules]{teal::module()}} object. } \description{ -Display Events by Term plot as a shiny module +Display Events by Term plot as a shiny module. + +This is an S3 generic that dispatches on the class of \code{term_var}: +\itemize{ +\item \link[teal.transform:choices_selected]{choices_selected} dispatches to the +default method. +\item \link[teal.picks:picks]{picks} dispatches to the picks method. +} } \section{Reporting}{ @@ -76,6 +114,7 @@ data <- teal_data() \%>\% join_keys(data) <- default_cdisc_join_keys[names(data)] +# Using the default method (choices_selected) app <- init( data = data, modules = modules( @@ -101,6 +140,42 @@ if (interactive()) { shinyApp(app$ui, app$server) } +# Using the picks method +data <- teal_data() \%>\% + within({ + ADSL <- rADSL + ADAE <- rADAE + }) + +join_keys(data) <- default_cdisc_join_keys[names(data)] + +app <- init( + data = data, + modules = modules( + tm_g_events_term_id( + label = "Common AE", + term_var = teal.picks::picks( + teal.picks::datasets("ADAE"), + teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = "AEDECOD" + ) + ), + arm_var = teal.picks::picks( + teal.picks::datasets("ADSL"), + teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = "ACTARMCD" + ) + ), + plot_height = c(600, 200, 2000) + ) + ) +) +if (interactive()) { + shinyApp(app$ui, app$server) +} + } \author{ Liming Li (lil128) \email{liming.li@roche.com} From 975ae0a4d9b3cdd87619c6a0dd743f5b79914825 Mon Sep 17 00:00:00 2001 From: osenan Date: Thu, 12 Mar 2026 12:24:14 +0100 Subject: [PATCH 02/27] tests: add test for tm_g_ae_oview module --- tests/testthat/test-tm_g_ae_oview.R | 73 +++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/testthat/test-tm_g_ae_oview.R diff --git a/tests/testthat/test-tm_g_ae_oview.R b/tests/testthat/test-tm_g_ae_oview.R new file mode 100644 index 00000000..cca1b623 --- /dev/null +++ b/tests/testthat/test-tm_g_ae_oview.R @@ -0,0 +1,73 @@ +arm_var_cs <- teal.transform::choices_selected( + selected = "ACTARM", + choices = c("ACTARM", "ACTARMCD") +) + +flag_var_cs <- teal.transform::choices_selected( + selected = "TMPFL_SER", + choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5") +) + +arm_var_picks <- teal.picks::picks( + teal.picks::datasets("ADAE"), + teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ) +) + +flag_var_picks <- teal.picks::picks( + teal.picks::datasets("ADAE"), + teal.picks::variables( + choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5"), + selected = "TMPFL_SER" + ) +) + +testthat::describe("tm_g_ae_oview argument verification", { + testthat::it("fails when arm_var is picks but flag_var_anl is choices_selected", { + testthat::expect_error( + tm_g_ae_oview( + label = "AE Overview", + arm_var = arm_var_picks, + flag_var_anl = flag_var_cs + ), + class = "error" + ) + }) + + testthat::it("fails when arm_var is choices_selected but flag_var_anl is picks", { + testthat::expect_error( + tm_g_ae_oview( + label = "AE Overview", + dataname = "ADAE", + arm_var = arm_var_cs, + flag_var_anl = flag_var_picks + ), + class = "error" + ) + }) +}) + +testthat::describe("tm_g_ae_oview module creation", { + testthat::it("creates a teal module using choices_selected (default method)", { + mod <- tm_g_ae_oview( + label = "AE Overview", + dataname = "ADAE", + arm_var = arm_var_cs, + flag_var_anl = flag_var_cs, + plot_height = c(600, 200, 2000) + ) + testthat::expect_s3_class(mod, "teal_module") + }) + + testthat::it("creates a teal module using picks (.picks method)", { + mod <- tm_g_ae_oview( + label = "AE Overview", + arm_var = arm_var_picks, + flag_var_anl = flag_var_picks, + plot_height = c(600, 200, 2000) + ) + testthat::expect_s3_class(mod, "teal_module") + }) +}) From b6fd8f60e71d507ce934df11a771406fe7f134ad Mon Sep 17 00:00:00 2001 From: osenan Date: Thu, 12 Mar 2026 12:25:54 +0100 Subject: [PATCH 03/27] chore: fix spelling --- R/utils.R | 2 +- inst/WORDLIST | 1 + man/dot-picks_datanames.Rd | 2 +- man/tm_g_events_term_id.Rd | 93 ++++---------------------------------- 4 files changed, 12 insertions(+), 86 deletions(-) diff --git a/R/utils.R b/R/utils.R index 15580d15..f71de8ef 100644 --- a/R/utils.R +++ b/R/utils.R @@ -242,7 +242,7 @@ set_chunk_dims <- function(pws, q_r, inner_classes = NULL) { #' Extract datanames from a list of picks objects #' -#' @param x (`list`) list of picks objects (or NULLs) +#' @param x (`list`) list of picks objects (or NULL objects) #' @return `character` vector of unique datanames, or `"all"` if any picks #' object uses dynamic dataset choices. #' @keywords internal diff --git a/inst/WORDLIST b/inst/WORDLIST index 21a72e78..a8ba8c59 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -8,6 +8,7 @@ UI Xuefeng chot ci +datanames dichotomization funder houx diff --git a/man/dot-picks_datanames.Rd b/man/dot-picks_datanames.Rd index 31074c46..998d6852 100644 --- a/man/dot-picks_datanames.Rd +++ b/man/dot-picks_datanames.Rd @@ -7,7 +7,7 @@ .picks_datanames(x) } \arguments{ -\item{x}{(\code{list}) list of picks objects (or NULLs)} +\item{x}{(\code{list}) list of picks objects (or NULL objects)} } \value{ \code{character} vector of unique datanames, or \code{"all"} if any picks diff --git a/man/tm_g_events_term_id.Rd b/man/tm_g_events_term_id.Rd index cab5ee5d..f7745d13 100644 --- a/man/tm_g_events_term_id.Rd +++ b/man/tm_g_events_term_id.Rd @@ -1,28 +1,12 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tm_g_events_term_id.R, -% R/tm_g_events_term_id_picks.R +% Please edit documentation in R/tm_g_events_term_id.R \name{tm_g_events_term_id} \alias{tm_g_events_term_id} -\alias{tm_g_events_term_id.default} -\alias{tm_g_events_term_id.picks} \title{Events by Term Plot Teal Module} \usage{ tm_g_events_term_id( - label = "Common AE", - dataname = NULL, - term_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = - teal.picks::is_categorical(min.len = 2), selected = 1L)), - arm_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = - teal.picks::is_categorical(min.len = 2), selected = 1L)), - fontsize = c(5, 3, 7), - plot_height = c(600L, 200L, 2000L), - plot_width = NULL, - transformators = list() -) - -\method{tm_g_events_term_id}{default}( - label = "Common AE", - dataname = NULL, + label, + dataname, term_var, arm_var, fontsize = c(5, 3, 7), @@ -30,32 +14,17 @@ tm_g_events_term_id( plot_width = NULL, transformators = list() ) - -\method{tm_g_events_term_id}{picks}( - label = "Common AE", - dataname = NULL, - term_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = - teal.picks::is_categorical(min.len = 2), selected = 1L)), - arm_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = - teal.picks::is_categorical(min.len = 2), selected = 1L)), - fontsize = c(5, 3, 7), - plot_height = c(600L, 200L, 2000L), - plot_width = NULL, - transformators = list() -) } \arguments{ \item{label}{(\code{character(1)}) Label shown in the navigation item for the module or module group. For \code{modules()} defaults to \code{"root"}. See \code{Details}.} -\item{dataname}{(\code{character(1)}) Name of the events dataset. Required when -using the default method with \link[teal.transform:choices_selected]{choices_selected}. -Ignored by the \code{.picks} method.} +\item{dataname}{(\code{character(1)})\cr +analysis data used in the teal module, needs to be +available in the list passed to the \code{data} argument of \code{\link[teal:init]{teal::init()}}.} -\item{term_var}{A variable selection object. Either a -\code{\link[teal.transform:choices_selected]{teal.transform::choices_selected()}} object (dispatches to the \code{.default} -method) or a \code{\link[teal.picks:picks]{teal.picks::picks()}} object (dispatches to the \code{.picks} -method).} +\item{term_var}{\link[teal.transform:choices_selected]{teal.transform::choices_selected} object with all available choices +and pre-selected option names that can be used to specify the term for events} \item{arm_var}{(\code{choices_selected})\cr object with all available choices and the pre-selected option for variable @@ -80,14 +49,7 @@ To learn more check \code{vignette("transform-input-data", package = "teal")}.} the \code{\link[teal:teal_modules]{teal::module()}} object. } \description{ -Display Events by Term plot as a shiny module. - -This is an S3 generic that dispatches on the class of \code{term_var}: -\itemize{ -\item \link[teal.transform:choices_selected]{choices_selected} dispatches to the -default method. -\item \link[teal.picks:picks]{picks} dispatches to the picks method. -} +Display Events by Term plot as a shiny module } \section{Reporting}{ @@ -114,7 +76,6 @@ data <- teal_data() \%>\% join_keys(data) <- default_cdisc_join_keys[names(data)] -# Using the default method (choices_selected) app <- init( data = data, modules = modules( @@ -140,42 +101,6 @@ if (interactive()) { shinyApp(app$ui, app$server) } -# Using the picks method -data <- teal_data() \%>\% - within({ - ADSL <- rADSL - ADAE <- rADAE - }) - -join_keys(data) <- default_cdisc_join_keys[names(data)] - -app <- init( - data = data, - modules = modules( - tm_g_events_term_id( - label = "Common AE", - term_var = teal.picks::picks( - teal.picks::datasets("ADAE"), - teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = "AEDECOD" - ) - ), - arm_var = teal.picks::picks( - teal.picks::datasets("ADSL"), - teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = "ACTARMCD" - ) - ), - plot_height = c(600, 200, 2000) - ) - ) -) -if (interactive()) { - shinyApp(app$ui, app$server) -} - } \author{ Liming Li (lil128) \email{liming.li@roche.com} From d68f94a10973ebca26efa4c71b241365af64ef37 Mon Sep 17 00:00:00 2001 From: osenan Date: Thu, 12 Mar 2026 12:30:05 +0100 Subject: [PATCH 04/27] chore: fix sign credentials From 3dd972e93ced5b4d95365efd22fd912e7ea5a779 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 11:39:31 +0000 Subject: [PATCH 05/27] [skip style] [skip vbump] Restyle files --- R/tm_g_ae_oview_picks.R | 78 ++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 7fe88f5d..5a128cc2 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -14,44 +14,44 @@ #' AEREL1 = (AEREL == "Y" & ACTARM == "A: Drug X"), #' AEREL2 = (AEREL == "Y" & ACTARM == "B: Placebo") #' ) -#' labels <- c( -#' "Serious AE", "Related AE", "Grade 5 AE", -#' "AE related to A: Drug X", "AE related to B: Placebo" -#' ) -#' cols <- c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2") -#' for (i in seq_along(labels)) { -#' attr(dat[[cols[i]]], "label") <- labels[i] -#' } -#' dat +#' labels <- c( +#' "Serious AE", "Related AE", "Grade 5 AE", +#' "AE related to A: Drug X", "AE related to B: Placebo" +#' ) +#' cols <- c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2") +#' for (i in seq_along(labels)) { +#' attr(dat[[cols[i]]], "label") <- labels[i] #' } -#' ADAE <- .add_event_flags(ADAE) -#' }) -#' join_keys(data) <- default_cdisc_join_keys[names(data)] -#' ADAE <- data[["ADAE"]] -#' # Using the picks method -#' app <- init( -#' data = data, -#' modules = modules( -#' tm_g_ae_oview( -#' label = "AE Overview", -#' arm_var = teal.picks::picks( -#' teal.picks::datasets("ADAE"), -#' teal.picks::variables( -#' choices = tidyselect::starts_with("ACTARM"), -#' selected = "ACTARMCD" -#' ) -#' ), -#' flag_var_anl = teal.picks::picks( -#' teal.picks::datasets("ADAE"), -#' teal.picks::variables( -#' choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), -#' selected = "AEREL1" -#' ) -#' ), -#' plot_height = c(600, 200, 2000) -#' ) -#' ) -#' ) +#' dat +#' } +#' ADAE <- .add_event_flags(ADAE) +#' }) +#' join_keys(data) <- default_cdisc_join_keys[names(data)] +#' ADAE <- data[["ADAE"]] +#' # Using the picks method +#' app <- init( +#' data = data, +#' modules = modules( +#' tm_g_ae_oview( +#' label = "AE Overview", +#' arm_var = teal.picks::picks( +#' teal.picks::datasets("ADAE"), +#' teal.picks::variables( +#' choices = tidyselect::starts_with("ACTARM"), +#' selected = "ACTARMCD" +#' ) +#' ), +#' flag_var_anl = teal.picks::picks( +#' teal.picks::datasets("ADAE"), +#' teal.picks::variables( +#' choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), +#' selected = "AEREL1" +#' ) +#' ), +#' plot_height = c(600, 200, 2000) +#' ) +#' ) +#' ) #' if (interactive()) { #' shinyApp(app$ui, app$server) #' } @@ -129,7 +129,8 @@ tm_g_ae_oview.picks <- function(label, # nolint: object_name_linter ) } -ui_g_ae_oview.picks <- function( # nolint: object_name_linter +ui_g_ae_oview.picks <- function( + # nolint: object_name_linter id, label = "Common AE", dataname = NULL, @@ -149,7 +150,6 @@ ui_g_ae_oview.picks <- function( # nolint: object_name_linter ), fontsize = c(5, 3, 7) ) { - ns <- NS(id) teal.widgets::standard_layout( output = teal.widgets::white_small_well( From 89ecbea80ba7fb1da16cf5ccdd42fe2d69b7fc33 Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Mon, 16 Mar 2026 12:31:37 +0100 Subject: [PATCH 06/27] Update DESCRIPTION MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> Signed-off-by: Oriol Senan <35930244+osenan@users.noreply.github.com> --- DESCRIPTION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 1f53643c..c4155c03 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -50,8 +50,8 @@ Suggests: testthat (>= 3.2.3), withr (>= 3.0.0) Remotes: - insightsengineering/osprey - insightsengineering/teal.picks@redesign_exptraction@main +insightsengineering/osprey, + insightsengineering/teal.picks@redesign_extraction@main Config/Needs/verdepcheck: insightsengineering/osprey, rstudio/shiny, insightsengineering/teal, insightsengineering/teal.picks, insightsengineering/teal.slice, insightsengineering/teal.transform, From 630f5bf30cabf3d408d4259b5e64d41fc76579c6 Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Mon, 16 Mar 2026 12:39:52 +0100 Subject: [PATCH 07/27] Update R/tm_g_ae_oview_picks.R MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> Signed-off-by: Oriol Senan <35930244+osenan@users.noreply.github.com> --- R/tm_g_ae_oview_picks.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 5a128cc2..edc2a9b5 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -209,7 +209,7 @@ ui_g_ae_oview.picks <- function( ) } -srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter +srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter. data, arm_var, flag_var_anl, From 2869ce9704fe5bba22d191fabb4e614426af2ac0 Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Mon, 16 Mar 2026 12:40:48 +0100 Subject: [PATCH 08/27] Update R/tm_g_ae_oview_picks.R MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> Signed-off-by: Oriol Senan <35930244+osenan@users.noreply.github.com> --- R/tm_g_ae_oview_picks.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index edc2a9b5..9de3098e 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -56,7 +56,7 @@ #' shinyApp(app$ui, app$server) #' } #' @export -tm_g_ae_oview.picks <- function(label, # nolint: object_name_linter +tm_g_ae_oview.picks <- function(label, # nolint: object_name_linter. dataname = NULL, arm_var = teal.picks::picks( teal.picks::datasets(), From c2f07a3ca6d90e4aefd4ce97c1a99e60c0f1cdb7 Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Mon, 16 Mar 2026 12:41:17 +0100 Subject: [PATCH 09/27] Update R/tm_g_ae_oview_picks.R MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> Signed-off-by: Oriol Senan <35930244+osenan@users.noreply.github.com> --- R/tm_g_ae_oview_picks.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 9de3098e..1dab6a70 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -129,8 +129,7 @@ tm_g_ae_oview.picks <- function(label, # nolint: object_name_linter. ) } -ui_g_ae_oview.picks <- function( - # nolint: object_name_linter +ui_g_ae_oview.picks <- function(# nolint: object_name_linter. id, label = "Common AE", dataname = NULL, From bf70fff61ac4036d414e6319f51732a21fe278d4 Mon Sep 17 00:00:00 2001 From: osenan Date: Mon, 16 Mar 2026 12:34:54 +0100 Subject: [PATCH 10/27] chore: update docs after fix style --- man/tm_g_ae_oview.Rd | 74 ++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/man/tm_g_ae_oview.Rd b/man/tm_g_ae_oview.Rd index ef1f4935..af5bc379 100644 --- a/man/tm_g_ae_oview.Rd +++ b/man/tm_g_ae_oview.Rd @@ -175,44 +175,44 @@ data <- teal_data() \%>\% AEREL1 = (AEREL == "Y" & ACTARM == "A: Drug X"), AEREL2 = (AEREL == "Y" & ACTARM == "B: Placebo") ) - labels <- c( - "Serious AE", "Related AE", "Grade 5 AE", - "AE related to A: Drug X", "AE related to B: Placebo" - ) - cols <- c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2") - for (i in seq_along(labels)) { - attr(dat[[cols[i]]], "label") <- labels[i] - } - dat + labels <- c( + "Serious AE", "Related AE", "Grade 5 AE", + "AE related to A: Drug X", "AE related to B: Placebo" + ) + cols <- c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2") + for (i in seq_along(labels)) { + attr(dat[[cols[i]]], "label") <- labels[i] } - ADAE <- .add_event_flags(ADAE) - }) - join_keys(data) <- default_cdisc_join_keys[names(data)] - ADAE <- data[["ADAE"]] - # Using the picks method - app <- init( - data = data, - modules = modules( - tm_g_ae_oview( - label = "AE Overview", - arm_var = teal.picks::picks( - teal.picks::datasets("ADAE"), - teal.picks::variables( - choices = tidyselect::starts_with("ACTARM"), - selected = "ACTARMCD" - ) - ), - flag_var_anl = teal.picks::picks( - teal.picks::datasets("ADAE"), - teal.picks::variables( - choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), - selected = "AEREL1" - ) - ), - plot_height = c(600, 200, 2000) - ) - ) - ) + dat + } + ADAE <- .add_event_flags(ADAE) + }) +join_keys(data) <- default_cdisc_join_keys[names(data)] +ADAE <- data[["ADAE"]] +# Using the picks method +app <- init( + data = data, + modules = modules( + tm_g_ae_oview( + label = "AE Overview", + arm_var = teal.picks::picks( + teal.picks::datasets("ADAE"), + teal.picks::variables( + choices = tidyselect::starts_with("ACTARM"), + selected = "ACTARMCD" + ) + ), + flag_var_anl = teal.picks::picks( + teal.picks::datasets("ADAE"), + teal.picks::variables( + choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), + selected = "AEREL1" + ) + ), + plot_height = c(600, 200, 2000) + ) + ) +) if (interactive()) { shinyApp(app$ui, app$server) } From 88fbf7e51688456485372a33433dca011019533b Mon Sep 17 00:00:00 2001 From: osenan Date: Mon, 16 Mar 2026 13:23:52 +0100 Subject: [PATCH 11/27] chore: fix typo in description --- DESCRIPTION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index c4155c03..014a968f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -50,8 +50,8 @@ Suggests: testthat (>= 3.2.3), withr (>= 3.0.0) Remotes: -insightsengineering/osprey, - insightsengineering/teal.picks@redesign_extraction@main + insightsengineering/osprey, + insightsengineering/teal.picks Config/Needs/verdepcheck: insightsengineering/osprey, rstudio/shiny, insightsengineering/teal, insightsengineering/teal.picks, insightsengineering/teal.slice, insightsengineering/teal.transform, From 8bd9bd3364fe73b526413b59dfa146cd974b42ad Mon Sep 17 00:00:00 2001 From: osenan Date: Mon, 16 Mar 2026 13:33:33 +0100 Subject: [PATCH 12/27] refactor: change defaults on ae_oview generic and use dataname directly --- R/tm_g_ae_oview.R | 26 +++++++------------------- R/tm_g_ae_oview_picks.R | 4 ++-- R/utils.R | 23 ----------------------- man/dot-picks_datanames.Rd | 19 ------------------- man/tm_g_ae_oview.Rd | 18 ++++++++---------- tests/testthat/test-tm_g_ae_oview.R | 1 + 6 files changed, 18 insertions(+), 73 deletions(-) delete mode 100644 man/dot-picks_datanames.Rd diff --git a/R/tm_g_ae_oview.R b/R/tm_g_ae_oview.R index feb822b9..4c32e6e9 100644 --- a/R/tm_g_ae_oview.R +++ b/R/tm_g_ae_oview.R @@ -81,25 +81,13 @@ #' #' @export tm_g_ae_oview <- function(label, - dataname = NULL, - arm_var = teal.picks::picks( - teal.picks::datasets(), - teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = 1L - ) - ), - flag_var_anl = teal.picks::picks( - teal.picks::datasets(), - teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = 1L - ) - ), - fontsize = c(5, 3, 7), - plot_height = c(600L, 200L, 2000L), - plot_width = NULL, - transformators = list()) { + dataname, + arm_var, + flag_var_anl, + fontsize, + plot_height, + plot_width, + transformators) { UseMethod("tm_g_ae_oview", flag_var_anl) } diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 1dab6a70..042699ff 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -57,7 +57,7 @@ #' } #' @export tm_g_ae_oview.picks <- function(label, # nolint: object_name_linter. - dataname = NULL, + dataname, arm_var = teal.picks::picks( teal.picks::datasets(), teal.picks::variables( @@ -125,7 +125,7 @@ tm_g_ae_oview.picks <- function(label, # nolint: object_name_linter. ui = ui_g_ae_oview.picks, ui_args = args[names(args) %in% names(formals(ui_g_ae_oview.picks))], transformators = transformators, - datanames = .picks_datanames(list(arm_var, flag_var_anl)) + datanames = c("ADSL", dataname) ) } diff --git a/R/utils.R b/R/utils.R index f71de8ef..1dfcf628 100644 --- a/R/utils.R +++ b/R/utils.R @@ -239,26 +239,3 @@ set_chunk_dims <- function(pws, q_r, inner_classes = NULL) { q }) } - -#' Extract datanames from a list of picks objects -#' -#' @param x (`list`) list of picks objects (or NULL objects) -#' @return `character` vector of unique datanames, or `"all"` if any picks -#' object uses dynamic dataset choices. -#' @keywords internal -.picks_datanames <- function(x) { - checkmate::assert_list(x, c("picks", "NULL")) - datanames_list <- lapply(x, function(x) { - if (is.character(x$datasets$choices)) { - x$datasets$choices - } else { - NULL - } - }) - - if (any(vapply(datanames_list, is.null, logical(1)))) { - "all" - } else { - unique(unlist(datanames_list)) - } -} diff --git a/man/dot-picks_datanames.Rd b/man/dot-picks_datanames.Rd deleted file mode 100644 index 998d6852..00000000 --- a/man/dot-picks_datanames.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{.picks_datanames} -\alias{.picks_datanames} -\title{Extract datanames from a list of picks objects} -\usage{ -.picks_datanames(x) -} -\arguments{ -\item{x}{(\code{list}) list of picks objects (or NULL objects)} -} -\value{ -\code{character} vector of unique datanames, or \code{"all"} if any picks -object uses dynamic dataset choices. -} -\description{ -Extract datanames from a list of picks objects -} -\keyword{internal} diff --git a/man/tm_g_ae_oview.Rd b/man/tm_g_ae_oview.Rd index af5bc379..3247afcd 100644 --- a/man/tm_g_ae_oview.Rd +++ b/man/tm_g_ae_oview.Rd @@ -8,15 +8,13 @@ \usage{ tm_g_ae_oview( label, - dataname = NULL, - arm_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = - teal.picks::is_categorical(min.len = 2), selected = 1L)), - flag_var_anl = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices - = teal.picks::is_categorical(min.len = 2), selected = 1L)), - fontsize = c(5, 3, 7), - plot_height = c(600L, 200L, 2000L), - plot_width = NULL, - transformators = list() + dataname, + arm_var, + flag_var_anl, + fontsize, + plot_height, + plot_width, + transformators ) \method{tm_g_ae_oview}{default}( @@ -32,7 +30,7 @@ tm_g_ae_oview( \method{tm_g_ae_oview}{picks}( label, - dataname = NULL, + dataname, arm_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = teal.picks::is_categorical(min.len = 2), selected = 1L)), flag_var_anl = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices diff --git a/tests/testthat/test-tm_g_ae_oview.R b/tests/testthat/test-tm_g_ae_oview.R index cca1b623..fd83f94d 100644 --- a/tests/testthat/test-tm_g_ae_oview.R +++ b/tests/testthat/test-tm_g_ae_oview.R @@ -64,6 +64,7 @@ testthat::describe("tm_g_ae_oview module creation", { testthat::it("creates a teal module using picks (.picks method)", { mod <- tm_g_ae_oview( label = "AE Overview", + dataname = "ADAE", arm_var = arm_var_picks, flag_var_anl = flag_var_picks, plot_height = c(600, 200, 2000) From 584c88bffcbe816eab7cb08510870d2728279175 Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 17 Mar 2026 07:33:46 +0100 Subject: [PATCH 13/27] refactor: add only necessary arguments to the UI --- NAMESPACE | 2 +- R/tm_g_ae_oview.R | 2 +- R/tm_g_ae_oview_picks.R | 69 ++++++++++++++--------------------------- man/tm_g_ae_oview.Rd | 24 ++++++-------- 4 files changed, 34 insertions(+), 63 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 08caa331..c2bc0c88 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,7 +1,7 @@ # Generated by roxygen2: do not edit by hand S3method(tm_g_ae_oview,default) -S3method(tm_g_ae_oview,picks) +S3method(tm_g_ae_oview,pick) export(label_aevar) export(plot_decorate_output) export(quick_filter) diff --git a/R/tm_g_ae_oview.R b/R/tm_g_ae_oview.R index 4c32e6e9..17690729 100644 --- a/R/tm_g_ae_oview.R +++ b/R/tm_g_ae_oview.R @@ -13,7 +13,7 @@ #' @inheritParams teal::module #' @inheritParams argument_convention #' @param flag_var_anl Either a ([`teal.transform::choices_selected`]) -#' `choices_selected` object or a (`[picks][teal.picks::picks()]`) +#' `choices_selected` object or a (`[teal.picks::variables()]`) #' object with variables used to count adverse event #' sub-groups (e.g. Serious events, Related events, etc.) #' @param dataname (`character(1)`) Name of the events dataset. Required when diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 042699ff..c4851ab9 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -34,19 +34,13 @@ #' modules = modules( #' tm_g_ae_oview( #' label = "AE Overview", -#' arm_var = teal.picks::picks( -#' teal.picks::datasets("ADAE"), -#' teal.picks::variables( +#' arm_var = teal.picks::variables( #' choices = tidyselect::starts_with("ACTARM"), #' selected = "ACTARMCD" -#' ) #' ), -#' flag_var_anl = teal.picks::picks( -#' teal.picks::datasets("ADAE"), -#' teal.picks::variables( +#' flag_var_anl = teal.picks::variables( #' choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), #' selected = "AEREL1" -#' ) #' ), #' plot_height = c(600, 200, 2000) #' ) @@ -56,28 +50,25 @@ #' shinyApp(app$ui, app$server) #' } #' @export -tm_g_ae_oview.picks <- function(label, # nolint: object_name_linter. - dataname, - arm_var = teal.picks::picks( - teal.picks::datasets(), - teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = 1L - ) - ), - flag_var_anl = teal.picks::picks( - teal.picks::datasets(), - teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = 1L - ) - ), - fontsize = c(5, 3, 7), - plot_height = c(600L, 200L, 2000L), - plot_width = NULL, - transformators = list()) { +tm_g_ae_oview.pick <- function(label, # nolint: object_name_linter. + dataname, + arm_var = teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ), + flag_var_anl = teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ), + fontsize = c(5, 3, 7), + plot_height = c(600L, 200L, 2000L), + plot_width = NULL, + transformators = list()) { message("Initializing tm_g_ae_oview") + arm_var <- teal.picks::picks(teal.picks::datasets(dataname), arm_var) + flag_var_anl <- teal.picks::picks(teal.picks::datasets(dataname), flag_var_anl) + checkmate::assert_class(arm_var, "picks") if (isTRUE(attr(arm_var$variables, "multiple"))) { warning( @@ -131,25 +122,12 @@ tm_g_ae_oview.picks <- function(label, # nolint: object_name_linter. ui_g_ae_oview.picks <- function(# nolint: object_name_linter. id, - label = "Common AE", - dataname = NULL, - arm_var = teal.picks::picks( - teal.picks::datasets(), - teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = 1L - ) - ), - flag_var_anl = teal.picks::picks( - teal.picks::datasets(), - teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = 1L - ) - ), - fontsize = c(5, 3, 7) + arm_var, + flag_var_anl, + fontsize ) { ns <- NS(id) + teal.widgets::standard_layout( output = teal.widgets::white_small_well( plot_decorate_output(id = ns(NULL)) @@ -315,7 +293,6 @@ srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter. # Original variable name and dataset for arm_N calculation on the source dataset arm_var_orig <- selectors$arm_var()$variables$selected arm_dataset <- selectors$arm_var()$datasets$selected - flag_dataset <- selectors$flag_var_anl()$datasets$selected shiny::validate( shiny::need( diff --git a/man/tm_g_ae_oview.Rd b/man/tm_g_ae_oview.Rd index 3247afcd..fcf913b2 100644 --- a/man/tm_g_ae_oview.Rd +++ b/man/tm_g_ae_oview.Rd @@ -3,7 +3,7 @@ \name{tm_g_ae_oview} \alias{tm_g_ae_oview} \alias{tm_g_ae_oview.default} -\alias{tm_g_ae_oview.picks} +\alias{tm_g_ae_oview.pick} \title{Teal module for the \code{AE} overview} \usage{ tm_g_ae_oview( @@ -28,13 +28,13 @@ tm_g_ae_oview( transformators = list() ) -\method{tm_g_ae_oview}{picks}( +\method{tm_g_ae_oview}{pick}( label, dataname, - arm_var = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices = - teal.picks::is_categorical(min.len = 2), selected = 1L)), - flag_var_anl = teal.picks::picks(teal.picks::datasets(), teal.picks::variables(choices - = teal.picks::is_categorical(min.len = 2), selected = 1L)), + arm_var = teal.picks::variables(choices = teal.picks::is_categorical(min.len = 2), + selected = 1L), + flag_var_anl = teal.picks::variables(choices = teal.picks::is_categorical(min.len = 2), + selected = 1L), fontsize = c(5, 3, 7), plot_height = c(600L, 200L, 2000L), plot_width = NULL, @@ -55,7 +55,7 @@ names that can be used as \code{arm_var}. See \code{\link[teal.transform:choices details. Column \code{arm_var} in the \code{dataname} has to be a factor.} \item{flag_var_anl}{Either a (\code{\link[teal.transform:choices_selected]{teal.transform::choices_selected}}) -\code{choices_selected} object or a (\verb{[picks][teal.picks::picks()]}) +\code{choices_selected} object or a (\verb{[teal.picks::variables()]}) object with variables used to count adverse event sub-groups (e.g. Serious events, Related events, etc.)} @@ -193,19 +193,13 @@ app <- init( modules = modules( tm_g_ae_oview( label = "AE Overview", - arm_var = teal.picks::picks( - teal.picks::datasets("ADAE"), - teal.picks::variables( + arm_var = teal.picks::variables( choices = tidyselect::starts_with("ACTARM"), selected = "ACTARMCD" - ) ), - flag_var_anl = teal.picks::picks( - teal.picks::datasets("ADAE"), - teal.picks::variables( + flag_var_anl = teal.picks::variables( choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), selected = "AEREL1" - ) ), plot_height = c(600, 200, 2000) ) From b3f3eb0e130a98c078f66afa58914e5f45023743 Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 17 Mar 2026 07:40:00 +0100 Subject: [PATCH 14/27] fix: update test after refactor on method --- tests/testthat/test-tm_g_ae_oview.R | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/tests/testthat/test-tm_g_ae_oview.R b/tests/testthat/test-tm_g_ae_oview.R index fd83f94d..7fa08f72 100644 --- a/tests/testthat/test-tm_g_ae_oview.R +++ b/tests/testthat/test-tm_g_ae_oview.R @@ -8,24 +8,18 @@ flag_var_cs <- teal.transform::choices_selected( choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5") ) -arm_var_picks <- teal.picks::picks( - teal.picks::datasets("ADAE"), - teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = 1L - ) +arm_var_picks <- teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L ) -flag_var_picks <- teal.picks::picks( - teal.picks::datasets("ADAE"), - teal.picks::variables( - choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5"), - selected = "TMPFL_SER" - ) +flag_var_picks <- teal.picks::variables( + choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5"), + selected = "TMPFL_SER" ) testthat::describe("tm_g_ae_oview argument verification", { - testthat::it("fails when arm_var is picks but flag_var_anl is choices_selected", { + testthat::it("fails when arm_var is pick but flag_var_anl is choices_selected", { testthat::expect_error( tm_g_ae_oview( label = "AE Overview", @@ -36,7 +30,7 @@ testthat::describe("tm_g_ae_oview argument verification", { ) }) - testthat::it("fails when arm_var is choices_selected but flag_var_anl is picks", { + testthat::it("fails when arm_var is choices_selected but flag_var_anl is pick", { testthat::expect_error( tm_g_ae_oview( label = "AE Overview", @@ -61,7 +55,7 @@ testthat::describe("tm_g_ae_oview module creation", { testthat::expect_s3_class(mod, "teal_module") }) - testthat::it("creates a teal module using picks (.picks method)", { + testthat::it("creates a teal module using picks (.pick method)", { mod <- tm_g_ae_oview( label = "AE Overview", dataname = "ADAE", From e00faeedae942428b36f7e26427a6df8bdffc9eb Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 06:46:56 +0000 Subject: [PATCH 15/27] [skip style] [skip vbump] Restyle files --- R/tm_g_ae_oview_picks.R | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index c4851ab9..650bc5a0 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -35,12 +35,12 @@ #' tm_g_ae_oview( #' label = "AE Overview", #' arm_var = teal.picks::variables( -#' choices = tidyselect::starts_with("ACTARM"), -#' selected = "ACTARMCD" +#' choices = tidyselect::starts_with("ACTARM"), +#' selected = "ACTARMCD" #' ), #' flag_var_anl = teal.picks::variables( -#' choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), -#' selected = "AEREL1" +#' choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), +#' selected = "AEREL1" #' ), #' plot_height = c(600, 200, 2000) #' ) @@ -120,7 +120,8 @@ tm_g_ae_oview.pick <- function(label, # nolint: object_name_linter. ) } -ui_g_ae_oview.picks <- function(# nolint: object_name_linter. +ui_g_ae_oview.picks <- function( + # nolint: object_name_linter. id, arm_var, flag_var_anl, From 440b9feeb950270adca2f57ef7fc0a1136bd5973 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 06:50:36 +0000 Subject: [PATCH 16/27] [skip roxygen] [skip vbump] Roxygen Man Pages Auto Update --- man/tm_g_ae_oview.Rd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/man/tm_g_ae_oview.Rd b/man/tm_g_ae_oview.Rd index fcf913b2..e6a2ee30 100644 --- a/man/tm_g_ae_oview.Rd +++ b/man/tm_g_ae_oview.Rd @@ -194,12 +194,12 @@ app <- init( tm_g_ae_oview( label = "AE Overview", arm_var = teal.picks::variables( - choices = tidyselect::starts_with("ACTARM"), - selected = "ACTARMCD" + choices = tidyselect::starts_with("ACTARM"), + selected = "ACTARMCD" ), flag_var_anl = teal.picks::variables( - choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), - selected = "AEREL1" + choices = c("TMPFL_SER", "TMPFL_REL", "TMPFL_GR5", "AEREL1", "AEREL2"), + selected = "AEREL1" ), plot_height = c(600, 200, 2000) ) From 5abc2ca5b1c9ec9ba74140db33d6b43e47ff83c8 Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 17 Mar 2026 11:12:35 +0100 Subject: [PATCH 17/27] chore: fix linters and examples --- R/tm_g_ae_oview.R | 10 +++++----- R/tm_g_ae_oview_picks.R | 14 +++++++------- man/tm_g_ae_oview.Rd | 9 +++++---- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/R/tm_g_ae_oview.R b/R/tm_g_ae_oview.R index 17690729..36569e95 100644 --- a/R/tm_g_ae_oview.R +++ b/R/tm_g_ae_oview.R @@ -23,13 +23,13 @@ #' @inheritSection teal::example_module Reporting #' #' @examples -#' data <- teal_data() %>% +#' data <- teal_data() |> #' within({ #' library(dplyr) #' ADSL <- rADSL #' ADAE <- rADAE #' .add_event_flags <- function(dat) { -#' dat <- dat %>% +#' dat <- dat |> #' mutate( #' TMPFL_SER = AESER == "Y", #' TMPFL_REL = AEREL == "Y", @@ -315,13 +315,13 @@ srv_g_ae_oview <- function(id, "Treatment or Control not found in Arm Variable. Perhaps they have been filtered out?" )) - q1 <- obj %>% + q1 <- obj |> teal.code::eval_code( code = as.expression(c( bquote(anl_labels <- formatters::var_labels(.(as.name(dataname)), fill = FALSE)), bquote( - flags <- .(as.name(dataname)) %>% - select(all_of(.(input$flag_var_anl))) %>% + flags <- .(as.name(dataname)) |> + select(all_of(.(input$flag_var_anl))) |> rename_at(vars(.(input$flag_var_anl)), function(x) paste0(x, ": ", anl_labels[x])) ) )) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 650bc5a0..93acce9c 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -1,12 +1,12 @@ #' @rdname tm_g_ae_oview #' @examples -#' data <- teal_data() %>% +#' data <- teal_data() |> #' within({ #' library(dplyr) #' ADSL <- rADSL #' ADAE <- rADAE #' .add_event_flags <- function(dat) { -#' dat <- dat %>% +#' dat <- dat |> #' mutate( #' TMPFL_SER = AESER == "Y", #' TMPFL_REL = AEREL == "Y", @@ -34,6 +34,7 @@ #' modules = modules( #' tm_g_ae_oview( #' label = "AE Overview", +#' dataname = "ADAE", #' arm_var = teal.picks::variables( #' choices = tidyselect::starts_with("ACTARM"), #' selected = "ACTARMCD" @@ -120,8 +121,7 @@ tm_g_ae_oview.pick <- function(label, # nolint: object_name_linter. ) } -ui_g_ae_oview.picks <- function( - # nolint: object_name_linter. +ui_g_ae_oview.picks <- function( # nolint: object_name_linter. id, arm_var, flag_var_anl, @@ -311,13 +311,13 @@ srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter. input$arm_trt %in% ANL[[arm_var_name]] && input$arm_ref %in% ANL[[arm_var_name]], "Treatment or Control not found in Arm Variable. Perhaps they have been filtered out?" )) - q1 <- qenv %>% + q1 <- qenv |> teal.code::eval_code( code = as.expression(c( bquote(anl_labels <- formatters::var_labels(ANL, fill = FALSE)), bquote( - flags <- ANL %>% - select(all_of(.(flag_var_name))) %>% + flags <- ANL |> + select(all_of(.(flag_var_name))) |> rename_at(.(flag_var_name), function(x) paste0(x, ": ", anl_labels[x])) ) )) diff --git a/man/tm_g_ae_oview.Rd b/man/tm_g_ae_oview.Rd index e6a2ee30..4c39c033 100644 --- a/man/tm_g_ae_oview.Rd +++ b/man/tm_g_ae_oview.Rd @@ -103,13 +103,13 @@ For more information on reporting in \code{teal}, see the vignettes: } \examples{ -data <- teal_data() \%>\% +data <- teal_data() |> within({ library(dplyr) ADSL <- rADSL ADAE <- rADAE .add_event_flags <- function(dat) { - dat <- dat \%>\% + dat <- dat |> mutate( TMPFL_SER = AESER == "Y", TMPFL_REL = AEREL == "Y", @@ -159,13 +159,13 @@ if (interactive()) { shinyApp(app$ui, app$server) } -data <- teal_data() \%>\% +data <- teal_data() |> within({ library(dplyr) ADSL <- rADSL ADAE <- rADAE .add_event_flags <- function(dat) { - dat <- dat \%>\% + dat <- dat |> mutate( TMPFL_SER = AESER == "Y", TMPFL_REL = AEREL == "Y", @@ -193,6 +193,7 @@ app <- init( modules = modules( tm_g_ae_oview( label = "AE Overview", + dataname = "ADAE", arm_var = teal.picks::variables( choices = tidyselect::starts_with("ACTARM"), selected = "ACTARMCD" From df0f269cb4a2d17f0df574f61c73cd309dad8a7c Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:15:15 +0000 Subject: [PATCH 18/27] [skip style] [skip vbump] Restyle files --- R/tm_g_ae_oview_picks.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 93acce9c..bd1313f4 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -121,7 +121,8 @@ tm_g_ae_oview.pick <- function(label, # nolint: object_name_linter. ) } -ui_g_ae_oview.picks <- function( # nolint: object_name_linter. +ui_g_ae_oview.picks <- function( + # nolint: object_name_linter. id, arm_var, flag_var_anl, From b7219f05a08efd99353d3c52d1605ea891fc8168 Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 17 Mar 2026 11:41:08 +0100 Subject: [PATCH 19/27] chore: fix R CMD check and lintr --- R/tm_g_ae_oview_picks.R | 6 ++---- man/tm_g_ae_oview.Rd | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index bd1313f4..1f0d0dfb 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -36,7 +36,7 @@ #' label = "AE Overview", #' dataname = "ADAE", #' arm_var = teal.picks::variables( -#' choices = tidyselect::starts_with("ACTARM"), +#' choices = dplyr::starts_with("ACTARM"), #' selected = "ACTARMCD" #' ), #' flag_var_anl = teal.picks::variables( @@ -121,9 +121,7 @@ tm_g_ae_oview.pick <- function(label, # nolint: object_name_linter. ) } -ui_g_ae_oview.picks <- function( - # nolint: object_name_linter. - id, +ui_g_ae_oview.picks <- function(id, # nolint: object_name_linter. arm_var, flag_var_anl, fontsize diff --git a/man/tm_g_ae_oview.Rd b/man/tm_g_ae_oview.Rd index 4c39c033..28ddb994 100644 --- a/man/tm_g_ae_oview.Rd +++ b/man/tm_g_ae_oview.Rd @@ -195,7 +195,7 @@ app <- init( label = "AE Overview", dataname = "ADAE", arm_var = teal.picks::variables( - choices = tidyselect::starts_with("ACTARM"), + choices = dplyr::starts_with("ACTARM"), selected = "ACTARMCD" ), flag_var_anl = teal.picks::variables( From 640f80e69c3621c78592519f61ed780cf72651dc Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:43:18 +0000 Subject: [PATCH 20/27] [skip style] [skip vbump] Restyle files --- R/tm_g_ae_oview_picks.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 1f0d0dfb..1c1fdbea 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -121,7 +121,8 @@ tm_g_ae_oview.pick <- function(label, # nolint: object_name_linter. ) } -ui_g_ae_oview.picks <- function(id, # nolint: object_name_linter. +ui_g_ae_oview.picks <- function( + id, # nolint: object_name_linter. arm_var, flag_var_anl, fontsize From 6e6e2220287244d57ac9ac06b8db5e48203e13ad Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 17 Mar 2026 12:05:13 +0100 Subject: [PATCH 21/27] chore: fix styler and linter --- R/tm_g_ae_oview_picks.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 1c1fdbea..ffe5f9ea 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -121,8 +121,10 @@ tm_g_ae_oview.pick <- function(label, # nolint: object_name_linter. ) } +# nolint start: object_name_linter. ui_g_ae_oview.picks <- function( - id, # nolint: object_name_linter. + # nolint end: object_name_linter. + id, arm_var, flag_var_anl, fontsize From 73c6f602bd7a1218e4f2aac3a53f94f8b6046198 Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 17 Mar 2026 15:31:40 +0100 Subject: [PATCH 22/27] chore: revert to magrittr pipe --- R/tm_g_ae_oview.R | 10 +++++----- R/tm_g_ae_oview_picks.R | 10 +++++----- man/tm_g_ae_oview.Rd | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/R/tm_g_ae_oview.R b/R/tm_g_ae_oview.R index 36569e95..17690729 100644 --- a/R/tm_g_ae_oview.R +++ b/R/tm_g_ae_oview.R @@ -23,13 +23,13 @@ #' @inheritSection teal::example_module Reporting #' #' @examples -#' data <- teal_data() |> +#' data <- teal_data() %>% #' within({ #' library(dplyr) #' ADSL <- rADSL #' ADAE <- rADAE #' .add_event_flags <- function(dat) { -#' dat <- dat |> +#' dat <- dat %>% #' mutate( #' TMPFL_SER = AESER == "Y", #' TMPFL_REL = AEREL == "Y", @@ -315,13 +315,13 @@ srv_g_ae_oview <- function(id, "Treatment or Control not found in Arm Variable. Perhaps they have been filtered out?" )) - q1 <- obj |> + q1 <- obj %>% teal.code::eval_code( code = as.expression(c( bquote(anl_labels <- formatters::var_labels(.(as.name(dataname)), fill = FALSE)), bquote( - flags <- .(as.name(dataname)) |> - select(all_of(.(input$flag_var_anl))) |> + flags <- .(as.name(dataname)) %>% + select(all_of(.(input$flag_var_anl))) %>% rename_at(vars(.(input$flag_var_anl)), function(x) paste0(x, ": ", anl_labels[x])) ) )) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index ffe5f9ea..5d5c3541 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -1,12 +1,12 @@ #' @rdname tm_g_ae_oview #' @examples -#' data <- teal_data() |> +#' data <- teal_data() %>% #' within({ #' library(dplyr) #' ADSL <- rADSL #' ADAE <- rADAE #' .add_event_flags <- function(dat) { -#' dat <- dat |> +#' dat <- dat %>% #' mutate( #' TMPFL_SER = AESER == "Y", #' TMPFL_REL = AEREL == "Y", @@ -313,13 +313,13 @@ srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter. input$arm_trt %in% ANL[[arm_var_name]] && input$arm_ref %in% ANL[[arm_var_name]], "Treatment or Control not found in Arm Variable. Perhaps they have been filtered out?" )) - q1 <- qenv |> + q1 <- qenv %>% teal.code::eval_code( code = as.expression(c( bquote(anl_labels <- formatters::var_labels(ANL, fill = FALSE)), bquote( - flags <- ANL |> - select(all_of(.(flag_var_name))) |> + flags <- ANL %>% + select(all_of(.(flag_var_name))) %>% rename_at(.(flag_var_name), function(x) paste0(x, ": ", anl_labels[x])) ) )) diff --git a/man/tm_g_ae_oview.Rd b/man/tm_g_ae_oview.Rd index 28ddb994..2853dc0f 100644 --- a/man/tm_g_ae_oview.Rd +++ b/man/tm_g_ae_oview.Rd @@ -103,13 +103,13 @@ For more information on reporting in \code{teal}, see the vignettes: } \examples{ -data <- teal_data() |> +data <- teal_data() \%>\% within({ library(dplyr) ADSL <- rADSL ADAE <- rADAE .add_event_flags <- function(dat) { - dat <- dat |> + dat <- dat \%>\% mutate( TMPFL_SER = AESER == "Y", TMPFL_REL = AEREL == "Y", @@ -159,13 +159,13 @@ if (interactive()) { shinyApp(app$ui, app$server) } -data <- teal_data() |> +data <- teal_data() \%>\% within({ library(dplyr) ADSL <- rADSL ADAE <- rADAE .add_event_flags <- function(dat) { - dat <- dat |> + dat <- dat \%>\% mutate( TMPFL_SER = AESER == "Y", TMPFL_REL = AEREL == "Y", From 8ca1bc18ff4c57c7f4b9293bbbecafdb6a452322 Mon Sep 17 00:00:00 2001 From: osenan Date: Tue, 17 Mar 2026 15:36:14 +0100 Subject: [PATCH 23/27] chore: remove pipe consistency linter as we need magrittr pipes --- .lintr | 1 + 1 file changed, 1 insertion(+) diff --git a/.lintr b/.lintr index 33fb8ec3..b26207c8 100644 --- a/.lintr +++ b/.lintr @@ -2,6 +2,7 @@ linters: linters_with_defaults( line_length_linter = line_length_linter(120), cyclocomp_linter = NULL, object_usage_linter = NULL, + pipe_consistency_linter = NULL, object_name_linter = object_name_linter( styles = c("snake_case", "symbols"), regexes = c(ANL = "^ANL_?[0-9A-Za-z_]*$", ADaM = "^r?AD[A-Z]{2,5}_?[0-9A-Za-z_]*$") From 0e4d1bc375a4392d029c2810436c8214d0936283 Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:47:20 +0100 Subject: [PATCH 24/27] Update R/tm_g_ae_oview.R MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> Signed-off-by: Oriol Senan <35930244+osenan@users.noreply.github.com> --- R/tm_g_ae_oview.R | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/R/tm_g_ae_oview.R b/R/tm_g_ae_oview.R index 17690729..f960ba11 100644 --- a/R/tm_g_ae_oview.R +++ b/R/tm_g_ae_oview.R @@ -102,6 +102,19 @@ tm_g_ae_oview.default <- function(label, plot_width = NULL, transformators = list()) { message("Initializing tm_g_ae_oview") + checkmate::assert_class(arm_var, classes = "choices_selected") + checkmate::assert_class(flag_var_anl, classes = "choices_selected") + tm_g_ae_oview.pick( + label, + dataname, + teal.picks::as.picks(arm_var), + teal.picks::as.picks(flag_var_anl), + fontsize, + plot_height, + plot_width, + transformators + ) + checkmate::assert_class(arm_var, classes = "choices_selected") checkmate::assert_class(flag_var_anl, classes = "choices_selected") checkmate::assert( From af6849539a282e7219bb3457c5f7d4b9c53798bb Mon Sep 17 00:00:00 2001 From: osenan Date: Wed, 18 Mar 2026 07:18:27 +0100 Subject: [PATCH 25/27] refactor: use as.picks to reuse picks srv and ui in choices_selected --- R/tm_g_ae_oview.R | 252 ++-------------------------- R/tm_g_ae_oview_picks.R | 111 ++++++++---- tests/testthat/test-tm_g_ae_oview.R | 1 + 3 files changed, 87 insertions(+), 277 deletions(-) diff --git a/R/tm_g_ae_oview.R b/R/tm_g_ae_oview.R index f960ba11..6442957f 100644 --- a/R/tm_g_ae_oview.R +++ b/R/tm_g_ae_oview.R @@ -88,7 +88,7 @@ tm_g_ae_oview <- function(label, plot_height, plot_width, transformators) { - UseMethod("tm_g_ae_oview", flag_var_anl) + UseMethod("tm_g_ae_oview", arm_var) } #' @rdname tm_g_ae_oview @@ -102,21 +102,10 @@ tm_g_ae_oview.default <- function(label, plot_width = NULL, transformators = list()) { message("Initializing tm_g_ae_oview") - checkmate::assert_class(arm_var, classes = "choices_selected") - checkmate::assert_class(flag_var_anl, classes = "choices_selected") - tm_g_ae_oview.pick( - label, - dataname, - teal.picks::as.picks(arm_var), - teal.picks::as.picks(flag_var_anl), - fontsize, - plot_height, - plot_width, - transformators - ) checkmate::assert_class(arm_var, classes = "choices_selected") checkmate::assert_class(flag_var_anl, classes = "choices_selected") + checkmate::assert( checkmate::check_number(fontsize, finite = TRUE), checkmate::assert( @@ -137,235 +126,14 @@ tm_g_ae_oview.default <- function(label, lower = plot_width[2], upper = plot_width[3], null.ok = TRUE, .var.name = "plot_width" ) - args <- as.list(environment()) - - module( + tm_g_ae_oview.pick( label = label, - server = srv_g_ae_oview, - server_args = list( - label = label, - dataname = dataname, - plot_height = plot_height, - plot_width = plot_width - ), - ui = ui_g_ae_oview, - ui_args = args, - transformators = transformators, - datanames = c("ADSL", dataname) - ) -} - -ui_g_ae_oview <- function(id, ...) { - ns <- NS(id) - args <- list(...) - teal.widgets::standard_layout( - output = teal.widgets::white_small_well( - plot_decorate_output(id = ns(NULL)) - ), - encoding = tags$div( - teal.widgets::optionalSelectInput( - ns("arm_var"), - "Arm Variable", - choices = get_choices(args$arm_var$choices), - selected = args$arm_var$selected, - multiple = FALSE - ), - selectInput( - ns("arm_ref"), - "Control", - choices = get_choices(args$arm_var$choices), - selected = args$arm_var$selected - ), - selectInput( - ns("arm_trt"), - "Treatment", - choices = get_choices(args$arm_var$choices), - selected = args$arm_var$selected - ), - selectInput( - ns("flag_var_anl"), - "Flags", - choices = get_choices(args$flag_var_anl$choices), - selected = args$flag_var_anl$selected, - multiple = TRUE - ), - teal.widgets::panel_item( - "Confidence interval settings", - teal.widgets::optionalSelectInput( - ns("diff_ci_method"), - "Method for Difference of Proportions CI", - choices = ci_choices, - selected = ci_choices[1], - multiple = FALSE - ), - teal.widgets::optionalSliderInput( - ns("conf_level"), - "Confidence Level", - min = 0.5, - max = 1, - value = 0.95 - ) - ), - teal.widgets::optionalSelectInput( - ns("axis"), - "Axis Side", - choices = c("Left" = "left", "Right" = "right"), - selected = "left", - multiple = FALSE - ), - ui_g_decorate( - ns(NULL), - fontsize = args$fontsize, - titles = "AE Overview", - footnotes = "" - ) - ) + dataname = dataname, + arm_var = teal.picks::as.picks(arm_var), + flag_var_anl = teal.picks::as.picks(flag_var_anl), + fontsize, + plot_height, + plot_width, + transformators ) } - -srv_g_ae_oview <- function(id, - data, - dataname, - label, - plot_height, - plot_width) { - checkmate::assert_class(data, "reactive") - checkmate::assert_class(isolate(data()), "teal_data") - - moduleServer(id, function(input, output, session) { - teal.logger::log_shiny_input_changes(input, namespace = "teal.osprey") - iv <- reactive({ - ANL <- data()[[dataname]] - - iv <- shinyvalidate::InputValidator$new() - iv$add_rule("arm_var", shinyvalidate::sv_required( - message = "Arm Variable is required" - )) - iv$add_rule("arm_var", ~ if (!is.factor(ANL[[.]])) { - "Arm Var must be a factor variable" - }) - iv$add_rule("arm_var", ~ if (nlevels(ANL[[.]]) < 2L) { - "Selected Arm Var must have at least two levels" - }) - iv$add_rule("flag_var_anl", shinyvalidate::sv_required( - message = "At least one Flag is required" - )) - rule_diff <- function(value, other) { - if (isTRUE(value == other)) "Control and Treatment must be different" - } - iv$add_rule("arm_trt", rule_diff, other = input$arm_ref) - iv$add_rule("arm_ref", rule_diff, other = input$arm_trt) - iv$enable() - iv - }) - - decorate_output <- srv_g_decorate( - id = NULL, plt = plot_r, - plot_height = plot_height, plot_width = plot_width - ) - font_size <- decorate_output$font_size - pws <- decorate_output$pws - - observeEvent(list(input$diff_ci_method, input$conf_level), { - req(!is.null(input$diff_ci_method) && !is.null(input$conf_level)) - diff_ci_method <- input$diff_ci_method - conf_level <- input$conf_level - updateTextAreaInput(session, - "foot", - value = sprintf( - "Note: %d%% CI is calculated using %s", - round(conf_level * 100), - name_ci(diff_ci_method) - ) - ) - }) - - observeEvent(input$arm_var, ignoreNULL = TRUE, { - ANL <- data()[[dataname]] - arm_var <- input$arm_var - arm_val <- ANL[[arm_var]] - choices <- levels(arm_val) - - if (length(choices) == 1) { - trt_index <- 1 - } else { - trt_index <- 2 - } - - updateSelectInput( - session, - "arm_ref", - selected = choices[1], - choices = choices - ) - updateSelectInput( - session, - "arm_trt", - selected = choices[trt_index], - choices = choices - ) - }) - - output_q <- shiny::debounce( - millis = 200, - r = reactive({ - obj <- data() - teal.reporter::teal_card(obj) <- - c( - teal.reporter::teal_card(obj), - teal.reporter::teal_card("## Module's output(s)") - ) - obj <- teal.code::eval_code(obj, "library(dplyr)") - - ANL <- obj[[dataname]] - - teal::validate_has_data(ANL, min_nrow = 10, msg = sprintf("%s has not enough data", dataname)) - - teal::validate_inputs(iv()) - - validate(need( - input$arm_trt %in% ANL[[input$arm_var]] && input$arm_ref %in% ANL[[input$arm_var]], - "Treatment or Control not found in Arm Variable. Perhaps they have been filtered out?" - )) - - q1 <- obj %>% - teal.code::eval_code( - code = as.expression(c( - bquote(anl_labels <- formatters::var_labels(.(as.name(dataname)), fill = FALSE)), - bquote( - flags <- .(as.name(dataname)) %>% - select(all_of(.(input$flag_var_anl))) %>% - rename_at(vars(.(input$flag_var_anl)), function(x) paste0(x, ": ", anl_labels[x])) - ) - )) - ) - - teal.reporter::teal_card(q1) <- c(teal.reporter::teal_card(q1), "### Plot") - - teal.code::eval_code( - q1, - code = as.expression(c( - bquote( - plot <- osprey::g_events_term_id( - term = flags, - id = .(as.name(dataname))[["USUBJID"]], - arm = .(as.name(dataname))[[.(input$arm_var)]], - arm_N = table(ADSL[[.(input$arm_var)]]), - ref = .(input$arm_ref), - trt = .(input$arm_trt), - diff_ci_method = .(input$diff_ci_method), - conf_level = .(input$conf_level), - axis_side = .(input$axis), - fontsize = .(font_size()), - draw = TRUE - ) - ) - )) - ) - }) - ) - - plot_r <- reactive(output_q()[["plot"]]) - set_chunk_dims(pws, output_q) - }) -} diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 5d5c3541..510ecaef 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -51,24 +51,29 @@ #' shinyApp(app$ui, app$server) #' } #' @export -tm_g_ae_oview.pick <- function(label, # nolint: object_name_linter. - dataname, - arm_var = teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = 1L - ), - flag_var_anl = teal.picks::variables( - choices = teal.picks::is_categorical(min.len = 2), - selected = 1L - ), - fontsize = c(5, 3, 7), - plot_height = c(600L, 200L, 2000L), - plot_width = NULL, - transformators = list()) { +tm_g_ae_oview.pick <- function( + label, # nolint: object_name_linter. + dataname, + arm_var = teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ), + flag_var_anl = teal.picks::variables( + choices = teal.picks::is_categorical(min.len = 2), + selected = 1L + ), + fontsize = c(5, 3, 7), + plot_height = c(600L, 200L, 2000L), + plot_width = NULL, + transformators = list() +) { message("Initializing tm_g_ae_oview") arm_var <- teal.picks::picks(teal.picks::datasets(dataname), arm_var) - flag_var_anl <- teal.picks::picks(teal.picks::datasets(dataname), flag_var_anl) + flag_var_anl <- teal.picks::picks( + teal.picks::datasets(dataname), + flag_var_anl + ) checkmate::assert_class(arm_var, "picks") if (isTRUE(attr(arm_var$variables, "multiple"))) { @@ -93,19 +98,44 @@ tm_g_ae_oview.pick <- function(label, # nolint: object_name_linter. checkmate::assert( combine = "and", .var.name = "fontsize", - checkmate::check_numeric(fontsize, len = 3, any.missing = FALSE, finite = TRUE), - checkmate::check_numeric(fontsize[1], lower = fontsize[2], upper = fontsize[3]) + checkmate::check_numeric( + fontsize, + len = 3, + any.missing = FALSE, + finite = TRUE + ), + checkmate::check_numeric( + fontsize[1], + lower = fontsize[2], + upper = fontsize[3] + ) ) ) - checkmate::assert_numeric(plot_height, len = 3, any.missing = FALSE, finite = TRUE) - checkmate::assert_numeric(plot_height[1], - lower = plot_height[2], upper = plot_height[3], + checkmate::assert_numeric( + plot_height, + len = 3, + any.missing = FALSE, + finite = TRUE + ) + checkmate::assert_numeric( + plot_height[1], + lower = plot_height[2], + upper = plot_height[3], .var.name = "plot_height" ) - checkmate::assert_numeric(plot_width, len = 3, any.missing = FALSE, null.ok = TRUE, finite = TRUE) + checkmate::assert_numeric( + plot_width, + len = 3, + any.missing = FALSE, + null.ok = TRUE, + finite = TRUE + ) checkmate::assert_numeric( plot_width[1], - lower = plot_width[2], upper = plot_width[3], null.ok = TRUE, .var.name = "plot_width" + lower = plot_width[2], + upper = plot_width[3], + null.ok = TRUE, + .var.name = "plot_width" ) args <- as.list(environment()) @@ -189,12 +219,14 @@ ui_g_ae_oview.picks <- function( ) } -srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter. - data, - arm_var, - flag_var_anl, - plot_height, - plot_width) { +srv_g_ae_oview.picks <- function( + id, # nolint: object_name_linter. + data, + arm_var, + flag_var_anl, + plot_height, + plot_width +) { checkmate::assert_class(data, "reactive") checkmate::assert_class(isolate(data()), "teal_data") @@ -219,8 +251,10 @@ srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter. teal.logger::log_shiny_input_changes(input, namespace = "teal.osprey") decorate_output <- srv_g_decorate( - id = NULL, plt = plot_r, - plot_height = plot_height, plot_width = plot_width + id = NULL, + plt = plot_r, + plot_height = plot_height, + plot_width = plot_width ) font_size <- decorate_output$font_size pws <- decorate_output$pws @@ -229,7 +263,8 @@ srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter. req(!is.null(input$diff_ci_method) && !is.null(input$conf_level)) diff_ci_method <- input$diff_ci_method conf_level <- input$conf_level - updateTextAreaInput(session, + updateTextAreaInput( + session, "foot", value = sprintf( "Note: %d%% CI is calculated using %s", @@ -308,9 +343,10 @@ srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter. ) ) - validate(need( - input$arm_trt %in% ANL[[arm_var_name]] && input$arm_ref %in% ANL[[arm_var_name]], + input$arm_trt %in% + ANL[[arm_var_name]] && + input$arm_ref %in% ANL[[arm_var_name]], "Treatment or Control not found in Arm Variable. Perhaps they have been filtered out?" )) q1 <- qenv %>% @@ -320,12 +356,17 @@ srv_g_ae_oview.picks <- function(id, # nolint: object_name_linter. bquote( flags <- ANL %>% select(all_of(.(flag_var_name))) %>% - rename_at(.(flag_var_name), function(x) paste0(x, ": ", anl_labels[x])) + rename_at(.(flag_var_name), function(x) { + paste0(x, ": ", anl_labels[x]) + }) ) )) ) - teal.reporter::teal_card(q1) <- c(teal.reporter::teal_card(q1), "### Plot") + teal.reporter::teal_card(q1) <- c( + teal.reporter::teal_card(q1), + "### Plot" + ) teal.code::eval_code( q1, code = as.expression(c( diff --git a/tests/testthat/test-tm_g_ae_oview.R b/tests/testthat/test-tm_g_ae_oview.R index 7fa08f72..157f71a7 100644 --- a/tests/testthat/test-tm_g_ae_oview.R +++ b/tests/testthat/test-tm_g_ae_oview.R @@ -23,6 +23,7 @@ testthat::describe("tm_g_ae_oview argument verification", { testthat::expect_error( tm_g_ae_oview( label = "AE Overview", + dataname = "ADAE", arm_var = arm_var_picks, flag_var_anl = flag_var_cs ), From e5e9dad7459f37928614bc0ba80494bedeb41e82 Mon Sep 17 00:00:00 2001 From: osenan Date: Wed, 18 Mar 2026 07:53:51 +0100 Subject: [PATCH 26/27] chore: fix lintr comment to avoid automatic restyling --- R/tm_g_ae_oview_picks.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 510ecaef..9d82f788 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -219,8 +219,10 @@ ui_g_ae_oview.picks <- function( ) } +# nolint start: object_name_linter. srv_g_ae_oview.picks <- function( - id, # nolint: object_name_linter. + # nolint end: object_name_linter. + id, data, arm_var, flag_var_anl, From 5f0cfc2c3d76d26c4e3d32aba6cd98fb27713eaa Mon Sep 17 00:00:00 2001 From: Oriol Senan <35930244+osenan@users.noreply.github.com> Date: Wed, 18 Mar 2026 12:04:23 +0100 Subject: [PATCH 27/27] Update R/tm_g_ae_oview_picks.R MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Veríssimo <211358+averissimo@users.noreply.github.com> Signed-off-by: Oriol Senan <35930244+osenan@users.noreply.github.com> --- R/tm_g_ae_oview_picks.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/tm_g_ae_oview_picks.R b/R/tm_g_ae_oview_picks.R index 9d82f788..19c622ad 100644 --- a/R/tm_g_ae_oview_picks.R +++ b/R/tm_g_ae_oview_picks.R @@ -276,8 +276,8 @@ srv_g_ae_oview.picks <- function( ) }) - observeEvent(selectors$arm_var(), { - arm_var_name <- selectors$arm_var()$variables$selected + observeEvent(merged$variables()$arm_var, { + arm_var_name <- merged$variables()$arm_var arm_dataset <- selectors$arm_var()$datasets$selected req(arm_var_name, arm_dataset)