diff --git a/DESCRIPTION b/DESCRIPTION index 75ed15b2b2..35631c86ed 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -38,6 +38,7 @@ Imports: ggplot2, ggrepel, grid, + lifecycle, logger (>= 0.2.0), magrittr, methods, diff --git a/NEWS.md b/NEWS.md index b71812282e..d4bca86fef 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,12 @@ # teal.modules.clinical 0.8.13.9021 +### Breaking changes + +* Replaced `chunks` with simpler `Quosure` class. +* Replaced `datasets` argument containing `FilteredData` with the new arguments `data` (list of reactive datasets) and `filter_panel_api` (`FilterPanelAPI`). + ### Enhancements + * Updated all test files in `tests/testthat/` to `synthetic_cdisc_data("2022_02_28")` * Reverted missing data checkbox in `tm_t_summary` (encoding and filtering should be separate). * Implemented a new widget that allows dragging and dropping to select comparison groups. @@ -10,10 +16,12 @@ * Added more descriptive title/labels to `tm_g_ci`. ### Bug fixes + * Fixed bug in `tm_g_barchart_simple` which prevented graph from being shown. * Fixed broken example for `tm_t_abnormality_by_worst_grade`. ### Miscellaneous + * Added `nestcolor` dependency and replaced deprecated function `tern::color_palette` with `nestcolor::color_palette` # teal.modules.clinical 0.8.13 diff --git a/R/argument_convention.R b/R/argument_convention.R index 255baa1bcf..ad57f9774f 100644 --- a/R/argument_convention.R +++ b/R/argument_convention.R @@ -113,7 +113,8 @@ NULL #' @param arm_var (`choices_selected` or `data_extract_spec`)\cr #' object with all available choices #' and preselected option for variable names that can be used as `arm_var`. -#' It defines the grouping variable(s) in the results table. If there are two elements selected for `arm_var`, +#' It defines the grouping variable(s) in the results table. +#' If there are two elements selected for `arm_var`, #' second variable will be nested under the first variable. #' @param arm_ref_comp optional, (`list`)\cr #' If specified it must be a named list with each element corresponding to diff --git a/R/arm_ref_comp.R b/R/arm_ref_comp.R index 6465fe9df0..fd5bbdca86 100644 --- a/R/arm_ref_comp.R +++ b/R/arm_ref_comp.R @@ -9,8 +9,8 @@ #' @param id_ref (`character`) id of reference Treatment input ui element #' @param id_comp (`character`) id of comparison group input ui element #' @param id_arm_var (`character`) id of Treatment variable input ui element -#' @param datasets (`FilteredData`) object from the module -#' @param dataname (`character`) dataset name +#' @param data (`reactive` or `data.frame`) dataset used to validate Treatment reference inputs and +#' set `id_ref` input. #' @param arm_ref_comp (`unknown`) Treatment reference and compare variables provided as a #' nested list where each Treatment variable corresponds a list specifying the default levels for the #' reference and comparison treatments. @@ -60,30 +60,24 @@ arm_ref_comp_observer <- function(session, id_ref = "Ref", id_comp = "Comp", id_arm_var, - datasets, - dataname = "ADSL", + data, arm_ref_comp, module, on_off = shiny::reactive(TRUE), input_id = "buckets", output_id = "arms_buckets") { - if (any(unlist(lapply(arm_ref_comp, lapply, inherits, "delayed_data")))) { - stopifnot( - all(vapply(arm_ref_comp, function(x) identical(sort(names(x)), c("comp", "ref")), logical(1))) - ) - # when a delayed object is used for arm_ref_comp, the entire FilteredData - # object must be passed to resolve it - arm_ref_comp <- teal.transform::resolve_delayed(arm_ref_comp, datasets) - } - - df <- datasets$get_data(dataname, filtered = FALSE) - - check_arm_ref_comp(arm_ref_comp, df, module) ## throws an error if there are issues - # uses observe because observeEvent evaluates only when on_off() is switched # not necessarily when variables are dropped output[[output_id]] <- shiny::renderUI({ if (!is.null(on_off()) && on_off()) { + df <- if (shiny::is.reactive(data)) { + data() + } else { + data + } + + check_arm_ref_comp(arm_ref_comp, df, module) ## throws an error if there are issues + arm_var <- input[[id_arm_var]] # validations here don't produce nice UI message (it's observe and not render output) but it prevent red errors @@ -97,7 +91,6 @@ arm_ref_comp_observer <- function(session, } else { unique(arm) } - default_settings <- arm_ref_comp[[arm_var]] if (is.null(default_settings)) { @@ -150,29 +143,17 @@ check_arm_ref_comp <- function(x, df_to_check, module) { } - Map(function(xi, var) { - if (!is.list(xi)) { - stop( - msg, "definition for Treatment variable ", - var, " list element needs to be lists with ref and comp elements" - ) - } - - rc <- names(xi) - if (is.null(rc) || !identical(sort(rc), c("comp", "ref"))) { - stop(msg, "definition for Treatment variable ", var, " nested list needs to have the elements ref and comp") - } - - - arm_levels <- unlist(xi) - - if (!all(arm_levels %in% df_to_check[[var]])) { - stop( - msg, "definition for Treatment variable ", - var, " refers to treatment levels that do not exist in the data" - ) + Map( + x, vars, + f = function(xi, var) { + if (!checkmate::check_list(xi) || !setequal(names(xi), c("comp", "ref"))) { + stop( + msg, "definition for Treatment variable ", + var, " list element needs to be lists with ref and comp elements" + ) + } } - }, x, vars) + ) } invisible(TRUE) diff --git a/R/tm_a_mmrm.R b/R/tm_a_mmrm.R index 896a386478..027daa3e10 100644 --- a/R/tm_a_mmrm.R +++ b/R/tm_a_mmrm.R @@ -788,18 +788,19 @@ ui_mmrm <- function(id, ...) { ) ) ) - ), - forms = teal::get_rcode_ui(ns("rcode")), - pre_output = a$pre_output, - post_output = a$post_output - ) + ) + ), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), + pre_output = a$pre_output, + post_output = a$post_output ) } #' @noRd srv_mmrm <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -815,11 +816,10 @@ srv_mmrm <- function(id, plot_width, basic_table_args, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") + shiny::moduleServer(id, function(input, output, session) { # Reactive responsible for sending a disable/enable signal # to show R code and debug info buttons disable_r_code <- shiny::reactiveVal(FALSE) @@ -841,8 +841,8 @@ srv_mmrm <- function(id, ) }) - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merge_inputs <- teal.transform::merge_expression_module( + datasets = data, data_extract = list( arm_var = arm_var, paramcd = paramcd, @@ -851,15 +851,23 @@ srv_mmrm <- function(id, split_covariates = split_covariates, aval_var = aval_var ), + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merge_inputs <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(arm_var = arm_var), + join_keys = attr(data, "join_keys"), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + q1 <- teal.code::new_quosure(data) + q2 <- teal.code::eval_code(q1, as.expression(anl_merge_inputs()$expr)) + teal.code::eval_code(q2, as.expression(adsl_merge_inputs()$expr)) + }) + # Initially hide the output title because there is no output yet. shinyjs::hide("mmrm_title") @@ -891,8 +899,8 @@ srv_mmrm <- function(id, # Setup arm variable selection, default reference arms, and default # comparison arms for encoding panel. - shiny::observeEvent(adsl_merged()$columns_source$arm_var, { - arm_var <- as.vector(adsl_merged()$columns_source$arm_var) + shiny::observeEvent(adsl_merge_inputs()$columns_source$arm_var, { + arm_var <- as.vector(adsl_merge_inputs()$columns_source$arm_var) if (length(arm_var) == 0) { shinyjs::hide("arms_buckets") shinyjs::hide("help_text") @@ -909,8 +917,7 @@ srv_mmrm <- function(id, input, output, id_arm_var = extract_input("arm_var", parentname), # From UI. - datasets = datasets, - dataname = parentname, + data = data[[parentname]], arm_ref_comp = arm_ref_comp, module = "tm_mmrm" ) @@ -1024,8 +1031,8 @@ srv_mmrm <- function(id, ) names(encoding_inputs) <- sync_inputs - adsl_filtered <- datasets$get_data("ADSL", filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- anl_merged_q()[["ADSL"]] + anl_filtered <- anl_merged_q()[[dataname]] shiny::validate( shiny::need( @@ -1099,23 +1106,24 @@ srv_mmrm <- function(id, # Prepare the analysis environment (filter data, check data, populate envir). validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- anl_merged_q()[[parentname]] + anl_filtered <- anl_merged_q()[[dataname]] + anl_data <- anl_merged_q()[["ANL"]] - anl_m <- anl_merged() + anl_m_inputs <- anl_merge_inputs() if (!is.null(input[[extract_input("arm_var", parentname)]])) { - input_arm_var <- as.vector(anl_m$columns_source$arm_var) + input_arm_var <- as.vector(anl_m_inputs$columns_source$arm_var) } else { input_arm_var <- NULL } - input_visit_var <- as.vector(anl_m$columns_source$visit_var) + input_visit_var <- as.vector(anl_m_inputs$columns_source$visit_var) - input_aval_var <- as.vector(anl_m$columns_source$aval_var) - input_id_var <- as.vector(anl_m$columns_source$id_var) + input_aval_var <- as.vector(anl_m_inputs$columns_source$aval_var) + input_id_var <- as.vector(anl_m_inputs$columns_source$id_var) input_paramcd <- unlist(paramcd$filter)["vars_selected"] # Split the existing covariate strings in their variable parts, to allow "A*B" and "A:B" notations. - input_cov_var <- as.vector(anl_m$columns_source$split_covariates) + input_cov_var <- as.vector(anl_m_inputs$columns_source$split_covariates) covariate_parts <- split_interactions(input_cov_var) all_x_vars <- c(input_arm_var, input_visit_var, covariate_parts) @@ -1144,9 +1152,6 @@ srv_mmrm <- function(id, need_arm = FALSE ) - - anl_data <- anl_m$data() - Map( function(visit_df, visit_name) { dup <- any(duplicated(visit_df[[input_id_var]])) @@ -1165,31 +1170,19 @@ srv_mmrm <- function(id, # Connector: # Fit the MMRM, once the user clicks on the start button. mmrm_fit <- shiny::eventReactive(input$button_start, { - # Create a private stack for this function only. - fit_stack <- teal.code::chunks_new() - fit_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = fit_stack) - } - - teal.code::chunks_reset(chunks = fit_stack) - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m, chunks = fit_stack) - teal.code::chunks_push_new_line(chunks = fit_stack) - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl, chunks = fit_stack) - teal.code::chunks_push_new_line(chunks = fit_stack) + q1 <- anl_merged_q() + anl_m_inputs <- anl_merge_inputs() my_calls <- template_fit_mmrm( parentname = "ANL_ADSL", dataname = "ANL", - aval_var = as.vector(anl_m$columns_source$aval_var), + aval_var = as.vector(anl_m_inputs$columns_source$aval_var), arm_var = input[[extract_input("arm_var", parentname)]], ref_arm = unlist(input$buckets$Ref), comp_arm = unlist(input$buckets$Comp), combine_comp_arms = input$combine_comp_arms, - id_var = as.vector(anl_m$columns_source$id_var), - visit_var = as.vector(anl_m$columns_source$visit_var), + id_var = as.vector(anl_m_inputs$columns_source$id_var), + visit_var = as.vector(anl_m_inputs$columns_source$visit_var), cov_var = input[[extract_input("cov_var", dataname)]], conf_level = as.numeric(input$conf_level), cor_struct = input$cor_struct, @@ -1197,9 +1190,7 @@ srv_mmrm <- function(id, optimizer = input$optimizer, parallel = input$parallel ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), fit_stack_push) - teal.code::chunks_safe_eval(chunks = fit_stack) - fit_stack + teal.code::eval_code(q1, as.expression(my_calls)) }) output$mmrm_title <- shiny::renderText({ @@ -1232,7 +1223,7 @@ srv_mmrm <- function(id, output_title }) - table_r <- shiny::reactive({ + table_q <- shiny::reactive({ shiny::validate( shiny::need( !state_has_changed(), @@ -1246,57 +1237,35 @@ srv_mmrm <- function(id, if (!isTRUE(grepl("^t_", output_function))) { return(NULL) } - # Reset global chunks. Needs to be done here so nothing yet in environment. - teal.code::chunks_reset() # Get the fit stack while evaluating the fit code at the same time. - fit_stack <- mmrm_fit() - fit <- teal.code::chunks_get_var("fit", chunks = fit_stack) - # Start new private stack for the table code. - table_stack <- teal.code::chunks_new() - - table_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = table_stack) - } + q1 <- mmrm_fit() + fit <- q1[["fit"]] - anl_m <- anl_merged() + anl_m_inputs <- anl_merge_inputs() - ANL <- teal.code::chunks_get_var("ANL", chunks = fit_stack) # nolint - ANL_ADSL <- teal.code::chunks_get_var("ANL_ADSL", chunks = fit_stack) # nolint + ANL <- q1[["ANL"]] # nolint + ANL_ADSL <- q1[["ANL_ADSL"]] # nolint paramcd <- unique(ANL[[unlist(paramcd$filter)["vars_selected"]]]) - mmrm_table <- function(table_type) { - res <- template_mmrm_tables( - parentname = "ANL_ADSL", - dataname = "ANL", - fit_name = "fit", - arm_var = input[[extract_input("arm_var", parentname)]], - ref_arm = unlist(input$buckets$Ref), - visit_var = as.vector(anl_m$columns_source$visit_var), - paramcd = paramcd, - show_relative = input$t_mmrm_lsmeans_show_relative, - table_type = table_type, - basic_table_args = basic_table_args - ) - - mapply(expression = res, id = paste(names(res), "call", sep = "_"), table_stack_push) - teal.code::chunks_push_chunks(table_stack) - teal.code::chunks_safe_eval() - } - teal.code::chunks_push_chunks(fit_stack) - mmrm_table(output_function) - - # Depending on the table function type, produce different code - switch(output_function, - t_mmrm_lsmeans = teal.code::chunks_get_var("lsmeans_table"), - t_mmrm_diagnostic = teal.code::chunks_get_var("diagnostic_table"), - t_mmrm_fixed = teal.code::chunks_get_var("fixed_effects"), - t_mmrm_cov = teal.code::chunks_get_var("cov_matrix") + mmrm_table <- template_mmrm_tables( + parentname = "ANL_ADSL", + dataname = "ANL", + fit_name = "fit", + arm_var = input[[extract_input("arm_var", parentname)]], + ref_arm = unlist(input$buckets$Ref), + visit_var = as.vector(anl_m_inputs$columns_source$visit_var), + paramcd = paramcd, + show_relative = input$t_mmrm_lsmeans_show_relative, + table_type = output_function, + basic_table_args = basic_table_args ) + + teal.code::eval_code(q1, as.expression(mmrm_table)) }) # Endpoint: # Plot outputs. - plot_r <- shiny::reactive({ + plot_q <- shiny::reactive({ shiny::validate( shiny::need( !state_has_changed(), @@ -1310,50 +1279,57 @@ srv_mmrm <- function(id, if (!isTRUE(grepl("^g_", output_function))) { return(NULL) } - teal.code::chunks_reset() - fit_stack <- mmrm_fit() - fit <- teal.code::chunks_get_var("fit", fit_stack) - - # Start new private stack for the plot code. - plot_stack <- teal.code::chunks_new() - plot_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = plot_stack) + + q1 <- mmrm_fit() + fit <- q1[["fit"]] + + lsmeans_args <- if (output_function == "g_mmrm_lsmeans") { + list( + select = input$g_mmrm_lsmeans_select, + width = input$g_mmrm_lsmeans_width, + show_pval = input$g_mmrm_lsmeans_contrasts_show_pval + ) + } + + diagnostic_args <- if (output_function == "g_mmrm_diagnostic") { + list( + type = input$g_mmrm_diagnostic_type, + z_threshold = input$g_mmrm_diagnostic_z_threshold + ) } - lsmeans_args <- list( - select = input$g_mmrm_lsmeans_select, - width = input$g_mmrm_lsmeans_width, - show_pval = input$g_mmrm_lsmeans_contrasts_show_pval - ) - diagnostic_args <- list( - type = input$g_mmrm_diagnostic_type, - z_threshold = input$g_mmrm_diagnostic_z_threshold + mmrm_plot_expr <- template_mmrm_plots( + fit_name = "fit", + lsmeans_plot = lsmeans_args, + diagnostic_plot = diagnostic_args, + ggplot2_args = ggplot2_args ) + teal.code::eval_code(q1, as.expression(mmrm_plot_expr)) + }) - mmrm_plot <- function(lsmeans_plot = lsmeans_args, - diagnostic_plot = diagnostic_args) { - res <- template_mmrm_plots( - "fit", - lsmeans_plot = lsmeans_plot, - diagnostic_plot = diagnostic_plot, - ggplot2_args = ggplot2_args - ) - mapply(expression = res, id = paste(names(res), "call", sep = "_"), plot_stack_push) - teal.code::chunks_push_chunks(plot_stack) - teal.code::chunks_safe_eval() + all_code <- shiny::reactive({ + if (!is.null(plot_q()) && !is.null(table_q())) { + join(plot_q(), table_q()) + } else if (!is.null(plot_q())) { + plot_q() + } else { + table_q() } + }) - teal.code::chunks_push_chunks(fit_stack) - # Depending on the plot function type, produce different code. - switch(output_function, - g_mmrm_lsmeans = { - mmrm_plot(diagnostic_plot = NULL) - teal.code::chunks_get_var("lsmeans_plot") - }, - g_mmrm_diagnostic = { - mmrm_plot(lsmeans_plot = NULL) - teal.code::chunks_get_var("diagnostic_plot") - } + table_r <- shiny::reactive({ + switch(input$output_function, + t_mmrm_lsmeans = table_q()[["lsmeans_table"]], + t_mmrm_diagnostic = table_q()[["diagnostic_table"]], + t_mmrm_fixed = table_q()[["fixed_effects"]], + t_mmrm_cov = table_q()[["cov_matrix"]] + ) + }) + + plot_r <- shiny::reactive({ + switch(input$output_function, + g_mmrm_lsmeans = plot_q()[["lsmeans_plot"]], + g_mmrm_diagnostic = plot_q()[["diagnostic_plot"]] ) }) @@ -1377,7 +1353,7 @@ srv_mmrm <- function(id, # First reassign reactive sources: fit_stack <- try(mmrm_fit(), silent = TRUE) result <- if (!inherits(fit_stack, "try-error")) { - fit <- teal.code::chunks_get_var("fit", chunks = fit_stack) + fit <- fit_stack[["fit"]] if (input$optimizer == "automatic") { selected <- attr(fit$fit, "optimizer") paste("Optimizer used:", selected) @@ -1398,13 +1374,11 @@ srv_mmrm <- function(id, }) # Show R code once button is pressed. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(arm_var, paramcd, id_var, visit_var, cov_var, aval_var)), - modal_title = "R Code for the Current MMRM Analysis", - code_header = label, - disable_buttons = disable_r_code + verbatim_content = reactive(teal.code::get_code(all_code())), + disabled = disable_r_code, + title = "R Code for the Current MMRM Analysis" ) ### REPORTER @@ -1420,7 +1394,9 @@ srv_mmrm <- function(id, ), "header3" ) - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } if (!is.null(table_r())) { card$append_text("Table", "header3") card$append_table(table_r()) @@ -1433,12 +1409,7 @@ srv_mmrm <- function(id, card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(all_code()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_barchart_simple.R b/R/tm_g_barchart_simple.R index afa4b79d98..ace4751e61 100644 --- a/R/tm_g_barchart_simple.R +++ b/R/tm_g_barchart_simple.R @@ -300,17 +300,18 @@ ui_g_barchart_simple <- function(id, ...) { ) ) ) - ), - forms = teal::get_rcode_ui(ns("rcode")), - pre_output = args$pre_output, - post_output = args$post_output - ) + ) + ), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), button_label = "Show R code"), + pre_output = args$pre_output, + post_output = args$post_output ) } srv_g_barchart_simple <- function(id, - datasets, + data, reporter, + filter_panel_api, x, fill, x_facet, @@ -318,113 +319,88 @@ srv_g_barchart_simple <- function(id, plot_height, plot_width, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - data_extract <- list(x = x, fill = fill, x_facet = x_facet, y_facet = y_facet) - data_extract <- data_extract[!vapply(data_extract, is.null, logical(1))] - - selector_list <- teal.transform::data_extract_multiple_srv(data_extract, datasets) - - reactive_select_input <- shiny::reactive({ - selectors <- selector_list() - extract_names <- names(selectors) - for (extract in extract_names) { - if (is.null(selectors[[extract]]) || length(selectors[[extract]]()$select) == 0) { - selectors <- selectors[-which(names(selectors) == extract)] - } - } - selectors - }) - - merged_data <- teal.transform::data_merge_srv( - selector_list = reactive_select_input, - datasets = datasets + merge_inputs <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), + data_extract = list(x = x, fill = fill, x_facet = x_facet, y_facet = y_facet) ) - data_chunk <- shiny::reactive({ + merged_data_q <- shiny::reactive({ shiny::validate({ - shiny::need("x" %in% names(reactive_select_input()), "Please select an x-variable") + shiny::need(merge_inputs()$columns_source$x, "Please select an x-variable") }) - ANL <- merged_data()$data() # nolint - teal::validate_has_data(ANL, 2) - chunk <- teal.code::chunks_new() - teal.code::chunks_push_data_merge(merged_data(), chunks = chunk) - chunk + quo <- teal.code::new_quosure(env = data) + quo <- teal.code::eval_code(quo, as.expression(merge_inputs()$expr)) + quo }) - count_chunk <- shiny::reactive({ - chunk <- teal.code::chunks_deep_clone(data_chunk()) + count_q <- shiny::reactive({ + req(merged_data_q()) + quo <- merged_data_q() + teal::validate_has_data(quo[["ANL"]], 2) groupby_vars <- r_groupby_vars() - groupby_vars_l <- as.list(groupby_vars) # atomic -> list #nolintr # count - n_names <- c() - count_by_group <- function(groupby_vars, ...) { - # chunk and n_names are modified + count_by_group <- function(groupby_vars, data_name) { n_name <- get_n_name(groupby_vars) - n_names <- c(n_names, n_name) - count_by_group_chunk(chunk, groupby_vars = groupby_vars, n_name = n_name, ...) + count_by_group_expr(groupby_vars = groupby_vars, data_name = data_name) } - count_by_group(groupby_vars, data_name = "ANL") # may be repeated by statements below + count_exprs <- count_by_group(groupby_vars, data_name = "ANL") if (input$show_n) { - # count for each group - # x_name: more complicated, done below - if (!is.null(groupby_vars_l$fill_name)) count_by_group(groupby_vars_l$fill_name) - if (!is.null(groupby_vars_l$x_facet_name)) count_by_group(groupby_vars_l$x_facet_name) - if (!is.null(groupby_vars_l$y_facet_name)) count_by_group(groupby_vars_l$y_facet_name) - - if (!is.null(groupby_vars_l$fill_name)) add_count_str_to_column(chunk, column = groupby_vars_l$fill_name) - if (!is.null(groupby_vars_l$x_facet_name)) add_count_str_to_column(chunk, column = groupby_vars_l$x_facet_name) - if (!is.null(groupby_vars_l$y_facet_name)) add_count_str_to_column(chunk, column = groupby_vars_l$y_facet_name) + count_exprs2 <- sapply(groupby_vars[-1], count_by_group, data_name = "counts") + count_str_to_col_exprs <- sapply(groupby_vars[-1], count_str_to_column_expr) + count_exprs <- c(count_exprs, count_exprs2, count_str_to_col_exprs) } + quo2 <- teal.code::eval_code(quo, code = count_exprs, name = "groupvar counts") # add label and slice(1) as all patients in the same subgroup have same n_'s - chunk$push( - bquote({ - attr(counts[[.(get_n_name(groupby_vars))]], "label") <- "Count" # for plot - counts <- counts %>% - dplyr::group_by_at(.(as.vector(groupby_vars))) %>% - dplyr::slice(1) %>% - dplyr::ungroup() %>% - dplyr::select(.(as.vector(groupby_vars)), dplyr::starts_with("n_")) - }), - id = "add_label_n_group_by_call" + quo3 <- teal.code::eval_code( + quo2, + as.expression( + c( + bquote(attr(counts[[.(get_n_name(groupby_vars))]], "label") <- "Count"), + bquote( + counts <- counts %>% + dplyr::group_by_at(.(as.vector(groupby_vars))) %>% + dplyr::slice(1) %>% + dplyr::ungroup() %>% + dplyr::select(.(as.vector(groupby_vars)), dplyr::starts_with("n_")) + ) + ) + ), + name = "add_label_n_group_by_call" ) # dplyr::select loses labels - chunk$push( + teal.code::eval_code( + quo3, teal.transform::get_anl_relabel_call( - columns_source = merged_data()$columns_source, - datasets = sapply(datasets$datanames(), function(x) shiny::reactive(datasets$get_data(x, filtered = TRUE))), + columns_source = merge_inputs()$columns_source, + datasets = data, anl_name = "counts" ), - id = "get_anl_relabel_call" + name = "get_anl_relabel_call" ) - - teal.code::chunks_safe_eval(chunk) - chunk }) - plot_chunk <- shiny::reactive({ - chunk <- teal.code::chunks_deep_clone(count_chunk()) - + output_q <- shiny::reactive({ + req(count_q()) groupby_vars <- as.list(r_groupby_vars()) # so $ access works below - chunk$push( - substitute( - env = list(groupby_vars = paste(groupby_vars, collapse = ", ")), - plot_title <- sprintf( - "Number of patients (total N = %s) for each combination of (%s)", - nrow(ANL), - groupby_vars - ) - ), - id = "plot_title_call" + quo2 <- teal.code::eval_code(count_q(), substitute( + env = list(groupby_vars = paste(groupby_vars, collapse = ", ")), + plot_title <- sprintf( + "Number of patients (total N = %s) for each combination of (%s)", + nrow(ANL), + groupby_vars + ) + ), + name = "plot_title_call" ) y_lab <- substitute( @@ -459,41 +435,26 @@ srv_g_barchart_simple <- function(id, ggplot2_args = all_ggplot2_args ) - chunk$push(plot_call, id = "plot_call") + quo3 <- teal.code::eval_code(quo2, code = plot_call, name = "plot_call") - # explicitly calling print on the plot inside the chunk evaluates + # explicitly calling print on the plot inside the quosure evaluates # the ggplot call and therefore catches errors - chunk$push(quote(print(plot)), "print_plot_call") - - teal.code::chunks_safe_eval(chunk) - chunk - }) - - generate_code <- shiny::reactive({ - chunk <- plot_chunk() - teal.code::chunks_reset() - teal.code::chunks_push_chunks(chunk) # set session chunks for ShowRCode - - chunk + teal.code::eval_code(quo3, code = quote(print(plot)), name = "print_plot_call") }) - plot_r <- shiny::reactive({ - generate_code()$get("plot") - }) + plot_r <- shiny::reactive(output_q()[["plot"]]) - output$table <- shiny::renderTable({ - generate_code()$get("counts") - }) + output$table <- shiny::renderTable(output_q()[["counts"]]) # reactive vars # NULL: not present in UI, vs character(0): no selection # returns named vector of non-NULL variables to group by r_groupby_vars <- function() { - x_name <- if (is.null(x)) NULL else as.vector(merged_data()$columns_source$x) - fill_name <- if (is.null(fill)) NULL else as.vector(merged_data()$columns_source$fill) - x_facet_name <- if (is.null(x_facet)) NULL else as.vector(merged_data()$columns_source$x_facet) - y_facet_name <- if (is.null(y_facet)) NULL else as.vector(merged_data()$columns_source$y_facet) + x_name <- if (is.null(x)) NULL else as.vector(merge_inputs()$columns_source$x) + fill_name <- if (is.null(fill)) NULL else as.vector(merge_inputs()$columns_source$fill) + x_facet_name <- if (is.null(x_facet)) NULL else as.vector(merge_inputs()$columns_source$x_facet) + y_facet_name <- if (is.null(y_facet)) NULL else as.vector(merge_inputs()$columns_source$y_facet) # set to NULL when empty character if (identical(x_name, character(0))) x_name <- NULL @@ -523,11 +484,10 @@ srv_g_barchart_simple <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(x, fill, x_facet, y_facet)), - modal_title = "Bar Chart" + verbatim_content = reactive(teal.code::get_code(output_q())), + title = "Bar Chart" ) ### REPORTER @@ -536,19 +496,16 @@ srv_g_barchart_simple <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Barchart Plot") card$append_text("Barchart Plot", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) @@ -559,7 +516,7 @@ srv_g_barchart_simple <- function(id, -# Helper functions for chunks ---- +# Helper functions for quosure ---- #' `ggplot2` call to generate simple barchart #' @@ -740,20 +697,19 @@ get_n_name <- function(groupby_vars) { paste0("n_", paste(groupby_vars, collapse = "_")) } -# chunk that counts by specified group +# expression that counts by specified group # n_name: name of column to add counts to, by default determined from groupby_vars -count_by_group_chunk <- function(chunk, groupby_vars, n_name = NULL, data_name = "counts") { - groupby_vars <- as.vector(groupby_vars) # as.vector unnames +count_by_group_expr <- function(groupby_vars, data_name = "counts") { checkmate::assert_character(groupby_vars) - - n_name <- `if`(is.null(n_name), get_n_name(groupby_vars), n_name) - chunk$push( - bquote({ - counts <- .(as.symbol(data_name)) %>% - dplyr::group_by_at(.(groupby_vars)) %>% - dplyr::mutate(.(as.symbol(n_name)) := dplyr::n()) %>% - dplyr::ungroup() - }), - id = paste(c(groupby_vars, "counts_group_by_at_call"), collapse = "_") + n_name <- get_n_name(groupby_vars) + + parse( + text = sprintf( + "counts <- %s %%>%% dplyr::group_by(%s) %%>%% dplyr::mutate(%s = dplyr::n()) %%>%% dplyr::ungroup()", + data_name, + paste(groupby_vars, collapse = ","), + n_name + ), + keep.source = FALSE ) } diff --git a/R/tm_g_ci.R b/R/tm_g_ci.R index 34dfa45105..163e7be2f1 100644 --- a/R/tm_g_ci.R +++ b/R/tm_g_ci.R @@ -352,15 +352,16 @@ ui_g_ci <- function(id, ...) { # nolint selected = args$stat ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = args$pre_output, post_output = args$post_output ) } srv_g_ci <- function(id, # nolint - datasets, + data, reporter, + filter_panel_api, x_var, y_var, color, @@ -368,14 +369,21 @@ srv_g_ci <- function(id, # nolint plot_height, plot_width, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() + merged_data <- teal.transform::merge_expression_module( + datasets = data, + data_extract = list(x_var = x_var, y_var = y_var, color = color), + join_keys = attr(data, "join_keys") + ) - merged_data <- teal.transform::data_merge_module( - datasets = datasets, - data_extract = list(x_var = x_var, y_var = y_var, color = color) + merged_data_q <- reactive( + teal.code::eval_code( + object = teal.code::new_quosure(data), + code = as.expression(merged_data()$expr), + name = "merge expression" + ) ) validate_data <- shiny::reactive({ @@ -391,28 +399,38 @@ srv_g_ci <- function(id, # nolint "Select an analyzed value (y axis)." ) ) - teal::validate_has_data(merged_data()$data(), min_nrow = 2) + teal::validate_has_data(merged_data_q()[["ANL"]], min_nrow = 2) shiny::validate(shiny::need( input$conf_level >= 0 && input$conf_level <= 1, "Please choose a confidence level between 0 and 1" )) }) - list_calls <- shiny::reactive({ + + output_q <- shiny::reactive({ + validate_data() x <- merged_data()$columns_source$x_var y <- merged_data()$columns_source$y_var color <- merged_data()$columns_source$color - ggplot2_args$labs$title <- paste("Confidence Interval Plot by", datasets$get_varlabels(attr(x, "dataname"), x)) - ggplot2_args$labs$x <- datasets$get_varlabels(attr(x, "dataname"), x) + + x_label <- column_annotation_label(data[[attr(x, "dataname")]](), x) + y_label <- column_annotation_label(data[[attr(y, "dataname")]](), y) + color_label <- if (length(color)) { + column_annotation_label(data[[attr(color, "dataname")]](), color) + } else { + NULL + } + + ggplot2_args$labs$title <- paste("Confidence Interval Plot by", x_label) + ggplot2_args$labs$x <- x_label ggplot2_args$labs$y <- paste( merged_data()$filter_info$y_var[[1]]$selected[[1]], - datasets$get_varlabels(attr(y, "dataname"), y) + y_label ) - ggplot2_args$labs$color <- datasets$get_varlabels(attr(color, "dataname"), color) - ggplot2_args$labs$lty <- datasets$get_varlabels(attr(color, "dataname"), color) - ggplot2_args$labs$shape <- datasets$get_varlabels(attr(color, "dataname"), color) - - template_g_ci( + ggplot2_args$labs$color <- color_label + ggplot2_args$labs$lty <- color_label + ggplot2_args$labs$shape <- color_label + list_calls <- template_g_ci( dataname = "ANL", x_var = x, y_var = y, @@ -425,29 +443,15 @@ srv_g_ci <- function(id, # nolint conf_level = as.numeric(input$conf_level), ggplot2_args = ggplot2_args ) + teal.code::eval_code(merged_data_q(), list_calls, name = "plot_call") }) - eval_call <- shiny::reactive({ - validate_data() - teal.code::chunks_reset() - teal.code::chunks_push_data_merge(x = merged_data()) - teal.code::chunks_push( - expression = list_calls(), - id = "plot_call" - ) - }) + plot_r <- shiny::reactive(output_q()[["gg"]]) - plot_r <- shiny::reactive({ - eval_call() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("gg") - }) - - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(x_var, y_var, color)), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) pws <- teal.widgets::plot_with_settings_srv( @@ -464,19 +468,16 @@ srv_g_ci <- function(id, # nolint card$set_name("CI Plot") card$append_text("CI Plot", "header2") card$append_text("Confidence Interval Plot", "header3") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_forest_rsp.R b/R/tm_g_forest_rsp.R index 0aa0ef1494..ff8c89bd4d 100644 --- a/R/tm_g_forest_rsp.R +++ b/R/tm_g_forest_rsp.R @@ -447,15 +447,16 @@ ui_g_forest_rsp <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) } srv_g_forest_rsp <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -469,12 +470,9 @@ srv_g_forest_rsp <- function(id, label, default_responses, ggplot2_args) { - checkmate::assert_true(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - # Setup arm variable selection, default reference arms, and default # comparison arms for encoding panel arm_ref_comp_observer( @@ -482,8 +480,7 @@ srv_g_forest_rsp <- function(id, input, output, id_arm_var = extract_input("arm_var", parentname), - datasets = datasets, - dataname = parentname, + data = data[[parentname]], arm_ref_comp = arm_ref_comp, module = "tm_t_tte" ) @@ -496,30 +493,47 @@ srv_g_forest_rsp <- function(id, paramcd = paramcd, aval_var = aval_var ), - datasets = datasets + datasets = data, + join_keys = attr(data, "join_keys") ) - anl_merged <- teal.transform::data_merge_srv( + anl_merged <- teal.transform::merge_expression_srv( selector_list = anl_selectors, - datasets = datasets, - merge_function = "dplyr::inner_join" + datasets = data, + merge_function = "dplyr::inner_join", + join_keys = attr(data, "join_keys") ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(arm_var = arm_var, subgroup_var = subgroup_var, strata_var = strata_var), + join_keys = attr(data, "join_keys"), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + q <- teal.code::new_quosure(env = data) + q1 <- teal.code::eval_code(q, as.expression(anl_merged()$expr)) + teal.code::eval_code(q1, as.expression(adsl_merged()$expr)) + }) + shiny::observeEvent( eventExpr = c( input[[extract_input("aval_var", "ADRS")]], input[[extract_input("paramcd", paramcd$filter[[1]]$dataname, filter = TRUE)]] ), handlerExpr = { + req(anl_merged_q()) + anl <- anl_merged_q()[["ANL"]] aval_var <- anl_merged()$columns_source$aval_var + + paramcd_level <- unlist(anl_merged()$filter_info$paramcd[[1]]$selected) + if (length(paramcd_level) == 0) { + return(NULL) + } + sel_param <- if (is.list(default_responses)) { - default_responses[[input[[extract_input("paramcd", paramcd$filter[[1]]$dataname, filter = TRUE)]]]] + default_responses[[paramcd_level]] } else { default_responses } @@ -532,13 +546,13 @@ srv_g_forest_rsp <- function(id, character(0) } else { if ("levels" %in% names(sel_param)) { - if (length(intersect(unique(anl_merged()$data()[[aval_var]]), sel_param$levels)) > 1) { + if (length(intersect(unique(anl[[aval_var]]), sel_param$levels)) > 1) { sel_param$levels } else { - union(unique(anl_merged()$data()[[aval_var]]), sel_param$levels) + union(anl[[aval_var]], sel_param$levels) } } else { - unique(anl_merged()$data()[[aval_var]]) + unique(anl[[aval_var]]) } } shiny::updateSelectInput( @@ -551,8 +565,11 @@ srv_g_forest_rsp <- function(id, # Prepare the analysis environment (filter data, check data, populate envir). validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + req(anl_merged_q()) + q1 <- anl_merged_q() + adsl_filtered <- q1[[parentname]] + anl_filtered <- q1[[dataname]] + anl <- q1[["ANL"]] anl_m <- anl_merged() input_arm_var <- as.vector(anl_m$columns_source$arm_var) @@ -576,7 +593,7 @@ srv_g_forest_rsp <- function(id, do.call(what = "validate_standard_inputs", validate_args) - teal::validate_one_row_per_id(anl_m$data(), key = c("USUBJID", "STUDYID", input_paramcd)) + teal::validate_one_row_per_id(q1[["ANL"]], key = c("USUBJID", "STUDYID", input_paramcd)) if (length(input_subgroup_var) > 0) { shiny::validate( @@ -603,7 +620,7 @@ srv_g_forest_rsp <- function(id, lvls <- x$levels all(x$rsp %in% lvls) } else { - lvls <- unique(anl_merged()$data()[[input$`aval_var-dataset_ADRS_singleextract-select`]]) + lvls <- unique(anl[[input$`aval_var-dataset_ADRS_singleextract-select`]]) if ("rsp" %in% names(x)) { all(x$rsp %in% lvls) } else { @@ -642,24 +659,15 @@ srv_g_forest_rsp <- function(id, ) ) - validate_has_data(anl_m$data(), min_nrow = 1) + validate_has_data(q1[["ANL"]], min_nrow = 1) NULL }) # The R-code corresponding to the analysis. - plot_r <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - - teal.code::chunks_reset() + q1 <- anl_merged_q() anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - ANL <- teal.code::chunks_get_var("ANL") # nolint strata_var <- as.vector(anl_m$columns_source$strata_var) subgroup_var <- as.vector(anl_m$columns_source$subgroup_var) @@ -681,12 +689,12 @@ srv_g_forest_rsp <- function(id, col_symbol_size = `if`(input$fixed_symbol_size, NULL, 1), ggplot2_args = ggplot2_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("p") + teal.code::eval_code(q1, as.expression(my_calls), name = "g_forest_rsp call") }) + plot_r <- reactive(output_q()[["p"]]) + pws <- teal.widgets::plot_with_settings_srv( id = "myplot", plot_r = plot_r, @@ -694,13 +702,10 @@ srv_g_forest_rsp <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, paramcd, subgroup_var, strata_var) - ), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -709,19 +714,16 @@ srv_g_forest_rsp <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Forest Response Plot") card$append_text("Forest Response Plot", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_forest_tte.R b/R/tm_g_forest_tte.R index 4d4cbb7851..af080c2dcd 100644 --- a/R/tm_g_forest_tte.R +++ b/R/tm_g_forest_tte.R @@ -438,15 +438,16 @@ ui_g_forest_tte <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) } srv_g_forest_tte <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -460,12 +461,9 @@ srv_g_forest_tte <- function(id, plot_height, plot_width, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - # Setup arm variable selection, default reference arms, and default # comparison arms for encoding panel arm_ref_comp_observer( @@ -473,8 +471,7 @@ srv_g_forest_tte <- function(id, input, output, id_arm_var = extract_input("arm_var", parentname), - datasets = datasets, - dataname = parentname, + data = data[[parentname]], arm_ref_comp = arm_ref_comp, module = "tm_g_forest_tte" ) @@ -489,24 +486,35 @@ srv_g_forest_tte <- function(id, cnsr_var = cnsr_var, time_unit_var = time_unit_var ), - datasets = datasets + datasets = data, + join_keys = attr(data, "join_keys") ) - anl_merged <- teal.transform::data_merge_srv( + anl_merged <- teal.transform::merge_expression_srv( selector_list = anl_selectors, - datasets = datasets, + datasets = data, + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var, subgroup_var = subgroup_var, strata_var = strata_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + q <- teal.code::new_quosure(env = data) + q1 <- teal.code::eval_code(q, as.expression(anl_merged()$expr)) + teal.code::eval_code(q1, as.expression(adsl_merged()$expr)) + }) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + q1 <- anl_merged_q() + adsl_filtered <- q1[[parentname]] + anl_filtered <- q1[[dataname]] + anl <- q1[["ANL"]] anl_m <- anl_merged() input_arm_var <- as.vector(anl_m$columns_source$arm_var) @@ -560,7 +568,7 @@ srv_g_forest_tte <- function(id, )) shiny::validate(shiny::need( - length(anl_m$data()[[input_paramcd]]) > 0, + length(anl[[input_paramcd]]) > 0, "Value of the endpoint variable should not be empty." )) shiny::validate( @@ -574,19 +582,11 @@ srv_g_forest_tte <- function(id, }) # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() + q1 <- anl_merged_q() anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - ANL <- teal.code::chunks_get_var("ANL") # nolint strata_var <- as.vector(anl_m$columns_source$strata_var) subgroup_var <- as.vector(anl_m$columns_source$subgroup_var) @@ -609,15 +609,11 @@ srv_g_forest_tte <- function(id, time_unit_var = as.vector(anl_m$columns_source$time_unit_var), ggplot2_args = ggplot2_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(q1, as.expression(my_calls), name = "g_forest_tte call") }) # Outputs to render. - plot_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("p") - }) + plot_r <- shiny::reactive(output_q()[["p"]]) pws <- teal.widgets::plot_with_settings_srv( id = "myplot", @@ -626,14 +622,10 @@ srv_g_forest_tte <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, paramcd, subgroup_var, strata_var, aval_var, cnsr_var) - ), - modal_title = "R Code for the Current Time-to-Event Forest Plot", - code_header = "Time-to-Event Forest Plot" + verbatim_content = reactive(teal.code::get_code(output_q())), + title = "R Code for the Current Time-to-Event Forest Plot" ) ### REPORTER @@ -642,19 +634,16 @@ srv_g_forest_tte <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Forest Survival Plot") card$append_text("Forest Survival Plot", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_ipp.R b/R/tm_g_ipp.R index 970094a189..d1205b94ba 100644 --- a/R/tm_g_ipp.R +++ b/R/tm_g_ipp.R @@ -443,15 +443,16 @@ ui_g_ipp <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) } srv_g_ipp <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -465,14 +466,11 @@ srv_g_ipp <- function(id, plot_width, label, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged <- teal.transform::merge_expression_module( + datasets = data, data_extract = list( arm_var = arm_var, aval_var = aval_var, @@ -482,19 +480,28 @@ srv_g_ipp <- function(id, visit_var = visit_var, base_var = base_var ), - merge_function = "dplyr::inner_join" + merge_function = "dplyr::inner_join", + join_keys = attr(data, "join_keys") ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var, id_var = id_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + q <- teal.code::new_quosure(env = data) + q1 <- teal.code::eval_code(q, as.expression(anl_merged()$expr)) + teal.code::eval_code(q1, as.expression(adsl_merged()$expr)) + }) + # Prepare the analysis environment (filter data, check data, populate envir). validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + q1 <- anl_merged_q() + adsl_filtered <- q1[[parentname]] + anl_filtered <- q1[[dataname]] anl_m <- anl_merged() input_arm_var <- unlist(arm_var$filter)["vars_selected"] @@ -537,19 +544,12 @@ srv_g_ipp <- function(id, }) # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - - teal.code::chunks_reset() + q1 <- anl_merged_q() anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - ANL <- teal.code::chunks_get_var("ANL") # nolint + ANL <- q1[["ANL"]] # nolint teal::validate_has_data(ANL, 2) arm_var <- unlist(arm_var$filter)["vars_selected"] @@ -578,15 +578,11 @@ srv_g_ipp <- function(id, ggplot2_args = ggplot2_args, add_avalu = input$add_avalu ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(q1, as.expression(my_calls), name = "h_g_ipp call") }) # Outputs to render. - plot_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("plot") - }) + plot_r <- shiny::reactive(output_q()[["plot"]]) # Insert the plot into a plot with settings module from teal.widgets pws <- teal.widgets::plot_with_settings_srv( @@ -596,13 +592,10 @@ srv_g_ipp <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, aval_var, avalu_var, id_var, paramcd, base_var, visit_var) - ), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -611,19 +604,16 @@ srv_g_ipp <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Individual Patient Plot") card$append_text("Individual Patient Plot", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_km.R b/R/tm_g_km.R index 3bd3830829..1d0e69a8c0 100644 --- a/R/tm_g_km.R +++ b/R/tm_g_km.R @@ -130,7 +130,7 @@ template_g_km <- function(dataname = "ANL", graph_list, substitute( expr = { - result <- mapply( + plot_list <- mapply( df = split(anl, f = anl$facet_var), nrow = seq_along(levels(anl$facet_var)), FUN = function(df_i, nrow_i) { if (nrow(df_i) == 0) { @@ -176,8 +176,8 @@ template_g_km <- function(dataname = "ANL", }, SIMPLIFY = FALSE ) - km_grobs <- tern::stack_grobs(grobs = result) - km_grobs + plot <- tern::stack_grobs(grobs = plot_list) + plot }, env = list( font_size = font_size, @@ -201,7 +201,7 @@ template_g_km <- function(dataname = "ANL", graph_list, substitute( expr = { - result <- g_km( + plot <- g_km( df = anl, variables = variables, font_size = font_size, @@ -227,7 +227,7 @@ template_g_km <- function(dataname = "ANL", ci_ribbon = ci_ribbon, title = title, ) - result + plot }, env = list( font_size = font_size, @@ -572,7 +572,7 @@ ui_g_km <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -583,8 +583,9 @@ ui_g_km <- function(id, ...) { #' @noRd #' srv_g_km <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, paramcd, @@ -598,10 +599,9 @@ srv_g_km <- function(id, time_unit_var, plot_height, plot_width) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() # Setup arm variable selection, default reference arms and default # comparison arms for encoding panel @@ -610,15 +610,14 @@ srv_g_km <- function(id, input, output, id_arm_var = extract_input("arm_var", parentname), - datasets = datasets, - dataname = parentname, + data = data[[parentname]], arm_ref_comp = arm_ref_comp, module = "tm_t_tte", on_off = shiny::reactive(input$compare_arms) ) - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged <- teal.transform::merge_expression_module( + datasets = data, data_extract = list( aval_var = aval_var, cnsr_var = cnsr_var, @@ -628,12 +627,21 @@ srv_g_km <- function(id, facet_var = facet_var, time_unit_var = time_unit_var ), - merge_function = "dplyr::inner_join" + merge_function = "dplyr::inner_join", + join_keys = attr(data, "join_keys") ) + anl_merged_q <- reactive({ + teal.code::eval_code( + teal.code::new_quosure(data), + code = as.expression(anl_merged()$expr) + ) + }) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + q1 <- anl_merged_q() + adsl_filtered <- q1[[parentname]] + anl_filtered <- q1[[dataname]] anl_m <- anl_merged() input_arm_var <- as.vector(anl_m$columns_source$arm_var) @@ -695,16 +703,14 @@ srv_g_km <- function(id, NULL }) - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() + q1 <- anl_merged_q() anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - ANL <- teal.code::chunks_get_var("ANL") # nolint - teal::validate_has_data(ANL, 2) + anl <- q1[["ANL"]] # nolint + teal::validate_has_data(anl, 2) input_xticks <- gsub(";", ",", trimws(input$xticks)) %>% strsplit(",") %>% @@ -715,7 +721,7 @@ srv_g_km <- function(id, input_xticks <- NULL } - input_paramcd <- as.character(unique(anl_m$data()[[as.vector(anl_m$columns_source$paramcd)]])) + input_paramcd <- as.character(unique(anl[[as.vector(anl_m$columns_source$paramcd)]])) title <- paste("KM Plot of", input_paramcd) my_calls <- template_g_km( @@ -743,13 +749,10 @@ srv_g_km <- function(id, ci_ribbon = input$show_ci_ribbon, title = title ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(q1, as.expression(my_calls)) }) - plot_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - }) + plot_r <- shiny::reactive(output_q()[["plot"]]) # Insert the plot into a plot with settings module from teal.widgets pws <- teal.widgets::plot_with_settings_srv( @@ -759,13 +762,10 @@ srv_g_km <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, paramcd, strata_var, facet_var, aval_var, cnsr_var, time_unit_var) - ), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -775,19 +775,16 @@ srv_g_km <- function(id, card$set_name("Kaplan Meier Plot") card$append_text("Kaplan Meier Plot", "header2") card$append_text("Non-parametric method used to estimate the survival function from lifetime data", "header3") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_lineplot.R b/R/tm_g_lineplot.R index b704745d1b..51b4e28ccd 100644 --- a/R/tm_g_lineplot.R +++ b/R/tm_g_lineplot.R @@ -171,8 +171,8 @@ template_g_lineplot <- function(dataname = "ANL", graph_list, substitute( expr = { - result <- plot_call - result + plot <- plot_call + plot }, env = list(plot_call = plot_call) ) @@ -482,7 +482,7 @@ ui_g_lineplot <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -493,8 +493,9 @@ ui_g_lineplot <- function(id, ...) { #' @noRd #' srv_g_lineplot <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, paramcd, @@ -507,29 +508,32 @@ srv_g_lineplot <- function(id, plot_height, plot_width, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(x = x, y = y, strata = strata, paramcd = paramcd, y_unit = y_unit, param = param), + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(data) %>% teal.code::eval_code(as.expression(anl_merged_input()$expr)) + }) + + merged <- list(anl_input_r = anl_merged_input, anl_q_r = anl_merged_q) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - anl_m <- anl_merged() - input_strata <- as.vector(anl_m$columns_source$strata) - input_x_var <- as.vector(anl_m$columns_source$x) - input_y <- as.vector(anl_m$columns_source$y) + input_strata <- names(merged$anl_input_r()$columns_source$strata) + input_x_var <- names(merged$anl_input_r()$columns_source$x) + input_y <- names(merged$anl_input_r()$columns_source$y) input_param <- unlist(param$filter)["vars_selected"] - input_paramcd <- as.vector(anl_m$columns_source$paramcd) - input_y_unit <- as.vector(anl_m$columns_source$y_unit) + input_paramcd <- names(merged$anl_input_r()$columns_source$paramcd) + input_y_unit <- names(merged$anl_input_r()$columns_source$y_unit) # validate inputs validate_args <- list( @@ -564,29 +568,23 @@ srv_g_lineplot <- function(id, NULL }) - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - ANL <- teal.code::chunks_get_var("ANL") # nolint + ANL <- merged$anl_q_r()[["ANL"]] # nolint teal::validate_has_data(ANL, 2) whiskers_selected <- ifelse(input$whiskers == "Lower", 1, ifelse(input$whiskers == "Upper", 2, 1:2)) input_whiskers <- names(tern::s_summary(0)[[input$interval]][whiskers_selected]) input_interval <- input$interval - input_param <- as.character(unique(anl_m$data()[[as.vector(anl_m$columns_source$param)]])) + input_param <- as.character(unique(ANL[[names(merged$anl_input_r()$columns_source$param)[1]]])) my_calls <- template_g_lineplot( dataname = "ANL", - strata = as.vector(anl_m$columns_source$strata), - y = as.vector(anl_m$columns_source$y), - x = as.vector(anl_m$columns_source$x), - paramcd = as.vector(anl_m$columns_source$paramcd), - y_unit = as.vector(anl_m$columns_source$y_unit), + strata = names(merged$anl_input_r()$columns_source$strata), + y = names(merged$anl_input_r()$columns_source$y), + x = names(merged$anl_input_r()$columns_source$x), + paramcd = names(merged$anl_input_r()$columns_source$paramcd), + y_unit = names(merged$anl_input_r()$columns_source$y_unit), conf_level = as.numeric(input$conf_level), incl_screen = input$incl_screen, mid = input$mid, @@ -598,13 +596,10 @@ srv_g_lineplot <- function(id, table_font_size = input$table_font_size, ggplot2_args = ggplot2_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls)) }) - plot_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - }) + plot_r <- shiny::reactive(output_q()[["plot"]]) # Insert the plot into a plot with settings module from teal.widgets pws <- teal.widgets::plot_with_settings_srv( @@ -614,13 +609,10 @@ srv_g_lineplot <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(strata, paramcd, y, x, y_unit, param) - ), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -629,19 +621,16 @@ srv_g_lineplot <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Line Plot") card$append_text("Line Plot", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_pp_adverse_events.R b/R/tm_g_pp_adverse_events.R index 97993e5cb3..a936ed29c3 100644 --- a/R/tm_g_pp_adverse_events.R +++ b/R/tm_g_pp_adverse_events.R @@ -97,7 +97,7 @@ template_adverse_events <- function(dataname = "ANL", chart_list <- add_expr( list(), substitute( - expr = chart <- dataname %>% + expr = plot <- dataname %>% dplyr::select(aeterm, time, tox_grade, causality) %>% dplyr::mutate(ATOXGR = as.character(tox_grade)) %>% dplyr::arrange(dplyr::desc(ATOXGR)) %>% @@ -145,7 +145,7 @@ template_adverse_events <- function(dataname = "ANL", chart_list <- add_expr( expr_ls = chart_list, - new_expr = quote(print(chart)) + new_expr = quote(print(plot)) ) y$table <- bracket_expr(table_list) @@ -388,7 +388,7 @@ ui_g_adverse_events <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = ui_args$pre_output, post_output = ui_args$post_output ) @@ -396,7 +396,8 @@ ui_g_adverse_events <- function(id, ...) { srv_g_adverse_events <- function(id, - datasets, + data, + filter_panel_api, reporter, dataname, parentname, @@ -412,16 +413,13 @@ srv_g_adverse_events <- function(id, plot_width, label, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - patient_id <- shiny::reactive(input$patient_id) # Init - patient_data_base <- shiny::reactive(unique(datasets$get_data(parentname, filtered = TRUE)[[patient_col]])) + patient_data_base <- shiny::reactive(unique(data[[parentname]]()[[patient_col]])) teal.widgets::updateOptionalSelectInput( session, "patient_id", @@ -446,25 +444,32 @@ srv_g_adverse_events <- function(id, ) # Adverse events tab ---- - ae_merged_data <- teal.transform::data_merge_module( - datasets = datasets, - data_extract = list( - aeterm = aeterm, - tox_grade = tox_grade, - causality = causality, - outcome = outcome, - action = action, - time = time, - decod = decod - ) + anl_merged <- teal.transform::merge_expression_module( + datasets = data, + data_extract = Filter( + Negate(is.null), + list( + aeterm = aeterm, + tox_grade = tox_grade, + causality = causality, + outcome = outcome, + action = action, + time = time, + decod = decod + ) + ), + join_keys = attr(data, "join_keys") ) - calls <- shiny::reactive({ + anl_merged_q <- reactive(teal.code::eval_code(teal.code::new_quosure(data), as.expression(anl_merged()$expr))) + + outputs_q <- shiny::reactive({ shiny::validate(shiny::need(patient_id(), "Please select a patient.")) - teal::validate_has_data( - ae_merged_data()$data()[ae_merged_data()$data()[[patient_col]] == input$patient_id, ], - 1 - ) + anl_m <- anl_merged() + q1 <- anl_merged_q() + ANL <- q1[["ANL"]] # nolint + + teal::validate_has_data(ANL[ANL[[patient_col]] == input$patient_id, ], min_nrow = 1) shiny::validate( shiny::need( @@ -493,12 +498,8 @@ srv_g_adverse_events <- function(id, ) ) - stack <- teal.code::chunks_new() - stack$reset() - - teal.code::chunks_push_data_merge(ae_merged_data(), chunks = stack) - - stack$push( + q2 <- teal.code::eval_code( + q1, substitute( expr = ANL <- ANL[ANL[[patient_col]] == patient_id, ], # nolint env = list( @@ -506,7 +507,7 @@ srv_g_adverse_events <- function(id, patient_id = patient_id() ) ), - id = "filter_patient_id_call" + name = "filter_patient_id_call" ) @@ -524,29 +525,14 @@ srv_g_adverse_events <- function(id, ggplot2_args = ggplot2_args ) - lapply( - names(calls), - function(call_name) { - teal.code::chunks_push(expression = calls[[call_name]], id = paste0(call_name, "_call"), chunks = stack) - } - ) - teal.code::chunks_safe_eval(chunks = stack) - stack + teal.code::eval_code(q2, as.expression(calls)) }) output$table <- DT::renderDataTable( - expr = { - teal.code::chunks_reset() - teal.code::chunks_push_chunks(calls()) - teal.code::chunks_get_var("table") - }, + expr = outputs_q()[["table"]], options = list(pageLength = input$table_rows) ) - plot_r <- shiny::reactive({ - teal.code::chunks_reset() - teal.code::chunks_push_chunks(calls()) - teal.code::chunks_get_var("chart") - }) + plot_r <- shiny::reactive(outputs_q()[["plot"]]) pws <- teal.widgets::plot_with_settings_srv( id = "chart", @@ -555,13 +541,10 @@ srv_g_adverse_events <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list( - aeterm, tox_grade, causality, outcome, action, time, decod - )), - modal_title = label + verbatim_content = reactive(teal.code::get_code(outputs_q())), + title = label ) ### REPORTER @@ -570,19 +553,16 @@ srv_g_adverse_events <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Patient Profile Adverse Events Plot") card$append_text("Patient Profile Adverse Events Plot", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(outputs_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_pp_patient_timeline.R b/R/tm_g_pp_patient_timeline.R index 01e04057f5..d490ec8e93 100644 --- a/R/tm_g_pp_patient_timeline.R +++ b/R/tm_g_pp_patient_timeline.R @@ -683,7 +683,7 @@ ui_g_patient_timeline <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = ui_args$pre_output, post_output = ui_args$post_output ) @@ -691,8 +691,9 @@ ui_g_patient_timeline <- function(id, ...) { srv_g_patient_timeline <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname_adae, dataname_adcm, parentname, @@ -711,16 +712,13 @@ srv_g_patient_timeline <- function(id, plot_width, label, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - patient_id <- shiny::reactive(input$patient_id) # Init - patient_data_base <- shiny::reactive(unique(datasets$get_data(parentname, filtered = TRUE)[[patient_col]])) + patient_data_base <- shiny::reactive(unique(data[[parentname]]()[[patient_col]])) teal.widgets::updateOptionalSelectInput( session, "patient_id", @@ -745,8 +743,9 @@ srv_g_patient_timeline <- function(id, ) # Patient timeline tab ---- - p_timeline_merged_data <- teal.transform::data_merge_module( - datasets = datasets, + merge_input_r <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list( dsrelday_start = dsrelday_start, dsrelday_end = dsrelday_end, aerelday_start = aerelday_start, aerelday_end = aerelday_end, @@ -755,7 +754,12 @@ srv_g_patient_timeline <- function(id, ) ) - patient_timeline_calls <- shiny::reactive({ + merge_q_r <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(merge_input_r()$expr)) + }) + + output_q <- shiny::reactive({ shiny::validate(shiny::need(patient_id(), "Please select a patient.")) aeterm <- input[[extract_input("aeterm", dataname_adae)]] @@ -773,7 +777,7 @@ srv_g_patient_timeline <- function(id, ae_chart_vars_null <- any(vapply(list(aeterm, aetime_start, aetime_end), is.null, FUN.VALUE = logical(1))) ds_chart_vars_null <- any(vapply(list(cmdecod, dstime_start, dstime_end), is.null, FUN.VALUE = logical(1))) - p_timeline_data <- p_timeline_merged_data()$data() + p_timeline_data <- merge_q_r()[["ANL"]] # time variables can not be NA p_time_data_pat <- p_timeline_data[p_timeline_data[[patient_col]] == patient_id(), ] @@ -798,22 +802,22 @@ srv_g_patient_timeline <- function(id, # AENDY columns to data_merge_module call above. aerelday_start_name <- `if`( length(aerelday_start), - p_timeline_merged_data()$columns_source$aerelday_start[[1]], + merge_input_r()$columns_source$aerelday_start[[1]], aerelday_start ) aerelday_end_name <- `if`( length(aerelday_end), - p_timeline_merged_data()$columns_source$aerelday_end[[1]], + merge_input_r()$columns_source$aerelday_end[[1]], aerelday_end ) dsrelday_start_name <- `if`( length(dsrelday_start), - p_timeline_merged_data()$columns_source$dsrelday_start[[1]], + merge_input_r()$columns_source$dsrelday_start[[1]], dsrelday_start ) dsrelday_end_name <- `if`( length(dsrelday_end), - p_timeline_merged_data()$columns_source$dsrelday_end[[1]], + merge_input_r()$columns_source$dsrelday_end[[1]], dsrelday_end ) @@ -831,25 +835,6 @@ srv_g_patient_timeline <- function(id, ) ) - patient_timeline_stack <- teal.code::chunks_new() - time_line_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = patient_timeline_stack) - } - - teal.code::chunks_push_data_merge(p_timeline_merged_data(), chunks = patient_timeline_stack) - - time_line_stack_push( - expression = substitute( - expr = { - ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint - }, env = list( - patient_col = patient_col, - patient_id = patient_id() - ) - ), - id = "patient_id_filter_call" - ) - patient_timeline_calls <- template_patient_timeline( dataname = "ANL", aeterm = aeterm, @@ -867,22 +852,24 @@ srv_g_patient_timeline <- function(id, patient_id = patient_id(), ggplot2_args = ggplot2_args ) - # patient_timeline_calls is a list containing one object - mapply( - expression = patient_timeline_calls, - id = "patient_timeline_plot_call", - time_line_stack_push - ) - teal.code::chunks_safe_eval(chunks = patient_timeline_stack) - patient_timeline_stack - }) - plot_r <- shiny::reactive({ - teal.code::chunks_reset() - teal.code::chunks_push_chunks(patient_timeline_calls()) - teal.code::chunks_get_var("patient_timeline_plot") + teal.code::eval_code( + merge_q_r(), + substitute( + expr = { + ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint + }, env = list( + patient_col = patient_col, + patient_id = patient_id() + ) + ), + name = "patient_id_filter_call" + ) %>% + teal.code::eval_code(as.expression(patient_timeline_calls), name = "patient_timeline_plot_call") }) + plot_r <- shiny::reactive(output_q()[["patient_timeline_plot"]]) + pws <- teal.widgets::plot_with_settings_srv( id = "patient_timeline_plot", plot_r = plot_r, @@ -890,13 +877,10 @@ srv_g_patient_timeline <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list( - aeterm, aetime_start, aetime_end, dstime_start, dstime_end, cmdecod - )), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -905,19 +889,16 @@ srv_g_patient_timeline <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Patient Profile Timeline Plot") card$append_text("Patient Profile Timeline Plot", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_pp_therapy.R b/R/tm_g_pp_therapy.R index 426d5ef636..528025ccad 100644 --- a/R/tm_g_pp_therapy.R +++ b/R/tm_g_pp_therapy.R @@ -538,7 +538,7 @@ ui_g_therapy <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = ui_args$pre_output, post_output = ui_args$post_output ) @@ -546,8 +546,9 @@ ui_g_therapy <- function(id, ...) { srv_g_therapy <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, patient_col, @@ -565,16 +566,13 @@ srv_g_therapy <- function(id, plot_width, label, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - patient_id <- shiny::reactive(input$patient_id) # Init - patient_data_base <- shiny::reactive(unique(datasets$get_data(parentname, filtered = TRUE)[[patient_col]])) + patient_data_base <- shiny::reactive(unique(data[[parentname]]()[[patient_col]])) teal.widgets::updateOptionalSelectInput( session, "patient_id", choices = patient_data_base(), selected = patient_data_base()[1] @@ -597,8 +595,9 @@ srv_g_therapy <- function(id, ) # Therapy tab ---- - therapy_merged_data <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list( atirel = atirel, cmdecod = cmdecod, cmindc = cmindc, cmdose = cmdose, cmtrt = cmtrt, cmdosu = cmdosu, @@ -607,10 +606,16 @@ srv_g_therapy <- function(id, merge_function = "dplyr::left_join" ) - therapy_call <- shiny::reactive({ - shiny::validate(shiny::need(patient_id(), "Please select a patient.")) + anl_q_r <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) + }) - teal::validate_has_data(therapy_merged_data()$data(), 1) + merged <- list(anl_input_r = anl_merged_input, anl_q_r = anl_q_r) + + output_q <- shiny::reactive({ + shiny::validate(shiny::need(patient_id(), "Please select a patient.")) + teal::validate_has_data(merged$anl_q_r()[["ANL"]], 1) shiny::validate( shiny::need( @@ -654,29 +659,11 @@ srv_g_therapy <- function(id, "Please select CMENDY variable." ), shiny::need( - nrow(therapy_merged_data()$data()[input$patient_id == therapy_merged_data()$data()[patient_col], ]) > 0, + nrow(merged$anl_q_r()[["ANL"]][input$patient_id == merged$anl_q_r()[["ANL"]][, patient_col], ]) > 0, "Selected patient is not in dataset (either due to filtering or missing values). Consider relaxing filters." ) ) - therapy_stack <- teal.code::chunks_new() - therapy_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = therapy_stack) - } - teal.code::chunks_push_data_merge(therapy_merged_data(), chunks = therapy_stack) - - therapy_stack_push( - expression = substitute( - expr = { - ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint - }, env = list( - patient_col = patient_col, - patient_id = patient_id() - ) - ), - id = "patient_id_filter_call" - ) - my_calls <- template_therapy( dataname = "ANL", atirel = input[[extract_input("atirel", dataname)]], @@ -694,29 +681,29 @@ srv_g_therapy <- function(id, ggplot2_args = ggplot2_args ) - mapply( - expression = my_calls, - id = paste(names(my_calls), "call", sep = "_"), - therapy_stack_push - ) - teal.code::chunks_safe_eval(chunks = therapy_stack) - therapy_stack + teal.code::eval_code( + merged$anl_q_r(), + substitute( + expr = { + ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint + }, env = list( + patient_col = patient_col, + patient_id = patient_id() + ) + ), + name = "patient_id_filter_call" + ) %>% + teal.code::eval_code(as.expression(my_calls), name = "patient_call") }) output$therapy_table <- DT::renderDataTable( expr = { - teal.code::chunks_reset() - teal.code::chunks_push_chunks(therapy_call()) - teal.code::chunks_get_var("therapy_table") + output_q()[["therapy_table"]] }, options = list(pageLength = input$therapy_table_rows) ) - plot_r <- shiny::reactive({ - teal.code::chunks_reset() - teal.code::chunks_push_chunks(therapy_call()) - teal.code::chunks_get_var("therapy_plot") - }) + plot_r <- shiny::reactive(output_q()[["therapy_plot"]]) pws <- teal.widgets::plot_with_settings_srv( id = "therapy_plot", @@ -725,13 +712,10 @@ srv_g_therapy <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list( - atirel, cmdecod, cmindc, cmdose, cmtrt, cmdosu, cmdosfrq, cmroute, cmstdy, cmendy - )), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -740,19 +724,16 @@ srv_g_therapy <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Patient Profile Therapy Plot") card$append_text("Patient Profile Therapy Plot", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_g_pp_vitals.R b/R/tm_g_pp_vitals.R index 6e95d202f3..524ded5517 100644 --- a/R/tm_g_pp_vitals.R +++ b/R/tm_g_pp_vitals.R @@ -346,7 +346,7 @@ ui_g_vitals <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = ui_args$pre_output, post_output = ui_args$post_output ) @@ -354,8 +354,9 @@ ui_g_vitals <- function(id, ...) { srv_g_vitals <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, patient_col, @@ -367,16 +368,13 @@ srv_g_vitals <- function(id, plot_width, label, ggplot2_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - patient_id <- shiny::reactive(input$patient_id) # Init - patient_data_base <- shiny::reactive(unique(datasets$get_data(parentname, filtered = TRUE)[[patient_col]])) + patient_data_base <- shiny::reactive(unique(data[[parentname]]()[[patient_col]])) teal.widgets::updateOptionalSelectInput( session, "patient_id", @@ -401,14 +399,19 @@ srv_g_vitals <- function(id, ) # Vitals tab ---- - vitals_merged_data <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(paramcd = paramcd, xaxis = xaxis, aval = aval), merge_function = "dplyr::left_join" ) + anl_q_r <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) + }) - vitals_dat <- vitals_merged_data()$data() + merged <- list(anl_input_r = anl_merged_input, anl_q_r = anl_q_r) output$paramcd_levels <- shiny::renderUI({ paramcd_var <- input[[extract_input("paramcd", dataname)]] @@ -416,6 +419,7 @@ srv_g_vitals <- function(id, shiny::req(paramcd_var) shiny::req(input$patient_id) + vitals_dat <- merged$anl_q_r()[["ANL"]] vitals_dat_sub <- vitals_dat[vitals_dat[[patient_col]] == patient_id(), ] paramcd_col <- vitals_dat_sub[[paramcd_var]] paramcd_col_levels <- unique(paramcd_col) @@ -439,10 +443,9 @@ srv_g_vitals <- function(id, ) }) - vitals_call <- shiny::reactive({ + output_q <- shiny::reactive({ shiny::validate(shiny::need(patient_id(), "Please select a patient.")) - - teal::validate_has_data(vitals_merged_data()$data(), 1) + teal::validate_has_data(merged$anl_q_r()[["ANL"]], 1) shiny::validate( shiny::need( @@ -462,29 +465,11 @@ srv_g_vitals <- function(id, "Please select AVAL variable." ), shiny::need( - nrow(vitals_merged_data()$data()[input$patient_id == vitals_merged_data()$data()[patient_col], ]) > 0, + nrow(merged$anl_q_r()[["ANL"]][input$patient_id == merged$anl_q_r()[["ANL"]][, patient_col], ]) > 0, "Selected patient is not in dataset (either due to filtering or missing values). Consider relaxing filters." ) ) - vitals_stack <- teal.code::chunks_new() - vitals_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = vitals_stack) - } - teal.code::chunks_push_data_merge(vitals_merged_data(), chunks = vitals_stack) - - vitals_stack_push( - expression = substitute( - expr = { - ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint - }, env = list( - patient_col = patient_col, - patient_id = patient_id() - ) - ), - id = "patient_id_filter_call" - ) - my_calls <- template_vitals( dataname = "ANL", paramcd = input[[extract_input("paramcd", dataname)]], @@ -492,20 +477,26 @@ srv_g_vitals <- function(id, xaxis = input[[extract_input("xaxis", dataname)]], aval = input[[extract_input("aval", dataname)]], patient_id = patient_id(), - font_size = input$`font_size`, + font_size = input[["font_size"]], ggplot2_args = ggplot2_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), vitals_stack_push) - teal.code::chunks_safe_eval(chunks = vitals_stack) - vitals_stack + teal.code::eval_code( + merged$anl_q_r(), + substitute( + expr = { + ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint + }, env = list( + patient_col = patient_col, + patient_id = patient_id() + ) + ), + name = "patient_id_filter_call" + ) %>% + teal.code::eval_code(as.expression(my_calls), name = "patient_call") }) - plot_r <- shiny::reactive({ - teal.code::chunks_reset() - teal.code::chunks_push_chunks(vitals_call()) - teal.code::chunks_get_var("result_plot") - }) + plot_r <- shiny::reactive(output_q()[["result_plot"]]) pws <- teal.widgets::plot_with_settings_srv( id = "vitals_plot", @@ -514,11 +505,10 @@ srv_g_vitals <- function(id, width = plot_width ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(paramcd, param, aval, xaxis)), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -527,19 +517,16 @@ srv_g_vitals <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Patient Profile Vitals Plot") card$append_text("Patient Profile Vitals Plot", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Plot", "header3") card$append_plot(plot_r(), dim = pws$dim()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_abnormality.R b/R/tm_t_abnormality.R index 8645728183..763f7c1fc3 100644 --- a/R/tm_t_abnormality.R +++ b/R/tm_t_abnormality.R @@ -465,7 +465,7 @@ ui_t_abnormality <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -473,8 +473,9 @@ ui_t_abnormality <- function(id, ...) { #' @noRd srv_t_abnormality <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, abnormal, @@ -489,20 +490,9 @@ srv_t_abnormality <- function(id, label, na_level, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - # Update UI choices depending on selection of previous options - shiny::observeEvent(input$grade, { - anl <- datasets$get_data(dataname, filtered = FALSE) - - validate_has_elements(input$grade, "Please select a grade variable") - choices <- unique(anl[[input$grade]][!is.na(anl[[input$grade]])]) - }) - anl_selectors <- teal.transform::data_extract_multiple_srv( list( arm_var = arm_var, @@ -512,32 +502,44 @@ srv_t_abnormality <- function(id, baseline_var = baseline_var, treatment_flag_var = treatment_flag_var ), - datasets = datasets + datasets = data ) - - anl_merged <- teal.transform::data_merge_srv( + anl_merged_input <- teal.transform::merge_expression_srv( selector_list = anl_selectors, - datasets = datasets, + datasets = data, + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_id_var <- as.vector(anl_m$columns_source$id_var) - input_by_vars <- as.vector(anl_m$columns_source$by_vars) - input_grade <- as.vector(anl_m$columns_source$grade) - input_baseline_var <- as.vector(anl_m$columns_source$baseline_var) - input_treatment_flag_var <- as.vector(anl_m$columns_source$treatment_flag_var) + input_arm_var <- names(merged$anl_input_r()$columns_source$arm_var) + input_id_var <- names(merged$anl_input_r()$columns_source$id_var) + input_by_vars <- names(merged$anl_input_r()$columns_source$by_vars) + input_grade <- names(merged$anl_input_r()$columns_source$grade) + input_baseline_var <- names(merged$anl_input_r()$columns_source$baseline_var) + input_treatment_flag_var <- names(merged$anl_input_r()$columns_source$treatment_flag_var) shiny::validate( shiny::need(input_arm_var, "Please select a treatment variable."), @@ -558,21 +560,12 @@ srv_t_abnormality <- function(id, ) }) - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - by_vars_names <- anl_m$columns_source$by_vars + by_vars_names <- merged$anl_input_r()$columns_source$by_vars by_vars_labels <- as.character(sapply(by_vars_names, function(name) { - attributes(anl_m$data()[[name]])$label + attr(merged$anl_q_r()[["ANL"]][[name]], "label") })) tbl_title <- ifelse( @@ -580,16 +573,17 @@ srv_t_abnormality <- function(id, paste("Laboratory Abnormality summary by", by_vars_labels), paste(paste("Laboratory Abnormality summary by", paste(by_vars_labels, collapse = ", "))) ) + my_calls <- template_abnormality( parentname = "ANL_ADSL", dataname = "ANL", - arm_var = as.vector(anl_m$columns_source$arm_var), - by_vars = anl_m$columns_source$by_vars, - id_var = as.vector(anl_m$columns_source$id_var), + arm_var = as.vector(merged$anl_input_r()$columns_source$arm_var), + by_vars = merged$anl_input_r()$columns_source$by_vars, + id_var = as.vector(merged$anl_input_r()$columns_source$id_var), abnormal = abnormal, - grade = as.vector(anl_m$columns_source$grade), - baseline_var = as.vector(anl_m$columns_source$baseline_var), - treatment_flag_var = as.vector(anl_m$columns_source$treatment_flag_var), + grade = as.vector(merged$anl_input_r()$columns_source$grade), + baseline_var = as.vector(merged$anl_input_r()$columns_source$baseline_var), + treatment_flag_var = as.vector(merged$anl_input_r()$columns_source$treatment_flag_var), treatment_flag = input$treatment_flag, add_total = input$add_total, exclude_base_abn = input$exclude_base_abn, @@ -598,15 +592,12 @@ srv_t_abnormality <- function(id, basic_table_args = basic_table_args, tbl_title = tbl_title ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), name = "tm_t_abnormality call") }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", @@ -614,14 +605,10 @@ srv_t_abnormality <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, id_var, by_vars, grade) - ), - modal_title = "R Code for Abnormality Table", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -630,19 +617,16 @@ srv_t_abnormality <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Abnormality Summary Table") card$append_text("Abnormality Summary Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_abnormality_by_worst_grade.R b/R/tm_t_abnormality_by_worst_grade.R index 1b64b7652c..c1e116dd73 100644 --- a/R/tm_t_abnormality_by_worst_grade.R +++ b/R/tm_t_abnormality_by_worst_grade.R @@ -447,7 +447,7 @@ ui_t_abnormality_by_worst_grade <- function(id, ...) { # nolint ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -455,8 +455,9 @@ ui_t_abnormality_by_worst_grade <- function(id, ...) { # nolint #' @noRd srv_t_abnormality_by_worst_grade <- function(id, # nolint - datasets, + data, reporter, + filter_panel_api, dataname, parentname, id_var, @@ -469,14 +470,12 @@ srv_t_abnormality_by_worst_grade <- function(id, # nolint drop_arm_levels, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list( arm_var = arm_var, id_var = id_var, paramcd = paramcd, atoxgr_var = atoxgr_var, worst_high_flag_var = worst_high_flag_var, @@ -485,45 +484,61 @@ srv_t_abnormality_by_worst_grade <- function(id, # nolint merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() + anl <- merged$anl_q_r()[["ANL"]] - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_id_var <- as.vector(anl_m$columns_source$id_var) - input_paramcd_var <- as.vector(anl_m$columns_source$paramcd) - input_atoxgr <- as.vector(anl_m$columns_source$atoxgr_var) - input_worst_high_flag_var <- as.vector(anl_m$columns_source$worst_high_flag_var) - input_worst_low_flag_var <- as.vector(anl_m$columns_source$worst_low_flag_var) + input_arm_var <- names(merged$anl_input_r()$columns_source$arm_var) + input_id_var <- names(merged$anl_input_r()$columns_source$id_var) + input_paramcd_var <- names(merged$anl_input_r()$columns_source$paramcd) + input_atoxgr <- names(merged$anl_input_r()$columns_source$atoxgr_var) + input_worst_high_flag_var <- names(merged$anl_input_r()$columns_source$worst_high_flag_var) + input_worst_low_flag_var <- names(merged$anl_input_r()$columns_source$worst_low_flag_var) shiny::validate( shiny::need(input_arm_var, "Please select a treatment variable."), shiny::need(input_worst_high_flag_var, "Please select the Worst High Grade flag variable."), shiny::need(input_worst_low_flag_var, "Please select the Worst Low Grade flag variable."), shiny::need( - length(anl_m$data()[[input_paramcd_var]]) > 0, + length(merged$anl_q_r()[["ANL"]][[input_paramcd_var]]) > 0, "Please select at least one Laboratory parameter." ), shiny::need(input_atoxgr, "Please select Analysis Toxicity Grade variable."), shiny::need(input_id_var, "Please select a Subject Identifier."), shiny::need(input$worst_flag_indicator, "Please select the value indicating worst grade."), shiny::need( - all(as.character(unique(anl_m$data()[[input_atoxgr]])) %in% as.character(c(-4:4))), + all(as.character(unique(merged$anl_q_r()[["ANL"]][[input_atoxgr]])) %in% as.character(c(-4:4))), "All grade values should be within -4:4 range." ) ) shiny::validate( - shiny::need(is.factor(anl_m$data()[[input_arm_var]]), "Treatment variable should be a factor."), - shiny::need(is.factor(anl_m$data()[[input_paramcd_var]]), "Parameter variable should be a factor."), - shiny::need(is.factor(anl_m$data()[[input_atoxgr]]), "Grade variable should be a factor.") + shiny::need(is.factor(merged$anl_q_r()[["ANL"]][[input_arm_var]]), "Treatment variable should be a factor."), + shiny::need( + is.factor(merged$anl_q_r()[["ANL"]][[input_paramcd_var]]), + "Parameter variable should be a factor." + ), + shiny::need(is.factor(merged$anl_q_r()[["ANL"]][[input_atoxgr]]), "Grade variable should be a factor.") ) # validate inputs @@ -540,39 +555,31 @@ srv_t_abnormality_by_worst_grade <- function(id, # nolint ) }) - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() my_calls <- template_abnormality_by_worst_grade( parentname = "ANL_ADSL", dataname = "ANL", - arm_var = as.vector(anl_m$columns_source$arm_var), - id_var = as.vector(anl_m$columns_source$id_var), - paramcd = as.vector(anl_m$columns_source$paramcd), - atoxgr_var = as.vector(anl_m$columns_source$atoxgr_var), - worst_high_flag_var = as.vector(anl_m$columns_source$worst_high_flag_var), - worst_low_flag_var = as.vector(anl_m$columns_source$worst_low_flag_var), + arm_var = names(merged$anl_input_r()$columns_source$arm_var), + id_var = names(merged$anl_input_r()$columns_source$id_var), + paramcd = names(merged$anl_input_r()$columns_source$paramcd), + atoxgr_var = names(merged$anl_input_r()$columns_source$atoxgr_var), + worst_high_flag_var = names(merged$anl_input_r()$columns_source$worst_high_flag_var), + worst_low_flag_var = names(merged$anl_input_r()$columns_source$worst_low_flag_var), worst_flag_indicator = input$worst_flag_indicator, add_total = input$add_total, drop_arm_levels = input$drop_arm_levels, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), + name = "tm_t_abnormality_by_worst_grade call" + ) }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", @@ -580,17 +587,10 @@ srv_t_abnormality_by_worst_grade <- function(id, # nolint ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list( - arm_var, id_var, paramcd, - atoxgr_var, worst_high_flag_var, worst_low_flag_var - ) - ), - modal_title = "R Code for Grade Laboratory Abnormalities", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -600,19 +600,16 @@ srv_t_abnormality_by_worst_grade <- function(id, # nolint card$set_name("Laboratory Test Results Table") card$append_text("Laboratory Test Results Table", "header2") card$append_text("Laboratory test results with highest grade post-baseline Table", "header3") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_ancova.R b/R/tm_t_ancova.R index fa8b7b7efa..ab93be19b7 100644 --- a/R/tm_t_ancova.R +++ b/R/tm_t_ancova.R @@ -510,7 +510,7 @@ ui_ancova <- function(id, ...) { fixed = a$conf_level$fixed ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -518,8 +518,9 @@ ui_ancova <- function(id, ...) { #' @noRd srv_ancova <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -530,12 +531,9 @@ srv_ancova <- function(id, avisit, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - # Setup arm variable selection, default reference arms, and default # comparison arms for encoding panel. arm_ref_comp_observer( @@ -543,14 +541,13 @@ srv_ancova <- function(id, input, output, id_arm_var = extract_input("arm_var", parentname), - datasets = datasets, - dataname = parentname, + data = data[[parentname]], arm_ref_comp = arm_ref_comp, module = "tm_ancova" ) - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, data_extract = list( arm_var = arm_var, aval_var = aval_var, @@ -558,24 +555,37 @@ srv_ancova <- function(id, avisit = avisit, paramcd = paramcd ), - merge_function = "dplyr::inner_join" + merge_function = "dplyr::inner_join", + join_keys = attr(data, "join_keys") ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(arm_var = arm_var), - anl_name = "ANL_ADSL" + anl_name = "ANL_ADSL", + join_keys = attr(data, "join_keys") + ) + + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q ) # Prepare the analysis environment (filter data, check data, populate envir). validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_aval_var <- as.vector(anl_m$columns_source$aval_var) - input_cov_var <- as.vector(anl_m$columns_source$cov_var) + input_arm_var <- as.vector(merged$anl_input_r()$columns_source$arm_var) + input_aval_var <- as.vector(merged$anl_input_r()$columns_source$aval_var) + input_cov_var <- as.vector(merged$anl_input_r()$columns_source$cov_var) input_avisit <- unlist(avisit$filter)["vars_selected"] input_paramcd <- unlist(paramcd$filter)["vars_selected"] @@ -604,11 +614,11 @@ srv_ancova <- function(id, )) # check that there is at least one record with no missing data shiny::validate(shiny::need( - !all(is.na(anl_m$data()[[input_aval_var]])), + !all(is.na(merged$anl_q_r()[["ANL"]][[input_aval_var]])), "ANCOVA table cannot be calculated as all values are missing." )) # check that for each visit there is at least one record with no missing data - all_NA_dataset <- anl_m$data() %>% # nolint + all_NA_dataset <- merged$anl_q_r()[["ANL"]] %>% # nolint dplyr::group_by(dplyr::across(dplyr::all_of(c(input_avisit, input_arm_var)))) %>% dplyr::summarize(all_NA = all(is.na(.data[[input_aval_var]]))) shiny::validate(shiny::need( @@ -642,35 +652,26 @@ srv_ancova <- function(id, }) # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_table <- shiny::reactive({ validate_checks() + ANL <- merged$anl_q_r()[["ANL"]] # nolint - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - ANL <- teal.code::chunks_get_var("ANL") # nolint label_paramcd <- get_paramcd_label(ANL, paramcd) - input_aval <- as.vector(anl_m$columns_source$aval_var) - label_aval <- if (length(input_aval) != 0) attributes(anl_m$data()[[input_aval]])$label else NULL + input_aval <- as.vector(merged$anl_input_r()$columns_source$aval_var) + label_aval <- if (length(input_aval) != 0) attributes(ANL[[input_aval]])$label else NULL paramcd_levels <- unique(ANL[[unlist(paramcd$filter)["vars_selected"]]]) visit_levels <- unique(ANL[[unlist(avisit$filter)["vars_selected"]]]) my_calls <- template_ancova( parentname = "ANL_ADSL", dataname = "ANL", - arm_var = as.vector(anl_m$columns_source$arm_var), + arm_var = as.vector(merged$anl_input_r()$columns_source$arm_var), ref_arm = unlist(input$buckets$Ref), comp_arm = unlist(input$buckets$Comp), combine_comp_arms = input$combine_comp_arms, - aval_var = as.vector(anl_m$columns_source$aval_var), + aval_var = as.vector(merged$anl_input_r()$columns_source$aval_var), label_aval = label_aval, - cov_var = as.vector(anl_m$columns_source$cov_var), + cov_var = as.vector(merged$anl_input_r()$columns_source$cov_var), paramcd_levels = paramcd_levels, paramcd_var = unlist(paramcd$filter)["vars_selected"], label_paramcd = label_paramcd, @@ -679,14 +680,12 @@ srv_ancova <- function(id, conf_level = as.numeric(input$conf_level), basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), name = "tm_t_ancova call") }) # Output to render. table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") + output_table()[["result"]] }) teal.widgets::table_with_settings_srv( @@ -695,13 +694,10 @@ srv_ancova <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, aval_var, cov_var, avisit, paramcd) - ), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_table())), + title = label ) ### REPORTER @@ -711,19 +707,16 @@ srv_ancova <- function(id, card$set_name("ANCOVA") card$append_text("ANCOVA", "header2") card$append_text("Analysis of Covariance", "header3") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_table()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_binary_outcome.R b/R/tm_t_binary_outcome.R index 611607c141..4eaf73e3f1 100644 --- a/R/tm_t_binary_outcome.R +++ b/R/tm_t_binary_outcome.R @@ -698,7 +698,7 @@ ui_t_binary_outcome <- function(id, ...) { is_single_dataset = is_single_dataset_value ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -706,8 +706,9 @@ ui_t_binary_outcome <- function(id, ...) { #' @noRd srv_t_binary_outcome <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, paramcd, @@ -720,12 +721,9 @@ srv_t_binary_outcome <- function(id, default_responses, rsp_table, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - # Setup arm variable selection, default reference arms, and default # comparison arms for encoding panel arm_ref_comp_observer( @@ -733,31 +731,39 @@ srv_t_binary_outcome <- function(id, input, output, id_arm_var = extract_input("arm_var", parentname), - datasets = datasets, - dataname = parentname, + data = data[[parentname]], arm_ref_comp = arm_ref_comp, module = "tm_t_tte", on_off = shiny::reactive(input$compare_arms) ) - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(arm_var = arm_var, paramcd = paramcd, strata_var = strata_var, aval_var = aval_var), - merge_function = "dplyr::inner_join" + merge_function = "dplyr::inner_join", + join_keys = attr(data, "join_keys") ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(arm_var = arm_var, strata_var = strata_var), + join_keys = attr(data, "join_keys"), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + q <- teal.code::new_quosure(env = data) + q1 <- teal.code::eval_code(q, as.expression(anl_merged()$expr)) + teal.code::eval_code(q1, as.expression(adsl_merged()$expr)) + }) + shiny::observeEvent( c( input[[extract_input("aval_var", "ADRS")]], input[[extract_input("paramcd", paramcd$filter[[1]]$dataname, filter = TRUE)]] ), handlerExpr = { + anl <- anl_merged_q()[["ANL"]] aval_var <- anl_merged()$columns_source$aval_var sel_param <- if (is.list(default_responses)) { default_responses[[input[[extract_input("paramcd", paramcd$filter[[1]]$dataname, filter = TRUE)]]]] @@ -773,13 +779,13 @@ srv_t_binary_outcome <- function(id, character(0) } else { if ("levels" %in% names(sel_param)) { - if (length(intersect(unique(anl_merged()$data()[[aval_var]]), sel_param$levels)) > 1) { + if (length(intersect(unique(anl[[aval_var]]), sel_param$levels)) > 1) { sel_param$levels } else { - union(unique(anl_merged()$data()[[aval_var]]), sel_param$levels) + union(unique(anl[[aval_var]]), sel_param$levels) } } else { - unique(anl_merged()$data()[[aval_var]]) + unique(anl[[aval_var]]) } } shiny::updateSelectInput( @@ -791,8 +797,10 @@ srv_t_binary_outcome <- function(id, ) validate_check <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + q1 <- anl_merged_q() + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() + anl <- q1[["ANL"]] anl_m <- anl_merged() input_arm_var <- as.vector(anl_m$columns_source$arm_var) @@ -820,14 +828,14 @@ srv_t_binary_outcome <- function(id, do.call(what = "validate_standard_inputs", validate_args) - teal::validate_one_row_per_id(anl_m$data(), key = c("USUBJID", "STUDYID", input_paramcd)) + teal::validate_one_row_per_id(anl, key = c("USUBJID", "STUDYID", input_paramcd)) shiny::validate( if (length(input_strata_var) >= 1L) { shiny::need( sum( vapply( - anl_m$data()[input_strata_var], + anl[input_strata_var], FUN = function(x) { length(unique(x)) > 1 }, @@ -844,9 +852,9 @@ srv_t_binary_outcome <- function(id, shiny::need( sum( vapply( - anl_m$data()[input_strata_var], + anl[input_strata_var], FUN = function(strata) { - tab <- base::table(strata, anl_m$data()[[input_arm_var]]) + tab <- base::table(strata, anl[[input_arm_var]]) tab_logic <- tab != 0L sum(apply(tab_logic, 1, sum) == ncol(tab_logic)) >= 2 }, @@ -883,26 +891,20 @@ srv_t_binary_outcome <- function(id, NULL }) - call_preparation <- shiny::reactive({ + output_table <- shiny::reactive({ validate_check() - teal.code::chunks_reset() + q1 <- anl_merged_q() anl_m <- anl_merged() - input_aval_var <- as.vector(anl_m$columns_source$aval_var) - shiny::req(input$responders %in% anl_m$data()[[input_aval_var]]) - - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() + anl <- q1[["ANL"]] - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() + input_aval_var <- as.vector(anl_m$columns_source$aval_var) + shiny::req(input$responders %in% anl[[input_aval_var]]) - anl <- teal.code::chunks_get_var("ANL") # nolint input_strata_var <- as.vector(anl_m$columns_source$strata_var) input_paramcd <- unlist(anl_m$filter_info$paramcd)["selected"] - responder_val_levels <- as.character(unique(anl_merged()$data()[[input_aval_var]])) + responder_val_levels <- as.character(unique(anl[[input_aval_var]])) final_responder <- if (is.list(default_responses)) { default_responses[[input_paramcd]][["levels"]] } else { @@ -942,15 +944,12 @@ srv_t_binary_outcome <- function(id, add_total = input$add_total, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + + teal.code::eval_code(q1, as.expression(my_calls), name = "tm_t_binary_outcome call") }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_table()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", @@ -958,14 +957,12 @@ srv_t_binary_outcome <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, paramcd, aval_var, strata_var) - ), - modal_title = "Binary Outcome", - code_header = label + verbatim_content = reactive({ + teal.code::get_code(output_table()) + }), + title = label ) ### REPORTER @@ -974,19 +971,16 @@ srv_t_binary_outcome <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Binary Outcome Table") card$append_text("Binary Outcome Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_table()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_coxreg.R b/R/tm_t_coxreg.R index 5a2984fdc4..a06598ccb4 100644 --- a/R/tm_t_coxreg.R +++ b/R/tm_t_coxreg.R @@ -689,7 +689,7 @@ ui_t_coxreg <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -697,8 +697,9 @@ ui_t_coxreg <- function(id, ...) { #' @noRd srv_t_coxreg <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -710,26 +711,23 @@ srv_t_coxreg <- function(id, arm_ref_comp, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - # Observer to update reference and comparison arm input options. arm_ref_comp_observer( session, input, output, id_arm_var = extract_input("arm_var", parentname), - datasets = datasets, - dataname = parentname, + data = data[[parentname]], arm_ref_comp = arm_ref_comp, module = "tm_t_coxreg" ) - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list( arm_var = arm_var, paramcd = paramcd, @@ -741,15 +739,25 @@ srv_t_coxreg <- function(id, merge_function = "dplyr::inner_join" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + anl_q_r = anl_merged_q + ) + ## render conditional strata levels input UI ---- - open_textinput <- function(x, anl) { + open_textinput <- function(x, dataset) { # For every numeric covariate, the numeric level for the Hazard Ration # estimation is proposed only if the covariate is included in the model: # for this purpose, a function and a UI-rendered output. shiny::textInput( session$ns(paste0("interact_", x)), label = paste("Hazard Ratios for", x, "at (comma delimited):"), - value = as.character(stats::median(anl$data()[[x]])) + value = as.character(stats::median(dataset[[x]])) ) } @@ -757,32 +765,29 @@ srv_t_coxreg <- function(id, # exclude cases when increments are not necessary and # finally accessing the UI-rendering function defined above. if (!is.null(input$interactions) && input$interactions) { - anl_m <- anl_merged() - input_cov_var <- as.vector(anl_m$columns_source$cov_var) - - anl <- datasets$get_data(dataname, filtered = FALSE) - cov_is_numeric <- vapply(anl[input_cov_var], is.numeric, logical(1)) + input_cov_var <- as.vector(merged$anl_input_r()$columns_source$cov_var) + dataset <- merged$anl_g_r()[[dataname]] + cov_is_numeric <- vapply(dataset[input_cov_var], is.numeric, logical(1)) interaction_var <- input_cov_var[cov_is_numeric] if (length(interaction_var) > 0 && length(input_cov_var) > 0) { - lapply(interaction_var, open_textinput, anl = anl_m) + lapply(interaction_var, open_textinput, dataset = dataset) } } }) ## Prepare the call evaluation environment ---- validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) - - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_strata_var <- as.vector(anl_m$columns_source$strata_var) - input_aval_var <- as.vector(anl_m$columns_source$aval_var) - input_cnsr_var <- as.vector(anl_m$columns_source$cnsr_var) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() + + input_arm_var <- as.vector(merged$anl_input_r()$columns_source$arm_var) + input_strata_var <- as.vector(merged$anl_input_r()$columns_source$strata_var) + input_aval_var <- as.vector(merged$anl_input_r()$columns_source$aval_var) + input_cnsr_var <- as.vector(merged$anl_input_r()$columns_source$cnsr_var) input_paramcd <- unlist(paramcd$filter)["vars_selected"] - input_cov_var <- as.vector(anl_m$columns_source$cov_var) - anl <- datasets$get_data(dataname, filtered = FALSE) - cov_is_numeric <- vapply(anl[input_cov_var], is.numeric, logical(1)) + input_cov_var <- as.vector(merged$anl_input_r()$columns_source$cov_var) + + cov_is_numeric <- vapply(anl_filtered[input_cov_var], is.numeric, logical(1)) interaction_var <- input_cov_var[cov_is_numeric] # validate inputs @@ -825,7 +830,7 @@ srv_t_coxreg <- function(id, do.call(what = "validate_standard_inputs", validate_args) - arm_n <- base::table(anl_m$data()[[input_arm_var]]) + arm_n <- base::table(anl_filtered[[input_arm_var]]) anl_arm_n <- if (input$combine_comp_arms) { c(sum(arm_n[unlist(input$buckets$Ref)]), sum(arm_n[unlist(input$buckets$Comp)])) } else { @@ -873,7 +878,7 @@ srv_t_coxreg <- function(id, # validate covariate has at least two levels shiny::validate( shiny::need( - all(vapply(anl_m$data()[input_cov_var], FUN = function(x) { + all(vapply(anl_filtered[input_cov_var], FUN = function(x) { length(unique(x)) > 1 }, logical(1))), "All covariate needs to have at least two levels" @@ -884,10 +889,8 @@ srv_t_coxreg <- function(id, }) at <- shiny::reactive({ - anl_m <- anl_merged() - input_cov_var <- as.vector(anl_m$columns_source$cov_var) - anl <- datasets$get_data(dataname, filtered = FALSE) - cov_is_numeric <- vapply(anl[input_cov_var], is.numeric, logical(1)) + input_cov_var <- as.vector(merged$anl_input_r()$columns_source$cov_var) + cov_is_numeric <- vapply(anl_filtered()[input_cov_var], is.numeric, logical(1)) interaction_var <- input_cov_var[cov_is_numeric] if (length(interaction_var) > 0 && length(input_cov_var) > 0) { res <- lapply( @@ -961,15 +964,10 @@ srv_t_coxreg <- function(id, } ## generate table call with template and render table ---- - table_r <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - ANL <- teal.code::chunks_get_var("ANL") # nolint + ANL <- merged$anl_q_r()[["ANL"]] # nolint paramcd <- as.character(unique(ANL[[unlist(paramcd$filter)["vars_selected"]]])) multivariate <- input$type == "Multivariate" @@ -979,62 +977,62 @@ srv_t_coxreg <- function(id, user_table = basic_table_args, module_table = teal.widgets::basic_table_args(title = main_title) ) - expr <- call_template(unlist(input$buckets$Comp), anl_m, paramcd, multivariate, all_basic_table_args) - mapply( - expression = expr, - id = paste(names(expr), "call", sep = "_"), - teal.code::chunks_push + expr <- call_template( + unlist(input$buckets$Comp), merged$anl_input_r(), + paramcd, multivariate, all_basic_table_args ) - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") + teal.code::eval_code(merged$anl_q_r(), as.expression(expr), name = "call") } else { main_title <- paste0("Cox Regression for ", paramcd) all_basic_table_args <- teal.widgets::resolve_basic_table_args( user_table = basic_table_args, module_table = teal.widgets::basic_table_args(title = main_title) ) - teal.code::chunks_push(expression = quote(result <- list()), id = "result_initiation_call") - lapply(unlist(input$buckets$Comp), function(x) { - expr <- call_template(x, anl_m, paramcd, multivariate, NULL) - mapply(expression = expr, id = paste(names(expr), "call", sep = "_"), teal.code::chunks_push) - }) - teal.code::chunks_push( - expression = substitute( - expr = { - final_table <- rtables::rbindl_rtables(result, check_headers = TRUE) - rtables::main_title(final_table) <- title - rtables::main_footer(final_table) <- footer - rtables::prov_footer(final_table) <- p_footer - rtables::subtitles(final_table) <- subtitle - final_table - }, - env = list( - title = all_basic_table_args$title, - footer = `if`(is.null(all_basic_table_args$main_footer), "", all_basic_table_args$main_footer), - p_footer = `if`(is.null(all_basic_table_args$prov_footer), "", all_basic_table_args$prov_footer), - subtitle = `if`(is.null(all_basic_table_args$subtitles), "", all_basic_table_args$subtitles) - ) - ), - id = "rbindl_rtables_call" - ) - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("final_table") + + merged$anl_q_r() %>% + teal.code::eval_code(quote(result <- list()), name = "result_initiation_call") %>% + teal.code::eval_code( + as.expression(lapply( + unlist(input$buckets$Comp), + function(x) { + call_template(x, merged$anl_input_r(), paramcd, multivariate, NULL) + } + )), + "Model fitting and table generation" + ) %>% + teal.code::eval_code( + substitute( + expr = { + result <- rtables::rbindl_rtables(result, check_headers = TRUE) + rtables::main_title(result) <- title + rtables::main_footer(result) <- footer + rtables::prov_footer(result) <- p_footer + rtables::subtitles(result) <- subtitle + result + }, + env = list( + title = all_basic_table_args$title, + footer = `if`(is.null(all_basic_table_args$main_footer), "", all_basic_table_args$main_footer), + p_footer = `if`(is.null(all_basic_table_args$prov_footer), "", all_basic_table_args$prov_footer), + subtitle = `if`(is.null(all_basic_table_args$subtitles), "", all_basic_table_args$subtitles) + ) + ), + name = "rbindl_rtables_call" + ) } }) + table_r <- shiny::reactive(output_q()[["result"]]) + teal.widgets::table_with_settings_srv( id = "table", table_r = table_r ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, paramcd, strata_var, aval_var, cnsr_var, cov_var) - ), - modal_title = "R Code for the Current (Multi-variable) Cox proportional hazard regression model", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = "R Code for the Current (Multi-variable) Cox proportional hazard regression model" ) ### REPORTER @@ -1043,19 +1041,16 @@ srv_t_coxreg <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Cox Regression Table") card$append_text("Cox Regression Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_events.R b/R/tm_t_events.R index f2eeec2d9b..a22d8dcc7b 100644 --- a/R/tm_t_events.R +++ b/R/tm_t_events.R @@ -127,11 +127,11 @@ template_events <- function(dataname, # Start layout steps. layout_list <- list() - basic_title <- if (is.null(hlt) & !is.null(llt)) { + basic_title <- if (is.null(hlt) && !is.null(llt)) { paste0("Event Summary by Term : ", label_llt) - } else if (!is.null(hlt) & is.null(llt)) { + } else if (!is.null(hlt) && is.null(llt)) { paste0("Event Summary by Term : ", label_hlt) - } else if (!is.null(hlt) & !is.null(llt)) { + } else if (!is.null(hlt) && !is.null(llt)) { paste0("Event Summary by Term : ", label_hlt, " and ", label_llt) } else { "Event Summary by Term" @@ -613,7 +613,7 @@ ui_t_events_byterm <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -621,7 +621,8 @@ ui_t_events_byterm <- function(id, ...) { #' @noRd srv_t_events_byterm <- function(id, - datasets, + data, + filter_panel_api, reporter, dataname, parentname, @@ -632,37 +633,49 @@ srv_t_events_byterm <- function(id, drop_arm_levels, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - anl_selectors <- teal.transform::data_extract_multiple_srv( - list(arm_var = arm_var, hlt = hlt, llt = llt), - datasets = datasets + data_extract = list(arm_var = arm_var, hlt = hlt, llt = llt), + datasets = data, + join_keys = attr(data, "join_keys") ) - anl_merged <- teal.transform::data_merge_srv( + anl_merged_input <- teal.transform::merge_expression_srv( selector_list = anl_selectors, - datasets = datasets, - merge_function = "dplyr::inner_join" + datasets = data, + merge_function = "dplyr::inner_join", + join_keys = attr(data, "join_keys") ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(arm_var = arm_var), - anl_name = "ANL_ADSL" + anl_name = "ANL_ADSL", + join_keys = attr(data, "join_keys") + ) + + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q ) validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) + input_arm_var <- as.vector(merged$anl_input_r()$columns_source$arm_var) input_level_term <- c( - as.vector(anl_m$columns_source$hlt), - as.vector(anl_m$columns_source$llt) + as.vector(merged$anl_input_r()$columns_source$hlt), + as.vector(merged$anl_input_r()$columns_source$llt) ) shiny::validate( @@ -706,27 +719,19 @@ srv_t_events_byterm <- function(id, }) # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_table <- shiny::reactive({ validate_checks() + ANL <- merged$anl_q_r()[["ANL"]] # nolint - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - input_hlt <- as.vector(anl_m$columns_source$hlt) - input_llt <- as.vector(anl_m$columns_source$llt) - label_hlt <- if (length(input_hlt) != 0) attributes(anl_m$data()[[input_hlt]])$label else NULL - label_llt <- if (length(input_llt) != 0) attributes(anl_m$data()[[input_llt]])$label else NULL + input_hlt <- as.vector(merged$anl_input_r()$columns_source$hlt) + input_llt <- as.vector(merged$anl_input_r()$columns_source$llt) + label_hlt <- if (length(input_hlt) != 0) attributes(ANL[[input_hlt]])$label else NULL + label_llt <- if (length(input_llt) != 0) attributes(ANL[[input_llt]])$label else NULL my_calls <- template_events( dataname = "ANL", parentname = "ANL_ADSL", - arm_var = as.vector(anl_m$columns_source$arm_var), + arm_var = as.vector(merged$anl_input_r()$columns_source$arm_var), hlt = if (length(input_hlt) != 0) input_hlt else NULL, llt = if (length(input_llt) != 0) input_llt else NULL, label_hlt = label_hlt, @@ -739,14 +744,13 @@ srv_t_events_byterm <- function(id, drop_arm_levels = input$drop_arm_levels, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), name = "tm_t_events call") }) # Outputs to render. table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("pruned_and_sorted_result") + output_table()[["pruned_and_sorted_result"]] }) teal.widgets::table_with_settings_srv( @@ -755,12 +759,10 @@ srv_t_events_byterm <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(arm_var, hlt, llt)), - modal_title = "Event Table", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_table())), + title = label ) ### REPORTER @@ -769,19 +771,16 @@ srv_t_events_byterm <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Events by Term Table") card$append_text("Events by Term Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_table()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_events_by_grade.R b/R/tm_t_events_by_grade.R index e1d4e5e91c..27ca94a6d7 100644 --- a/R/tm_t_events_by_grade.R +++ b/R/tm_t_events_by_grade.R @@ -108,11 +108,11 @@ template_events_by_grade <- function(dataname, layout_list <- list() - basic_title <- if (is.null(hlt) & !is.null(llt)) { + basic_title <- if (is.null(hlt) && !is.null(llt)) { paste0("Adverse Event summary by ", label_grade, ": ", label_llt) - } else if (!is.null(hlt) & is.null(llt)) { + } else if (!is.null(hlt) && is.null(llt)) { paste0("Adverse Event summary by ", label_grade, ": ", label_hlt) - } else if (!is.null(hlt) & !is.null(llt)) { + } else if (!is.null(hlt) && !is.null(llt)) { paste0("Adverse Event summary by ", label_grade, ": ", label_hlt, " and ", label_llt) } else { paste0("Adverse Event summary by ", label_grade) @@ -500,11 +500,11 @@ template_events_col_by_grade <- function(dataname, y$data <- bracket_expr(data_list) layout_list <- list() - basic_title <- if (is.null(hlt) & !is.null(llt)) { + basic_title <- if (is.null(hlt) && !is.null(llt)) { paste0("Adverse Event summary by ", label_grade, ": ", label_llt) - } else if (!is.null(hlt) & is.null(llt)) { + } else if (!is.null(hlt) && is.null(llt)) { paste0("Adverse Event summary by ", label_grade, ": ", label_hlt) - } else if (!is.null(hlt) & !is.null(llt)) { + } else if (!is.null(hlt) && !is.null(llt)) { paste0("Adverse Event summary by ", label_grade, ": ", label_hlt, " and ", label_llt) } else { paste0("Adverse Event summary by ", label_grade) @@ -732,17 +732,17 @@ template_events_col_by_grade <- function(dataname, ) ) - if (prune_freq > 0 & prune_diff > 0) { + if (prune_freq > 0 && prune_diff > 0) { prune_pipe <- add_expr( prune_pipe, quote(rtables::prune_table(keep_rows(at_least_percent_any & at_least_percent_diff))) ) - } else if (prune_freq > 0 & prune_diff == 0) { + } else if (prune_freq > 0 && prune_diff == 0) { prune_pipe <- add_expr( prune_pipe, quote(rtables::prune_table(keep_rows(at_least_percent_any))) ) - } else if (prune_freq == 0 & prune_diff > 0) { + } else if (prune_freq == 0 && prune_diff > 0) { prune_pipe <- add_expr( prune_pipe, quote(rtables::prune_table(keep_rows(at_least_percent_diff))) @@ -958,7 +958,7 @@ ui_t_events_by_grade <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -966,8 +966,9 @@ ui_t_events_by_grade <- function(id, ...) { #' @noRd srv_t_events_by_grade <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, label, @@ -979,36 +980,46 @@ srv_t_events_by_grade <- function(id, grading_groups, drop_arm_levels, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(arm_var = arm_var, hlt = hlt, llt = llt, grade = grade), + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(arm_var = arm_var), + join_keys = attr(data, "join_keys"), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) - adsl_keys <- datasets$get_keys(parentname) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() + adsl_keys <- merged$adsl_input_r()$keys - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) + input_arm_var <- as.vector(merged$anl_input_r()$columns_source$arm_var) input_level_term <- c( - as.vector(anl_m$columns_source$hlt), - as.vector(anl_m$columns_source$llt) + as.vector(merged$anl_input_r()$columns_source$hlt), + as.vector(merged$anl_input_r()$columns_source$llt) ) - input_grade <- as.vector(anl_m$columns_source$grade) + input_grade <- as.vector(merged$anl_input_r()$columns_source$grade) shiny::validate( shiny::need(input_arm_var, "Please select a treatment variable"), @@ -1050,7 +1061,7 @@ srv_t_events_by_grade <- function(id, if (input$col_by_grade) { shiny::validate( shiny::need( - as.vector(anl_m$columns_source$llt), + as.vector(merged$anl_input_r()$columns_source$llt), "Low Level Term must be present for nested grade grouping display." ) ) @@ -1067,23 +1078,17 @@ srv_t_events_by_grade <- function(id, }) # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_table <- shiny::reactive({ validate_checks() - - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - input_hlt <- as.vector(anl_m$columns_source$hlt) - input_llt <- as.vector(anl_m$columns_source$llt) - input_grade <- as.vector(anl_m$columns_source$grade) - label_hlt <- if (length(input_hlt) != 0) attributes(anl_m$data()[[input_hlt]])$label else NULL - label_llt <- if (length(input_llt) != 0) attributes(anl_m$data()[[input_llt]])$label else NULL - label_grade <- if (length(input_grade) != 0) attributes(anl_m$data()[[input_grade]])$label else NULL + ANL <- merged$anl_q_r()[["ANL"]] # nolint + adsl_keys <- merged$adsl_input_r()$keys + + input_hlt <- as.vector(merged$anl_input_r()$columns_source$hlt) + input_llt <- as.vector(merged$anl_input_r()$columns_source$llt) + input_grade <- as.vector(merged$anl_input_r()$columns_source$grade) + label_hlt <- if (length(input_hlt) != 0) attributes(ANL[[input_hlt]])$label else NULL + label_llt <- if (length(input_llt) != 0) attributes(ANL[[input_llt]])$label else NULL + label_grade <- if (length(input_grade) != 0) attributes(ANL[[input_grade]])$label else NULL label_grade <- if (is.null(label_grade)) input_grade else NULL my_calls <- if (input$col_by_grade) { @@ -1092,8 +1097,8 @@ srv_t_events_by_grade <- function(id, parentname = "ANL_ADSL", add_total = input$add_total, grading_groups = grading_groups, - arm_var = as.vector(anl_m$columns_source$arm_var), - id = datasets$get_keys(parentname)[2], + arm_var = as.vector(merged$anl_input_r()$columns_source$arm_var), + id = adsl_keys[2], hlt = if (length(input_hlt) != 0) input_hlt else NULL, llt = if (length(input_llt) != 0) input_llt else NULL, label_hlt = label_hlt, @@ -1109,8 +1114,8 @@ srv_t_events_by_grade <- function(id, template_events_by_grade( dataname = "ANL", parentname = "ANL_ADSL", - arm_var = as.vector(anl_m$columns_source$arm_var), - id = datasets$get_keys(parentname)[2], + arm_var = as.vector(merged$anl_input_r()$columns_source$arm_var), + id = adsl_keys[2], hlt = if (length(input_hlt) != 0) input_hlt else NULL, llt = if (length(input_llt) != 0) input_llt else NULL, label_hlt = label_hlt, @@ -1124,14 +1129,12 @@ srv_t_events_by_grade <- function(id, basic_table_args = basic_table_args ) } - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), name = "tm_t_events_by_grade call") }) # Outputs to render. table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("pruned_and_sorted_result") + output_table()[["pruned_and_sorted_result"]] }) teal.widgets::table_with_settings_srv( @@ -1140,14 +1143,10 @@ srv_t_events_by_grade <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, hlt, llt, grade) - ), - modal_title = "AE by Grade Table", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_table())), + title = label ) ### REPORTER @@ -1156,19 +1155,16 @@ srv_t_events_by_grade <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Events by Grade Table") card$append_text("Events by Grade Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_table()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_events_patyear.R b/R/tm_t_events_patyear.R index 9b537fed35..8a1268d132 100644 --- a/R/tm_t_events_patyear.R +++ b/R/tm_t_events_patyear.R @@ -343,7 +343,7 @@ ui_events_patyear <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -351,8 +351,9 @@ ui_events_patyear <- function(id, ...) { #' @noRd srv_events_patyear <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -364,15 +365,12 @@ srv_events_patyear <- function(id, drop_arm_levels, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - shiny::observeEvent(anl_merged(), { - data <- anl_merged()$data() - aval_unit_var <- anl_merged()$columns_source$avalu_var + shiny::observeEvent(anl_merged_q(), { + data <- merged$anl_q_r()[["ANL"]] + aval_unit_var <- merged$anl_input_r()$columns_source$avalu_var if (length(aval_unit_var) > 0) { choices <- stats::na.omit(unique(data[[aval_unit_var]])) choices <- gsub("s$", "", tolower(choices)) @@ -386,8 +384,8 @@ srv_events_patyear <- function(id, } }) - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, data_extract = list( arm_var = arm_var, paramcd = paramcd, @@ -395,25 +393,38 @@ srv_events_patyear <- function(id, avalu_var = avalu_var, events_var = events_var ), + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, data_extract = list(arm_var = arm_var), + join_keys = attr(data, "join_keys"), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + # Prepare the analysis environment (filter data, check data, populate envir). validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) - - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_aval_var <- as.vector(anl_m$columns_source$aval_var) - input_avalu_var <- as.vector(anl_m$columns_source$avalu_var) - input_events_var <- as.vector(anl_m$columns_source$events_var) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() + + input_arm_var <- as.vector(merged$anl_input_r()$columns_source$arm_var) + input_aval_var <- as.vector(merged$anl_input_r()$columns_source$aval_var) + input_avalu_var <- as.vector(merged$anl_input_r()$columns_source$avalu_var) + input_events_var <- as.vector(merged$anl_input_r()$columns_source$events_var) input_paramcd <- unlist(paramcd$filter)["vars_selected"] # validate inputs @@ -440,7 +451,7 @@ srv_events_patyear <- function(id, "`Select an Event Type Parameter is not selected." ), shiny::need( - !any(is.na(anl_m$data()[[input_events_var]])), + !any(is.na(merged$anl_q_r()[["ANL"]][[input_events_var]])), "`Event Variable` for selected parameter includes NA values." ) ) @@ -449,27 +460,18 @@ srv_events_patyear <- function(id, }) # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_table <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - ANL <- teal.code::chunks_get_var("ANL") # nolint + ANL <- merged$anl_q_r()[["ANL"]] # nolint label_paramcd <- get_paramcd_label(ANL, paramcd) my_calls <- template_events_patyear( dataname = "ANL", parentname = "ANL_ADSL", - arm_var = as.vector(anl_m$columns_source$arm_var), - aval_var = as.vector(anl_m$columns_source$aval_var), - events_var = as.vector(anl_m$columns_source$events_var), + arm_var = as.vector(merged$anl_input_r()$columns_source$arm_var), + aval_var = as.vector(merged$anl_input_r()$columns_source$aval_var), + events_var = as.vector(merged$anl_input_r()$columns_source$events_var), label_paramcd = label_paramcd, add_total = input$add_total, control = control_incidence_rate( @@ -493,14 +495,12 @@ srv_events_patyear <- function(id, drop_arm_levels = input$drop_arm_levels, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), name = "tm_t_events_patyear call") }) # Outputs to render. table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") + output_table()[["result"]] }) teal.widgets::table_with_settings_srv( @@ -509,14 +509,10 @@ srv_events_patyear <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, paramcd, aval_var, events_var) - ), - modal_title = "Event Rate adjusted for patient-year at risk", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_table())), + title = label ) ### REPORTER @@ -525,19 +521,16 @@ srv_events_patyear <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Event Rates Adjusted For Patient-Years Table") card$append_text("Event Rates Adjusted For Patient-Years Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_table()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_events_summary.R b/R/tm_t_events_summary.R index fc92382ab3..76e78f0119 100644 --- a/R/tm_t_events_summary.R +++ b/R/tm_t_events_summary.R @@ -790,7 +790,7 @@ ui_t_events_summary <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -798,8 +798,9 @@ ui_t_events_summary <- function(id, ...) { #' @noRd srv_t_events_summary <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -811,12 +812,9 @@ srv_t_events_summary <- function(id, llt, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - data_extract_vars <- list( arm_var = arm_var, dthfl_var = dthfl_var, dcsreas_var = dcsreas_var, aeseq_var = aeseq_var, llt = llt @@ -832,41 +830,54 @@ srv_t_events_summary <- function(id, anl_selectors <- teal.transform::data_extract_multiple_srv( data_extract_vars, - datasets = datasets + datasets = data ) - anl_merged <- teal.transform::data_merge_srv( + anl_merged_input <- teal.transform::merge_expression_srv( selector_list = anl_selectors, - datasets = datasets, + datasets = data, + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, - data_extract = list(arm_var = arm_var, dthfl_var = dthfl_var, dcsreas_var = dcsreas_var), + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + data_extract = Filter(Negate(is.null), list(arm_var = arm_var, dthfl_var = dthfl_var, dcsreas_var = dcsreas_var)), + join_keys = attr(data, "join_keys"), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_dthfl_var <- as.vector(anl_m$columns_source$dthfl_var) - input_dcsreas_var <- as.vector(anl_m$columns_source$dcsreas_var) + input_arm_var <- as.vector(merged$anl_input_r()$columns_source$arm_var) + input_dthfl_var <- as.vector(merged$anl_input_r()$columns_source$dthfl_var) + input_dcsreas_var <- as.vector(merged$anl_input_r()$columns_source$dcsreas_var) input_flag_var_anl <- if (!is.null(flag_var_anl)) { - as.vector(anl_m$columns_source$flag_var_anl) + as.vector(merged$anl_input_r()$columns_source$flag_var_anl) } else { NULL } input_flag_var_aesi <- if (!is.null(flag_var_anl)) { - as.vector(anl_m$columns_source$flag_var_aesi) + as.vector(merged$anl_input_r()$columns_source$flag_var_aesi) } else { NULL } - input_aeseq_var <- as.vector(anl_m$columns_source$aeseq_var) - input_llt <- as.vector(anl_m$columns_source$llt) + input_aeseq_var <- as.vector(merged$anl_input_r()$columns_source$aeseq_var) + input_llt <- as.vector(merged$anl_input_r()$columns_source$llt) shiny::validate( shiny::need(input_arm_var, "Please select a treatment variable"), @@ -895,25 +906,16 @@ srv_t_events_summary <- function(id, }) # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_table <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - input_flag_var_anl <- if (!is.null(flag_var_anl)) { - as.vector(anl_m$columns_source$flag_var_anl) + as.vector(merged$anl_input_r()$columns_source$flag_var_anl) } else { NULL } input_flag_var_aesi <- if (!is.null(flag_var_anl)) { - as.vector(anl_m$columns_source$flag_var_aesi) + as.vector(merged$anl_input_r()$columns_source$flag_var_aesi) } else { NULL } @@ -921,65 +923,54 @@ srv_t_events_summary <- function(id, my_calls <- template_events_summary( anl_name = "ANL", parentname = "ANL_ADSL", - arm_var = as.vector(anl_m$columns_source$arm_var), - dthfl_var = as.vector(anl_m$columns_source$dthfl_var), - dcsreas_var = as.vector(anl_m$columns_source$dcsreas_var), + arm_var = as.vector(merged$anl_input_r()$columns_source$arm_var), + dthfl_var = as.vector(merged$anl_input_r()$columns_source$dthfl_var), + dcsreas_var = as.vector(merged$anl_input_r()$columns_source$dcsreas_var), flag_var_anl = if (length(input_flag_var_anl) != 0) input_flag_var_anl else NULL, flag_var_aesi = if (length(input_flag_var_aesi) != 0) input_flag_var_aesi else NULL, - aeseq_var = as.vector(anl_m$columns_source$aeseq_var), - llt = as.vector(anl_m$columns_source$llt), + aeseq_var = as.vector(merged$anl_input_r()$columns_source$aeseq_var), + llt = as.vector(merged$anl_input_r()$columns_source$llt), add_total = input$add_total, count_subj = input$count_subj, count_pt = input$count_pt, count_events = input$count_events ) - mapply( - expression = my_calls, - id = paste(names(my_calls), "call", sep = "_"), - teal.code::chunks_push - ) - all_basic_table_args <- teal.widgets::resolve_basic_table_args(user_table = basic_table_args) - teal.code::chunks_push( - expression = substitute( - expr = { - rtables::main_title(result) <- title - rtables::main_footer(result) <- footer - rtables::prov_footer(result) <- p_footer - rtables::subtitles(result) <- subtitle - result - }, - env = list( - title = `if`(is.null(all_basic_table_args$title), label, all_basic_table_args$title), - footer = `if`(is.null(all_basic_table_args$main_footer), "", all_basic_table_args$main_footer), - p_footer = `if`(is.null(all_basic_table_args$prov_footer), "", all_basic_table_args$prov_footer), - subtitle = `if`(is.null(all_basic_table_args$subtitles), "", all_basic_table_args$subtitles) + teal.code::eval_code( + merged$anl_q_r(), + as.expression(my_calls) + ) %>% + teal.code::eval_code( + substitute( + expr = { + rtables::main_title(result) <- title + rtables::main_footer(result) <- footer + rtables::prov_footer(result) <- p_footer + rtables::subtitles(result) <- subtitle + result + }, env = list( + title = `if`(is.null(all_basic_table_args$title), label, all_basic_table_args$title), + footer = `if`(is.null(all_basic_table_args$main_footer), "", all_basic_table_args$main_footer), + p_footer = `if`(is.null(all_basic_table_args$prov_footer), "", all_basic_table_args$prov_footer), + subtitle = `if`(is.null(all_basic_table_args$subtitles), "", all_basic_table_args$subtitles) + ) ) - ), - id = "meta_info_call" - ) + ) }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_table()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", table_r = table_r ) - # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(data_extract_vars), - modal_title = "Adverse Event Summary Table", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_table())), + title = label ) ### REPORTER @@ -988,19 +979,16 @@ srv_t_events_summary <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Adverse Events Summary Table") card$append_text("Adverse Events Summary Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_table()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_exposure.R b/R/tm_t_exposure.R index c14d741001..3aaf2632ad 100644 --- a/R/tm_t_exposure.R +++ b/R/tm_t_exposure.R @@ -453,7 +453,7 @@ ui_t_exposure <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -461,8 +461,9 @@ ui_t_exposure <- function(id, ...) { #' @noRd srv_t_exposure <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, paramcd, @@ -476,14 +477,12 @@ srv_t_exposure <- function(id, na_level, label, basic_table_args = basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list( id_var = id_var, paramcd = paramcd, @@ -496,25 +495,36 @@ srv_t_exposure <- function(id, merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(col_by_var = col_by_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) - anl_m <- anl_merged() - anl_adsl <- adsl_merged() + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() input_paramcd <- unlist(paramcd$filter)["vars_selected"] - input_id_var <- as.vector(anl_m$columns_source$id_var) - input_row_by_var <- as.vector(anl_m$columns_source$row_by_var) - input_col_by_var <- as.vector(anl_adsl$columns_source$col_by_var) + input_id_var <- names(merged$anl_input_r()$columns_source$id_var) + input_row_by_var <- names(merged$anl_input_r()$columns_source$row_by_var) + input_col_by_var <- names(merged$adsl_input_r()$columns_source$col_by_var) input_parcat <- unlist(parcat$filter)["vars_selected"] - input_aval_var <- as.vector(anl_m$columns_source$aval_var) - input_avalu_var <- as.vector(anl_m$columns_source$avalu_var) + input_aval_var <- names(merged$anl_input_r()$columns_source$aval_var) + input_avalu_var <- names(merged$anl_input_r()$columns_source$avalu_var) shiny::validate( shiny::need(input_row_by_var, "Please select a row by variable."), @@ -549,29 +559,21 @@ srv_t_exposure <- function(id, NULL }) - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + anl_filtered <- data[[dataname]]() input_avalu_var <- as.character( - unique(anl_m$data()[[as.vector(anl_m$columns_source$avalu_var)]]) + unique(merged$anl_q_r()[["ANL"]][[names(merged$anl_input_r()$columns_source$avalu_var)[1]]]) ) input_paramcd <- as.character( - unique(anl_m$data()[[as.vector(anl_m$columns_source$paramcd)]]) + unique(merged$anl_q_r()[["ANL"]][[names(merged$anl_input_r()$columns_source$paramcd)[1]]]) ) if (is.null(paramcd_label)) { input_paramcd_label <- input_paramcd } else { - paramcd <- as.vector(anl_m$columns_source$paramcd) + paramcd <- names(merged$anl_input_r()$columns_source$paramcd) paramcd_map_list <- c(paramcd, paramcd_label) paramcd_map <- unique(anl_filtered[paramcd_map_list]) input_paramcd_label <- as.character(paramcd_map[paramcd_map[1] == input_paramcd, 2]) @@ -580,27 +582,23 @@ srv_t_exposure <- function(id, my_calls <- template_exposure( parentname = "ANL_ADSL", dataname = "ANL", - id_var <- as.vector(anl_m$columns_source$id_var), + id_var <- names(merged$anl_input_r()$columns_source$id_var), paramcd <- input_paramcd, paramcd_label = input_paramcd_label, - row_by_var <- as.vector(anl_m$columns_source$row_by_var), - col_by_var <- as.vector(anl_m$columns_source$col_by_var), + row_by_var <- names(merged$anl_input_r()$columns_source$row_by_var), + col_by_var <- names(merged$anl_input_r()$columns_source$col_by_var), add_total = input$add_total, drop_levels = TRUE, na_level = na_level, - aval_var <- as.vector(anl_m$columns_source$aval_var), + aval_var <- names(merged$anl_input_r()$columns_source$aval_var), avalu_var <- input_avalu_var, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls)) }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", @@ -608,14 +606,10 @@ srv_t_exposure <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(id_var, paramcd, row_by_var, col_by_var, parcat, aval_var, avalu_var) - ), - modal_title = "R Code for Risk Management Plan Table", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -624,19 +618,16 @@ srv_t_exposure <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Exposure for Risk Management Plan Table") card$append_text("Exposure for Risk Management Plan Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_logistic.R b/R/tm_t_logistic.R index 7b6da4e77e..0b1819d6ec 100644 --- a/R/tm_t_logistic.R +++ b/R/tm_t_logistic.R @@ -424,7 +424,7 @@ ui_t_logistic <- function(id, ...) { fixed = a$conf_level$fixed ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -434,8 +434,9 @@ ui_t_logistic <- function(id, ...) { #' @noRd #' srv_t_logistic <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -445,48 +446,54 @@ srv_t_logistic <- function(id, cov_var, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - # Observer to update reference and comparison arm input options. - if (!is.null(arm_var)) { - arm_ref_comp_observer( - session, - input, - output, - id_arm_var = extract_input("arm_var", parentname), - datasets = datasets, - dataname = parentname, - arm_ref_comp = arm_ref_comp, - module = "tm_t_logistic" - ) - } + arm_ref_comp_observer( + session, + input, + output, + id_arm_var = extract_input("arm_var", parentname), + data = data[[parentname]], + arm_ref_comp = arm_ref_comp, + module = "tm_t_logistic" + ) - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var, paramcd = paramcd, avalc_var = avalc_var, cov_var = cov_var), merge_function = "dplyr::inner_join" ) - if (!is.null(arm_var)) { - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, - data_extract = list(arm_var = arm_var), - anl_name = "ANL_ADSL" - ) - } + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), + data_extract = list(arm_var = arm_var), + anl_name = "ANL_ADSL" + ) + + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) # Because the AVALC values depends on the selected PARAMCD. - shiny::observeEvent(anl_merged(), { - avalc_var <- anl_merged()$columns_source$avalc_var - if (nrow(anl_merged()$data()) == 0) { + shiny::observeEvent(merged$anl_input_r(), { + avalc_var <- merged$anl_input_r()$columns_source$avalc_var + if (nrow(merged$anl_q_r()[["ANL"]]) == 0) { responder_choices <- c("CR", "PR") responder_sel <- c("CR", "PR") } else { - responder_choices <- unique(anl_merged()$data()[[avalc_var]]) + responder_choices <- unique(merged$anl_q_r()[["ANL"]][[avalc_var]]) responder_sel <- intersect(responder_choices, shiny::isolate(input$responders)) } shiny::updateSelectInput( @@ -497,8 +504,7 @@ srv_t_logistic <- function(id, }) output$interaction_var <- shiny::renderUI({ - anl_m <- anl_merged() - cov_var <- as.vector(anl_m$columns_source$cov_var) + cov_var <- as.vector(merged$anl_input_r()$columns_source$cov_var) if (length(cov_var) > 0) { teal.widgets::optionalSelectInput( session$ns("interaction_var"), @@ -513,15 +519,14 @@ srv_t_logistic <- function(id, }) output$interaction_input <- shiny::renderUI({ - anl_m <- anl_merged() interaction_var <- input$interaction_var if (length(interaction_var) > 0) { - if (is.numeric(anl_m$data()[[interaction_var]])) { + if (is.numeric(merged$anl_q_r()[["ANL"]][[interaction_var]])) { shiny::tagList( shiny::textInput( session$ns("interaction_values"), label = sprintf("Specify %s values (comma delimited) for treatment ORs calculation:", interaction_var), - value = as.character(stats::median(anl_m$data()[[interaction_var]])) + value = as.character(stats::median(merged$anl_q_r()[["ANL"]][[interaction_var]])) ) ) } @@ -531,13 +536,12 @@ srv_t_logistic <- function(id, }) validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_avalc_var <- as.vector(anl_m$columns_source$avalc_var) - input_cov_var <- as.vector(anl_m$columns_source$cov_var) + input_arm_var <- as.vector(merged$anl_input_r()$columns_source$arm_var) + input_avalc_var <- as.vector(merged$anl_input_r()$columns_source$avalc_var) + input_cov_var <- as.vector(merged$anl_input_r()$columns_source$cov_var) input_paramcd <- unlist(paramcd$filter)["vars_selected"] input_interaction_var <- input$interaction_var @@ -575,7 +579,7 @@ srv_t_logistic <- function(id, do.call(what = "validate_standard_inputs", validate_args) - arm_n <- base::table(anl_m$data()[[input_arm_var]]) + arm_n <- base::table(merged$anl_q_r()[["ANL"]][[input_arm_var]]) anl_arm_n <- if (input$combine_comp_arms) { c(sum(arm_n[unlist(input$buckets$Ref)]), sum(arm_n[unlist(input$buckets$Comp)])) } else { @@ -593,7 +597,7 @@ srv_t_logistic <- function(id, ) # validate interaction values - if (interaction_flag && (is.numeric(anl_m$data()[[input_interaction_at]]))) { + if (interaction_flag && (is.numeric(merged$anl_q_r()[["ANL"]][[input_interaction_at]]))) { shiny::validate(shiny::need( !is.na(at_values), "If interaction is specified the level should be entered." @@ -605,7 +609,7 @@ srv_t_logistic <- function(id, shiny::need( all( vapply( - anl_m$data()[input_cov_var], + merged$anl_q_r()[["ANL"]][input_cov_var], FUN = function(x) { length(unique(x)) > 1 }, @@ -617,21 +621,10 @@ srv_t_logistic <- function(id, ) }) - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - if (!is.null(arm_var)) { - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - } - - ANL <- teal.code::chunks_get_var("ANL") # nolint + ANL <- merged$anl_q_r()[["ANL"]] # nolint label_paramcd <- get_paramcd_label(ANL, paramcd) @@ -645,14 +638,14 @@ srv_t_logistic <- function(id, } else { unlist(as_num(input$interaction_values)) } - at_flag <- interaction_flag && is.numeric(anl_m$data()[[interaction_var]]) + at_flag <- interaction_flag && is.numeric(ANL[[interaction_var]]) - cov_var <- as.vector(anl_m$columns_source$cov_var) + cov_var <- names(merged$anl_input_r()$columns_source$cov_var) calls <- template_logistic( dataname = "ANL", - arm_var = as.vector(anl_m$columns_source$arm_var), - aval_var = as.vector(anl_m$columns_source$avalc_var), + arm_var = names(merged$anl_input_r()$columns_source$arm_var), + aval_var = names(merged$anl_input_r()$columns_source$avalc_var), paramcd = paramcd, label_paramcd = label_paramcd, cov_var = if (length(cov_var) > 0) cov_var else NULL, @@ -667,28 +660,20 @@ srv_t_logistic <- function(id, basic_table_args = basic_table_args ) - mapply(expression = calls, id = paste(names(calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(merged$anl_q_r(), as.expression(calls), name = "summarize_logistic call") }) - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", table_r = table_r ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, paramcd, avalc_var, cov_var) - ), - modal_title = "R Code for the Current Logistic Regression", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -697,19 +682,16 @@ srv_t_logistic <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Logistic Regression Table") card$append_text("Logistic Regression Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_mult_events.R b/R/tm_t_mult_events.R index 3e3fb8a101..7992f5331b 100644 --- a/R/tm_t_mult_events.R +++ b/R/tm_t_mult_events.R @@ -162,8 +162,7 @@ template_mult_events <- function(dataname, lbl_lst <- add_expr( lbl_lst, substitute( # nolint - expr = - attr(dataname$hlt_new, which = "label"), + expr = attr(dataname$hlt_new, which = "label"), env = list( dataname = as.name(dataname), hlt_new = hlt_new @@ -430,7 +429,7 @@ ui_t_mult_events_byterm <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -438,8 +437,9 @@ ui_t_mult_events_byterm <- function(id, ...) { #' @noRd srv_t_mult_events_byterm <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, event_type, @@ -450,40 +450,42 @@ srv_t_mult_events_byterm <- function(id, drop_arm_levels, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_selectors <- teal.transform::data_extract_multiple_srv( - list( + anl_merge_inputs <- teal.transform::merge_expression_module( + id = "anl_merge", + datasets = data, + join_keys = attr(data, "join_keys"), + data_extract = list( arm_var = arm_var, seq_var = seq_var, hlt = hlt, llt = llt ), - datasets = datasets - ) - - anl_merged <- teal.transform::data_merge_srv( - selector_list = anl_selectors, - datasets = datasets, merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merge_inputs <- teal.transform::merge_expression_module( + id = "adsl_merge", + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var), anl_name = "ANL_ADSL" ) + merged_data_q <- reactive({ + q1 <- teal.code::new_quosure(data) + q2 <- teal.code::eval_code(q1, as.expression(anl_merge_inputs()$expr)) + teal.code::eval_code(q2, as.expression(adsl_merge_inputs()$expr)) + }) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - anl_m <- anl_merged() + anl_m <- anl_merge_inputs() input_arm_var <- as.vector(anl_m$columns_source$arm_var) input_seq_var <- as.vector(anl_m$columns_source$seq_var) @@ -511,23 +513,17 @@ srv_t_mult_events_byterm <- function(id, }) # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() + q1 <- merged_data_q() + anl_m <- anl_merge_inputs() - input_hlt <- as.vector(anl_m$columns_source$hlt) - input_llt <- as.vector(anl_m$columns_source$llt) + input_hlt <- names(anl_m$columns_source$hlt) + input_llt <- names(anl_m$columns_source$llt) - hlt_labels <- mapply(function(x) rtables::obj_label(anl_m$data()[[x]]), input_hlt) - llt_labels <- mapply(function(x) rtables::obj_label(anl_m$data()[[x]]), input_llt) + hlt_labels <- mapply(function(x) rtables::obj_label(q1[["ANL"]][[x]]), input_hlt) + llt_labels <- mapply(function(x) rtables::obj_label(q1[["ANL"]][[x]]), input_llt) basic_table_args$title <- ifelse( is.null(basic_table_args$title), @@ -543,8 +539,8 @@ srv_t_mult_events_byterm <- function(id, my_calls <- template_mult_events( dataname = "ANL", parentname = "ANL_ADSL", - arm_var = as.vector(anl_m$columns_source$arm_var), - seq_var = as.vector(anl_m$columns_source$seq_var), + arm_var = names(anl_m$columns_source$arm_var), + seq_var = names(anl_m$columns_source$seq_var), hlt = if (length(input_hlt) != 0) input_hlt else NULL, llt = input_llt, add_total = input$add_total, @@ -552,28 +548,19 @@ srv_t_mult_events_byterm <- function(id, drop_arm_levels = input$drop_arm_levels, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(q1, as.expression(my_calls)) }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) - teal.widgets::table_with_settings_srv( - id = "table", - table_r = table_r - ) + teal.widgets::table_with_settings_srv(id = "table", table_r = table_r) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(arm_var, seq_var, hlt, llt)), - modal_title = "Event Table", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -582,19 +569,16 @@ srv_t_mult_events_byterm <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Multiple Events by Term Table") card$append_text("Multiple Events by Term Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(get_rcode(teal.code::get_code(output_q())), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_pp_basic_info.R b/R/tm_t_pp_basic_info.R index cf710fc2ec..46aa829637 100644 --- a/R/tm_t_pp_basic_info.R +++ b/R/tm_t_pp_basic_info.R @@ -143,7 +143,7 @@ ui_t_basic_info <- function(id, ...) { is_single_dataset = is_single_dataset_value ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = ui_args$pre_output, post_output = ui_args$post_output ) @@ -151,22 +151,20 @@ ui_t_basic_info <- function(id, ...) { srv_t_basic_info <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, patient_col, vars, label) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - patient_id <- shiny::reactive(input$patient_id) # Init - patient_data_base <- shiny::reactive(unique(datasets$get_data(dataname, filtered = TRUE)[[patient_col]])) + patient_data_base <- shiny::reactive(unique(data[[dataname]]()[[patient_col]])) teal.widgets::updateOptionalSelectInput( session, "patient_id", @@ -191,29 +189,35 @@ srv_t_basic_info <- function(id, ) # Basic Info tab ---- - binf_merged_data <- teal.transform::data_merge_module( - datasets = datasets, + merge_input_r <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(vars = vars), merge_function = "dplyr::left_join" ) - basic_info_call <- shiny::reactive({ + merge_q_r <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(merge_input_r()$expr)) + }) + + output_q <- shiny::reactive({ shiny::validate(shiny::need(patient_id(), "Please select a patient.")) shiny::validate( shiny::need( - input[[extract_input("vars", dataname)]], + merge_input_r()$columns_source$vars, "Please select basic info variables." ) ) - call_stack <- teal.code::chunks_new() - call_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = call_stack) - } - teal.code::chunks_push_data_merge(binf_merged_data(), chunks = call_stack) + my_calls <- template_basic_info( + dataname = "ANL", + vars = merge_input_r()$columns_source$vars + ) - call_stack_push( - expression = substitute( + teal.code::eval_code( + merge_q_r(), + substitute( expr = { ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint }, env = list( @@ -221,34 +225,22 @@ srv_t_basic_info <- function(id, patient_id = patient_id() ) ), - id = "patient_id_filter_call" - ) - - my_calls <- template_basic_info( - dataname = "ANL", - vars = input[[extract_input("vars", dataname)]] - ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), call_stack_push) - teal.code::chunks_safe_eval(chunks = call_stack) - call_stack + name = "patient_id_filter_call" + ) %>% + teal.code::eval_code(as.expression(my_calls), name = "call") }) - table_r <- shiny::reactive({ - teal.code::chunks_reset() - teal.code::chunks_push_chunks(basic_info_call()) - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) output$basic_info_table <- DT::renderDataTable( expr = table_r(), options = list(pageLength = input$basic_info_table_rows) ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(vars)), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -257,19 +249,16 @@ srv_t_basic_info <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Patient Profile Basic Info Table") card$append_text("Patient Profile Basic Info Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_pp_laboratory.R b/R/tm_t_pp_laboratory.R index 072ac90b57..99c5f278ea 100644 --- a/R/tm_t_pp_laboratory.R +++ b/R/tm_t_pp_laboratory.R @@ -273,15 +273,16 @@ ui_g_laboratory <- function(id, ...) { choices = NULL ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = ui_args$pre_output, post_output = ui_args$post_output ) } srv_g_laboratory <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, patient_col, @@ -292,16 +293,13 @@ srv_g_laboratory <- function(id, paramcd, anrind, label) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - patient_id <- shiny::reactive(input$patient_id) # Init - patient_data_base <- shiny::reactive(unique(datasets$get_data(parentname, filtered = TRUE)[[patient_col]])) + patient_data_base <- shiny::reactive(unique(data[[parentname]]()[[patient_col]])) teal.widgets::updateOptionalSelectInput( session, "patient_id", @@ -326,7 +324,7 @@ srv_g_laboratory <- function(id, ) # Update round_values - aval_values <- datasets$get_data(dataname, filtered = TRUE)[, aval$select$selected] + aval_values <- data[[dataname]]()[, aval$select$selected] decimal_nums <- aval_values[trunc(aval_values) != aval_values] max_decimal <- max(nchar(gsub("([0-9]+).([0-9]+)", "\\2", decimal_nums))) @@ -338,8 +336,9 @@ srv_g_laboratory <- function(id, ) # Laboratory values tab ---- - labor_merged_data <- teal.transform::data_merge_module( - datasets = datasets, + merge_input_r <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list( timepoints = timepoints, aval = aval, @@ -350,7 +349,12 @@ srv_g_laboratory <- function(id, ) ) - labor_calls <- shiny::reactive({ + merge_q_r <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(merge_input_r()$expr)) + }) + + output_q <- shiny::reactive({ shiny::validate(shiny::need(patient_id(), "Please select a patient.")) shiny::validate( @@ -380,26 +384,6 @@ srv_g_laboratory <- function(id, ) ) - labor_stack <- teal.code::chunks_new() - labor_stack$reset() - labor_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = labor_stack) - } - - teal.code::chunks_push_data_merge(labor_merged_data(), chunks = labor_stack) - - labor_stack_push( - substitute( - expr = { - ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint - }, env = list( - patient_col = patient_col, - patient_id = patient_id() - ) - ), - id = "patient_id_filter_call" - ) - labor_calls <- template_laboratory( dataname = "ANL", timepoints = input[[extract_input("timepoints", dataname)]], @@ -411,21 +395,26 @@ srv_g_laboratory <- function(id, round_value = as.integer(input$round_value) ) - mapply( - expression = labor_calls, - id = paste(names(labor_calls), "call", sep = "_"), - labor_stack_push - ) - teal.code::chunks_safe_eval(chunks = labor_stack) - labor_stack + teal.code::eval_code( + merge_q_r(), + substitute( + expr = { + ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint + }, env = list( + patient_col = patient_col, + patient_id = patient_id() + ) + ), + name = "patient_id_filter_call" + ) %>% + teal.code::eval_code(as.expression(labor_calls)) }) table_r <- shiny::reactive({ - teal.code::chunks_reset() - teal.code::chunks_push_chunks(labor_calls()) + q <- output_q() list( - html = teal.code::chunks_get_var("labor_table_html"), - raw = teal.code::chunks_get_var("labor_table_raw") + html = q[["labor_table_html"]], + raw = q[["labor_table_raw"]] ) }) @@ -435,11 +424,10 @@ srv_g_laboratory <- function(id, options = list(pageLength = input$lab_values_table_rows, scrollX = TRUE) ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(timepoints, aval, avalu, param, paramcd, anrind)), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -448,19 +436,16 @@ srv_g_laboratory <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Patient Profile Laboratory Table") card$append_text("Patient Profile Laboratory Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()$raw) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_pp_medical_history.R b/R/tm_t_pp_medical_history.R index ffc3a1931d..5877af6387 100644 --- a/R/tm_t_pp_medical_history.R +++ b/R/tm_t_pp_medical_history.R @@ -210,7 +210,7 @@ ui_t_medical_history <- function(id, ...) { is_single_dataset = is_single_dataset_value ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = ui_args$pre_output, post_output = ui_args$post_output ) @@ -218,8 +218,9 @@ ui_t_medical_history <- function(id, ...) { srv_t_medical_history <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, patient_col, @@ -227,16 +228,13 @@ srv_t_medical_history <- function(id, mhbodsys, mhdistat, label) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - patient_id <- shiny::reactive(input$patient_id) # Init - patient_data_base <- shiny::reactive(unique(datasets$get_data(parentname, filtered = TRUE)[[patient_col]])) + patient_data_base <- shiny::reactive(unique(data[[parentname]]()[[patient_col]])) teal.widgets::updateOptionalSelectInput( session, "patient_id", choices = patient_data_base(), selected = patient_data_base()[1] @@ -259,13 +257,19 @@ srv_t_medical_history <- function(id, ) # Medical history tab ---- - mhist_merged_data <- teal.transform::data_merge_module( - datasets = datasets, + merge_input_r <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(mhterm = mhterm, mhbodsys = mhbodsys, mhdistat = mhdistat), merge_function = "dplyr::left_join" ) - mhist_call <- shiny::reactive({ + merge_q_r <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(merge_input_r()$expr)) + }) + + output_q <- shiny::reactive({ shiny::validate(shiny::need(patient_id(), "Please select a patient.")) shiny::validate( @@ -282,19 +286,21 @@ srv_t_medical_history <- function(id, "Please select MHDISTAT variable." ), shiny::need( - nrow(mhist_merged_data()$data()[mhist_merged_data()$data()[[patient_col]] == patient_id(), ]) > 0, + nrow(merge_q_r()[["ANL"]][merge_q_r()[["ANL"]][[patient_col]] == patient_id(), ]) > 0, "Patient has no data about medical history." ) ) - mhist_stack <- teal.code::chunks_new() - mhist_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = mhist_stack) - } - teal.code::chunks_push_data_merge(mhist_merged_data(), chunks = mhist_stack) + my_calls <- template_medical_history( + dataname = "ANL", + mhterm = input[[extract_input("mhterm", dataname)]], + mhbodsys = input[[extract_input("mhbodsys", dataname)]], + mhdistat = input[[extract_input("mhdistat", dataname)]] + ) - mhist_stack_push( - expression = substitute( + teal.code::eval_code( + merge_q_r(), + substitute( expr = { ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint }, env = list( @@ -302,40 +308,22 @@ srv_t_medical_history <- function(id, patient_id = patient_id() ) ), - id = "patient_id_filter_call" - ) - - my_calls <- template_medical_history( - dataname = "ANL", - mhterm = input[[extract_input("mhterm", dataname)]], - mhbodsys = input[[extract_input("mhbodsys", dataname)]], - mhdistat = input[[extract_input("mhdistat", dataname)]] - ) - mapply( - expression = my_calls, - id = paste(names(my_calls), "call", sep = "_"), - mhist_stack_push - ) - teal.code::chunks_safe_eval(chunks = mhist_stack) - mhist_stack + name = "patient_id_filter_call" + ) %>% + teal.code::eval_code(as.expression(my_calls), name = "call") }) - table_r <- shiny::reactive({ - teal.code::chunks_reset() - teal.code::chunks_push_chunks(mhist_call()) - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", table_r = table_r ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(mhterm, mhbodsys, mhdistat)), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -344,19 +332,16 @@ srv_t_medical_history <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Patient Medical History Table") card$append_text("Patient Medical History Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_pp_prior_medication.R b/R/tm_t_pp_prior_medication.R index 3a5ba90fd0..a0efa57970 100644 --- a/R/tm_t_pp_prior_medication.R +++ b/R/tm_t_pp_prior_medication.R @@ -242,7 +242,7 @@ ui_t_prior_medication <- function(id, ...) { is_single_dataset = is_single_dataset_value ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = ui_args$pre_output, post_output = ui_args$post_output ) @@ -250,8 +250,9 @@ ui_t_prior_medication <- function(id, ...) { srv_t_prior_medication <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, patient_col, @@ -260,16 +261,13 @@ srv_t_prior_medication <- function(id, cmindc, cmstdy, label) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - patient_id <- shiny::reactive(input$patient_id) # Init - patient_data_base <- shiny::reactive(unique(datasets$get_data(parentname, filtered = TRUE)[[patient_col]])) + patient_data_base <- shiny::reactive(unique(data[[parentname]]()[[patient_col]])) teal.widgets::updateOptionalSelectInput( session, "patient_id", @@ -294,13 +292,19 @@ srv_t_prior_medication <- function(id, ) # Prior medication tab ---- - pmed_merged_data <- teal.transform::data_merge_module( - datasets = datasets, + merge_input_r <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(atirel = atirel, cmdecod = cmdecod, cmindc = cmindc, cmstdy = cmstdy), merge_function = "dplyr::left_join" ) - pmed_call <- shiny::reactive({ + merge_q_r <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(merge_input_r()$expr)) + }) + + output_q <- shiny::reactive({ shiny::validate(shiny::need(patient_id(), "Please select a patient.")) shiny::validate( @@ -322,13 +326,16 @@ srv_t_prior_medication <- function(id, ) ) - pmed_stack <- teal.code::chunks_new() - pmed_stack_push <- function(...) { - teal.code::chunks_push(..., chunks = pmed_stack) - } - teal.code::chunks_push_data_merge(pmed_merged_data(), chunks = pmed_stack) + my_calls <- template_prior_medication( + dataname = "ANL", + atirel = input[[extract_input("atirel", dataname)]], + cmdecod = input[[extract_input("cmdecod", dataname)]], + cmindc = input[[extract_input("cmindc", dataname)]], + cmstdy = input[[extract_input("cmstdy", dataname)]] + ) - pmed_stack_push( + teal.code::eval_code( + merge_q_r(), substitute( expr = { ANL <- ANL[ANL[[patient_col]] == patient_id, ] # nolint @@ -337,38 +344,22 @@ srv_t_prior_medication <- function(id, patient_id = patient_id() ) ), - id = "patient_id_filter_call" - ) - - my_calls <- template_prior_medication( - dataname = "ANL", - atirel = input[[extract_input("atirel", dataname)]], - cmdecod = input[[extract_input("cmdecod", dataname)]], - cmindc = input[[extract_input("cmindc", dataname)]], - cmstdy = input[[extract_input("cmstdy", dataname)]] - ) - - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), pmed_stack_push) - teal.code::chunks_safe_eval(pmed_stack) - pmed_stack + name = "patient_id_filter_call" + ) %>% + teal.code::eval_code(as.expression(my_calls), name = "call") }) - table_r <- shiny::reactive({ - teal.code::chunks_reset() - teal.code::chunks_push_chunks(pmed_call()) - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) output$prior_medication_table <- DT::renderDataTable( expr = table_r(), options = list(pageLength = input$prior_medication_table_rows) ) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(atirel, cmdecod, cmindc, cmstdy)), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) if (with_reporter) { @@ -376,19 +367,16 @@ srv_t_prior_medication <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Patient Prior Medication Table") card$append_text("Patient Prior Medication Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_shift_by_arm.R b/R/tm_t_shift_by_arm.R index 0acc0d3534..45b88c75a7 100644 --- a/R/tm_t_shift_by_arm.R +++ b/R/tm_t_shift_by_arm.R @@ -362,7 +362,7 @@ ui_shift_by_arm <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -370,8 +370,9 @@ ui_shift_by_arm <- function(id, ...) { #' @noRd srv_shift_by_arm <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -384,14 +385,12 @@ srv_shift_by_arm <- function(id, na_level, add_total, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list( arm_var = arm_var, paramcd = paramcd, @@ -403,28 +402,39 @@ srv_shift_by_arm <- function(id, merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + # validate inputs validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - anl_m <- anl_merged() - anl_m_rowcount <- NROW(anl_m$data()) - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_aval_var <- as.vector(anl_m$columns_source$aval_var) - input_base_var <- as.vector(anl_m$columns_source$base_var) - input_treatment_flag_var <- as.vector(anl_m$columns_source$treatment_flag_var) + input_arm_var <- names(merged$anl_input_r()$columns_source$arm_var) + input_aval_var <- names(merged$anl_input_r()$columns_source$aval_var) + input_base_var <- names(merged$anl_input_r()$columns_source$base_var) + input_treatment_flag_var <- names(merged$anl_input_r()$columns_source$treatment_flag_var) shiny::validate( shiny::need(input_arm_var, "Please select a treatment variable"), shiny::need( - anl_m_rowcount > 0, + nrow(merged$anl_q_r()[["ANL"]]) > 0, paste0( "Please make sure the analysis dataset is not empty or\n", "endpoint parameter and analysis visit are selected." @@ -444,41 +454,29 @@ srv_shift_by_arm <- function(id, }) # generate r code for the analysis - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - my_calls <- template_shift_by_arm( dataname = "ANL", parentname = "ANL_ADSL", - arm_var = as.vector(anl_m$columns_source$arm_var), - paramcd = unlist(paramcd$filter)["vars_selected"], - treatment_flag_var = as.vector(anl_m$columns_source$treatment_flag_var), + arm_var = names(merged$anl_input_r()$columns_source$arm_var), + paramcd = unlist(merged$anl_input_r()$filter)["vars_selected"], + treatment_flag_var = names(merged$anl_input_r()$columns_source$treatment_flag_var), treatment_flag = input$treatment_flag, - aval_var = as.vector(anl_m$columns_source$aval_var), - base_var = as.vector(anl_m$columns_source$base_var), + aval_var = names(merged$anl_input_r()$columns_source$aval_var), + base_var = names(merged$anl_input_r()$columns_source$base_var), na.rm = ifelse(input$useNA == "ifany", FALSE, TRUE), # nolint na_level = na_level, add_total = input$add_total, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), name = "tm_t_shift_by_arm call") }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", @@ -486,12 +484,10 @@ srv_shift_by_arm <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(arm_var, paramcd, visit_var, aval_var, base_var)), - modal_title = "R Code for Shift Table by Arm", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -500,19 +496,16 @@ srv_shift_by_arm <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Shift by Arm Table") card$append_text("Shift by Arm Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_shift_by_arm_by_worst.R b/R/tm_t_shift_by_arm_by_worst.R index 3d368feeb9..80d1a025b4 100644 --- a/R/tm_t_shift_by_arm_by_worst.R +++ b/R/tm_t_shift_by_arm_by_worst.R @@ -382,7 +382,7 @@ ui_shift_by_arm_by_worst <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -390,8 +390,9 @@ ui_shift_by_arm_by_worst <- function(id, ...) { #' @noRd srv_shift_by_arm_by_worst <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -404,14 +405,12 @@ srv_shift_by_arm_by_worst <- function(id, na_level, add_total, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list( arm_var = arm_var, paramcd = paramcd, @@ -423,29 +422,40 @@ srv_shift_by_arm_by_worst <- function(id, merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + # validate inputs validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - anl_m <- anl_merged() - anl_m_rowcount <- NROW(anl_m$data()) - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_aval_var <- as.vector(anl_m$columns_source$aval_var) - input_base_var <- as.vector(anl_m$columns_source$base_var) - input_treatment_flag_var <- as.vector(anl_m$columns_source$treatment_flag_var) - input_worst_flag_var <- as.vector(anl_m$columns_source$worst_flag_var) + input_arm_var <- names(merged$anl_input_r()$columns_source$arm_var) + input_aval_var <- names(merged$anl_input_r()$columns_source$aval_var) + input_base_var <- names(merged$anl_input_r()$columns_source$base_var) + input_treatment_flag_var <- names(merged$anl_input_r()$columns_source$treatment_flag_var) + input_worst_flag_var <- names(merged$anl_input_r()$columns_source$worst_flag_var) shiny::validate( shiny::need(input_arm_var, "Please select a treatment variable"), shiny::need( - anl_m_rowcount > 0, + nrow(merged$anl_q_r()[["ANL"]]) > 0, paste0( "Please make sure the analysis dataset is not empty or\n", "endpoint parameter and analysis visit are selected." @@ -466,45 +476,31 @@ srv_shift_by_arm_by_worst <- function(id, }) # generate r code for the analysis - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - my_calls <- template_shift_by_arm_by_worst( dataname = "ANL", parentname = "ANL_ADSL", - arm_var = as.vector(anl_m$columns_source$arm_var), + arm_var = names(merged$anl_input_r()$columns_source$arm_var), paramcd = unlist(paramcd$filter)["vars_selected"], - worst_flag_var = as.vector(anl_m$columns_source$worst_flag_var), + worst_flag_var = names(merged$anl_input_r()$columns_source$worst_flag_var), worst_flag = input$worst_flag, - treatment_flag_var = as.vector(anl_m$columns_source$treatment_flag_var), + treatment_flag_var = names(merged$anl_input_r()$columns_source$treatment_flag_var), treatment_flag = input$treatment_flag, - aval_var = as.vector(anl_m$columns_source$aval_var), - base_var = as.vector(anl_m$columns_source$base_var), + aval_var = names(merged$anl_input_r()$columns_source$aval_var), + base_var = names(merged$anl_input_r()$columns_source$base_var), na.rm = ifelse(input$useNA == "ifany", FALSE, TRUE), # nolint na_level = na_level, add_total = input$add_total, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), name = "tm_t_shift_by_arm_by_worst call") }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", @@ -512,12 +508,10 @@ srv_shift_by_arm_by_worst <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(arm_var, paramcd, aval_var, base_var)), - modal_title = "R Code for Shift Table by Arm", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -526,19 +520,16 @@ srv_shift_by_arm_by_worst <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Shift by Arm by Worst Table") card$append_text("Shift by Arm by Worst Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_shift_by_grade.R b/R/tm_t_shift_by_grade.R index e0c0306c2e..3a28de9cfc 100644 --- a/R/tm_t_shift_by_grade.R +++ b/R/tm_t_shift_by_grade.R @@ -715,7 +715,7 @@ ui_t_shift_by_grade <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -723,8 +723,9 @@ ui_t_shift_by_grade <- function(id, ...) { #' @noRd srv_t_shift_by_grade <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -739,14 +740,12 @@ srv_t_shift_by_grade <- function(id, na_level, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list( arm_var = arm_var, visit_var = visit_var, @@ -759,73 +758,71 @@ srv_t_shift_by_grade <- function(id, merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) - - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_id_var <- as.vector(anl_m$columns_source$id_var) - input_visit_var <- as.vector(anl_m$columns_source$visit_var) - input_paramcd <- unlist(paramcd$filter)["vars_selected"] - input_paramcd_var <- anl_m$data()[[as.vector(anl_m$columns_source$paramcd)]] - input_worst_flag_var <- as.vector(anl_m$columns_source$worst_flag_var) - input_anl_toxgrade_var <- as.vector(anl_m$columns_source$anl_toxgrade_var) - input_base_toxgrade_var <- as.vector(anl_m$columns_source$base_toxgrade_var) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() + + input_arm_var <- names(merged$anl_input_r()$columns_source$arm_var) + input_id_var <- names(merged$anl_input_r()$columns_source$id_var) + input_visit_var <- names(merged$anl_input_r()$columns_source$visit_var) + input_paramcd_var <- names(merged$anl_input_r()$columns_source$paramcd) + input_paramcd <- unlist(merged$anl_input_r()$filter_info$paramcd[[1]]$selected) + input_worst_flag_var <- names(merged$anl_input_r()$columns_source$worst_flag_var) + input_anl_toxgrade_var <- names(merged$anl_input_r()$columns_source$anl_toxgrade_var) + input_base_toxgrade_var <- names(merged$anl_input_r()$columns_source$base_toxgrade_var) shiny::validate( shiny::need(input_worst_flag_var, "Please select the worst flag variable."), - shiny::need(input_paramcd_var, "Please select Laboratory parameter."), + shiny::need(input_paramcd, "Please select Laboratory parameter."), shiny::need(input_id_var, "Please select a subject identifier."), shiny::need(input$worst_flag_indicator, "Please select the value indicating worst grade.") ) - input_worst_flag <- anl_m$data()[[as.vector(anl_m$columns_source$worst_flag_var)]] - shiny::validate(shiny::need( - any(input_worst_flag == input$worst_flag_indicator), - "There's no positive flag, please select another flag parameter." - )) - # validate inputs validate_standard_inputs( adsl = adsl_filtered, adslvars = c("USUBJID", "STUDYID", input_arm_var), anl = anl_filtered, anlvars = c( - "USUBJID", "STUDYID", input_visit_var, input_paramcd, input_worst_flag_var, + "USUBJID", "STUDYID", input_visit_var, input_paramcd_var, input_worst_flag_var, input_anl_toxgrade_var, input_base_toxgrade_var ), arm_var = input_arm_var ) }) - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - my_calls <- template_shift_by_grade( parentname = "ANL_ADSL", dataname = "ANL", - arm_var = as.vector(anl_m$columns_source$arm_var), - visit_var = as.vector(anl_m$columns_source$visit_var), - id_var = as.vector(anl_m$columns_source$id_var), - worst_flag_var = as.vector(anl_m$columns_source$worst_flag_var), + arm_var = names(merged$anl_input_r()$columns_source$arm_var), + visit_var = names(merged$anl_input_r()$columns_source$visit_var), + id_var = names(merged$anl_input_r()$columns_source$id_var), + worst_flag_var = names(merged$anl_input_r()$columns_source$worst_flag_var), worst_flag_indicator = input$worst_flag_indicator, - anl_toxgrade_var = as.vector(anl_m$columns_source$anl_toxgrade_var), - base_toxgrade_var = as.vector(anl_m$columns_source$base_toxgrade_var), + anl_toxgrade_var = names(merged$anl_input_r()$columns_source$anl_toxgrade_var), + base_toxgrade_var = names(merged$anl_input_r()$columns_source$base_toxgrade_var), paramcd = unlist(paramcd$filter)["vars_selected"], drop_arm_levels = input$drop_arm_levels, add_total = input$add_total, @@ -833,15 +830,12 @@ srv_t_shift_by_grade <- function(id, code_missing_baseline = input$code_missing_baseline, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), name = "tm_t_shift_by_grade call") }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", @@ -849,17 +843,10 @@ srv_t_shift_by_grade <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list( - arm_var, id_var, paramcd, worst_flag_var, - anl_toxgrade_var, base_toxgrade_var - ) - ), - modal_title = "R Code for Grade Laboratory Abnormalities", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -868,19 +855,16 @@ srv_t_shift_by_grade <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Grade Summary Table") card$append_text("Grade Summary Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_smq.R b/R/tm_t_smq.R index 44d34e9fa1..877ed2185a 100644 --- a/R/tm_t_smq.R +++ b/R/tm_t_smq.R @@ -509,15 +509,16 @@ ui_t_smq <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) } srv_t_smq <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -528,12 +529,9 @@ srv_t_smq <- function(id, na_level, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - anl_selectors <- teal.transform::data_extract_multiple_srv( list( arm_var = arm_var, @@ -542,32 +540,43 @@ srv_t_smq <- function(id, scopes = scopes, llt = llt ), - datasets = datasets + datasets = data ) - - anl_merged <- teal.transform::data_merge_srv( + anl_merged_input <- teal.transform::merge_expression_srv( selector_list = anl_selectors, - datasets = datasets, + datasets = data, + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) - anl_m <- anl_merged() - anl_adsl <- adsl_merged() + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_id_var <- as.vector(anl_m$columns_source$id_var) - input_baskets <- as.vector(anl_m$columns_source$baskets) - input_scopes <- as.vector(anl_m$columns_source$scopes) - input_llt <- as.vector(anl_m$columns_source$llt) + input_arm_var <- names(merged$anl_input_r()$columns_source$arm_var) + input_id_var <- names(merged$anl_input_r()$columns_source$id_var) + input_baskets <- names(merged$anl_input_r()$columns_source$baskets) + input_scopes <- names(merged$anl_input_r()$columns_source$scopes) + input_llt <- names(merged$anl_input_r()$columns_source$llt) shiny::validate( shiny::need(input_id_var, "Please select a subject identifier."), @@ -590,39 +599,28 @@ srv_t_smq <- function(id, ) }) - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - my_calls <- template_smq( parentname = "ANL_ADSL", dataname = "ANL", - arm_var = anl_m$columns_source$arm_var, - llt = as.vector(anl_m$columns_source$llt), + arm_var = names(merged$anl_input_r()$columns_source$arm_var), + llt = names(merged$anl_input_r()$columns_source$llt), add_total = input$add_total, sort_criteria = input$sort_criteria, drop_arm_levels = input$drop_arm_levels, - baskets = as.vector(anl_m$columns_source$baskets), + baskets = names(merged$anl_input_r()$columns_source$baskets), na_level = na_level, - id_var = as.vector(anl_m$columns_source$id_var), + id_var = names(merged$anl_input_r()$columns_source$id_var), basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls), name = "tm_t_smq call") }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("pruned_and_sorted_result") - }) + table_r <- shiny::reactive(output_q()[["pruned_and_sorted_result"]]) teal.widgets::table_with_settings_srv( id = "table", @@ -630,14 +628,10 @@ srv_t_smq <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, id_var, baskets, scopes, llt) - ), - modal_title = "R Code for SMQ tables", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -646,19 +640,16 @@ srv_t_smq <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("SMQ Table Table") card$append_text("Adverse Events Table by Standardized `MedDRA` Query (SMQ)", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_summary.R b/R/tm_t_summary.R index a33e5f7b34..9e62033c3e 100644 --- a/R/tm_t_summary.R +++ b/R/tm_t_summary.R @@ -397,7 +397,7 @@ ui_summary <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -405,8 +405,9 @@ ui_summary <- function(id, ...) { #' @noRd srv_summary <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -416,33 +417,42 @@ srv_summary <- function(id, drop_arm_levels, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - - anl_selectors <- teal.transform::data_extract_multiple_srv( - list(arm_var = arm_var, summarize_vars = summarize_vars), - datasets = datasets - ) - - anl_merged <- teal.transform::data_merge_srv( - selector_list = anl_selectors, - datasets = datasets, + anl_merged_input <- teal.transform::merge_expression_module( + id = "anl_merge", + datasets = data, + data_extract = list(arm_var = arm_var, summarize_vars = summarize_vars), + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + id = "adsl_merge", + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var), anl_name = "ANL_ADSL" ) - shiny::observeEvent(anl_merged()$columns_source$summarize_vars, { + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + + shiny::observeEvent(merged$anl_input_r()$columns_source$summarize_vars, { choices_classes <- sapply( - anl_merged()$columns_source$summarize_vars, + names(merged$anl_input_r()$columns_source$summarize_vars), function(x) { - summarize_var_data <- datasets$get_data(summarize_vars$dataname)[[x]] + summarize_var_data <- data[[summarize_vars$dataname]]()[[x]] inherits(summarize_var_data, "numeric") | inherits(summarize_var_data, "integer") } @@ -457,16 +467,18 @@ srv_summary <- function(id, # validate inputs validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() + anl <- merged$anl_q_r()[["ANL"]] - anl_m <- anl_merged() - input_arm_var <- anl_merged()$columns_source$arm_var - input_summarize_vars <- anl_merged()$columns_source$summarize_vars + # we take names of the columns source as they match names of the input data in merge_datasets + # if we use $arm_var they might be renamed to .arm_var + input_arm_var <- names(merged$anl_input_r()$columns_source$arm_var) + input_summarize_vars <- names(merged$anl_input_r()$columns_source$summarize_vars) shiny::validate( shiny::need( - length(unique(anl_m$data()$USUBJID)) == nrow(anl_m$data()), + length(unique(anl$USUBJID)) == nrow(anl), paste0( "Please choose an analysis dataset where each row represents a different subject, ", "i.e. USUBJID is different in each row" @@ -475,7 +487,9 @@ srv_summary <- function(id, shiny::need(input_arm_var, "Please select a treatment variable"), shiny::need(input_summarize_vars, "Please select a summarize variable"), shiny::need( - !any(vapply(anl_m$data()[, input_summarize_vars], inherits, c("Date", "POSIXt"), FUN.VALUE = logical(1))), + !any(vapply(anl_filtered[, input_summarize_vars], inherits, c("Date", "POSIXt"), + FUN.VALUE = logical(1) + )), "Date and POSIXt variables are not supported, please select other variables" ), shiny::need(length(input_arm_var) <= 2, "Please limit treatment variables within two"), @@ -500,27 +514,19 @@ srv_summary <- function(id, }) # generate r code for the analysis - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - sum_vars <- anl_merged()$columns_source$summarize_vars - + summarize_vars <- merged$anl_input_r()$columns_source$summarize_vars + var_labels <- formatters::var_labels(data[[dataname]]()[, summarize_vars, drop = FALSE]) my_calls <- template_summary( dataname = "ANL", parentname = "ANL_ADSL", - arm_var = anl_merged()$columns_source$arm_var, - sum_vars = sum_vars, + arm_var = merged$anl_input_r()$columns_source$arm_var, + sum_vars = summarize_vars, show_labels = "visible", add_total = input$add_total, - var_labels = get_var_labels(datasets, dataname, sum_vars), + var_labels = var_labels, na.rm = ifelse(input$useNA == "ifany", FALSE, TRUE), # nolint na_level = na_level, numeric_stats = input$numeric_stats, @@ -528,28 +534,19 @@ srv_summary <- function(id, drop_arm_levels = input$drop_arm_levels, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) - }) - # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls)) }) - teal.widgets::table_with_settings_srv( - id = "table", - table_r = table_r - ) + # Outputs to render. + table_r <- shiny::reactive(output_q()[["result"]]) + teal.widgets::table_with_settings_srv(id = "table", table_r = table_r) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames(list(arm_var, summarize_vars)), - modal_title = "R Code for the current Summary Table", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -558,19 +555,16 @@ srv_summary <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Summary Table") card$append_text("Summary Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_summary_by.R b/R/tm_t_summary_by.R index a58463342f..fc504798d6 100644 --- a/R/tm_t_summary_by.R +++ b/R/tm_t_summary_by.R @@ -556,7 +556,7 @@ ui_summary_by <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -565,8 +565,9 @@ ui_summary_by <- function(id, ...) { #' @noRd srv_summary_by <- function(id, - datasets, + data, reporter, + filter_panel_api, dataname, parentname, arm_var, @@ -580,44 +581,51 @@ srv_summary_by <- function(id, drop_zero_levels, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") - + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - vars <- list(arm_var = arm_var, id_var = id_var, by_vars = by_vars, summarize_vars = summarize_vars) if (!is.null(paramcd)) { vars[["paramcd"]] <- paramcd } - anl_selectors <- teal.transform::data_extract_multiple_srv( - vars, - datasets = datasets - ) - - anl_merged <- teal.transform::data_merge_srv( + anl_selectors <- teal.transform::data_extract_multiple_srv(vars, datasets = data) + anl_merged_input <- teal.transform::merge_expression_srv( selector_list = anl_selectors, - datasets = datasets, + datasets = data, + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merged_input <- teal.transform::merge_expression_module( + id = "adsl_merge", + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var), anl_name = "ANL_ADSL" ) + anl_merged_q <- reactive({ + teal.code::new_quosure(env = data) %>% + teal.code::eval_code(as.expression(anl_merged_input()$expr)) %>% + teal.code::eval_code(as.expression(adsl_merged_input()$expr)) + }) + + merged <- list( + anl_input_r = anl_merged_input, + adsl_input_r = adsl_merged_input, + anl_q_r = anl_merged_q + ) + # Prepare the analysis environment (filter data, check data, populate envir). validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) - - anl_m <- anl_merged() - input_arm_var <- as.vector(anl_m$columns_source$arm_var) - input_id_var <- as.vector(anl_m$columns_source$id_var) - input_by_vars <- as.vector(anl_m$columns_source$by_vars) - input_summarize_vars <- as.vector(anl_m$columns_source$summarize_vars) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() + + input_arm_var <- names(merged$anl_input_r()$columns_source$arm_var) + input_id_var <- names(merged$anl_input_r()$columns_source$id_var) + input_by_vars <- names(merged$anl_input_r()$columns_source$by_vars) + input_summarize_vars <- names(merged$anl_input_r()$columns_source$summarize_var) input_paramcd <- `if`(is.null(paramcd), NULL, unlist(paramcd$filter)["vars_selected"]) # validate inputs @@ -650,26 +658,19 @@ srv_summary_by <- function(id, }) # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() + summarize_vars <- as.vector(merged$anl_input_r()$columns_source$summarize_vars) + var_labels <- formatters::var_labels(data[[dataname]]()[, summarize_vars, drop = FALSE]) my_calls <- template_summary_by( parentname = "ANL_ADSL", dataname = "ANL", - arm_var = as.vector(anl_m$columns_source$arm_var), - sum_vars = as.vector(anl_m$columns_source$summarize_vars), - by_vars = as.vector(anl_m$columns_source$by_vars), - var_labels = get_var_labels(datasets, dataname, as.vector(anl_m$columns_source$summarize_vars)), - id_var = as.vector(anl_m$columns_source$id_var), + arm_var = as.vector(merged$anl_input_r()$columns_source$arm_var), + sum_vars = summarize_vars, + by_vars = as.vector(merged$anl_input_r()$columns_source$by_vars), + var_labels = var_labels, + id_var = as.vector(merged$anl_input_r()$columns_source$id_var), na.rm = ifelse(input$useNA == "ifany", FALSE, TRUE), na_level = na_level, numeric_stats = input$numeric_stats, @@ -681,15 +682,12 @@ srv_summary_by <- function(id, drop_zero_levels = input$drop_zero_levels, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) + + teal.code::eval_code(merged$anl_q_r(), as.expression(my_calls)) }) # Outputs to render. - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") - }) + table_r <- shiny::reactive(output_q()[["result"]]) teal.widgets::table_with_settings_srv( id = "table", @@ -697,14 +695,10 @@ srv_summary_by <- function(id, ) # Render R code. - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, id_var, paramcd, by_vars, summarize_vars) - ), - modal_title = "Summary by Row Groups Table", - code_header = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -713,19 +707,16 @@ srv_summary_by <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Summarize Variables by Row Groups Table") card$append_text("Summarize Variables by Row Groups Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/tm_t_tte.R b/R/tm_t_tte.R index 0464139f48..83a0218810 100644 --- a/R/tm_t_tte.R +++ b/R/tm_t_tte.R @@ -332,8 +332,8 @@ template_tte <- function(dataname = "ANL", y$table <- substitute( expr = { - result <- rtables::build_table(lyt = lyt, df = anl, alt_counts_df = parentname) - result + table <- rtables::build_table(lyt = lyt, df = anl, alt_counts_df = parentname) + table }, env = list(parentname = as.name(parentname)) ) @@ -675,7 +675,7 @@ ui_t_tte <- function(id, ...) { ) ) ), - forms = teal::get_rcode_ui(ns("rcode")), + forms = teal.widgets::verbatim_popup_ui(ns("rcode"), "Show R code"), pre_output = a$pre_output, post_output = a$post_output ) @@ -683,7 +683,8 @@ ui_t_tte <- function(id, ...) { #' @noRd srv_t_tte <- function(id, - datasets, + data, + filter_panel_api, reporter, arm_var, paramcd, @@ -698,11 +699,9 @@ srv_t_tte <- function(id, add_total, label, basic_table_args) { - stopifnot(is_cdisc_data(datasets)) with_reporter <- !missing(reporter) && inherits(reporter, "Reporter") + with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelAPI") shiny::moduleServer(id, function(input, output, session) { - teal.code::init_chunks() - # Setup arm variable selection, default reference arms, and default # comparison arms for encoding panel arm_ref_comp_observer( @@ -710,15 +709,14 @@ srv_t_tte <- function(id, input, output, id_arm_var = extract_input("arm_var", parentname), - datasets = datasets, - dataname = parentname, + data = data[[parentname]], arm_ref_comp = arm_ref_comp, module = "tm_t_tte", on_off = shiny::reactive(input$compare_arms) ) - anl_merged <- teal.transform::data_merge_module( - datasets = datasets, + anl_merge_inputs <- teal.transform::merge_expression_module( + datasets = data, data_extract = list( arm_var = arm_var, paramcd = paramcd, @@ -728,21 +726,30 @@ srv_t_tte <- function(id, event_desc_var = event_desc_var, time_unit_var = time_unit_var ), + join_keys = attr(data, "join_keys"), merge_function = "dplyr::inner_join" ) - adsl_merged <- teal.transform::data_merge_module( - datasets = datasets, + adsl_merge_inputs <- teal.transform::merge_expression_module( + datasets = data, + join_keys = attr(data, "join_keys"), data_extract = list(arm_var = arm_var, strata_var = strata_var), anl_name = "ANL_ADSL" ) + merged_q <- reactive({ + quo <- teal.code::new_quosure(data) + quo1 <- teal.code::eval_code(quo, as.expression(anl_merge_inputs()$expr)) + teal.code::eval_code(quo1, as.expression(adsl_merge_inputs()$expr)) + }) + # Prepare the analysis environment (filter data, check data, populate envir). validate_checks <- shiny::reactive({ - adsl_filtered <- datasets$get_data(parentname, filtered = TRUE) - anl_filtered <- datasets$get_data(dataname, filtered = TRUE) + adsl_filtered <- data[[parentname]]() + anl_filtered <- data[[dataname]]() + anl <- merged_q()[["ANL"]] - anl_m <- anl_merged() + anl_m <- anl_merge_inputs() input_arm_var <- as.vector(anl_m$columns_source$arm_var) input_strata_var <- as.vector(anl_m$columns_source$strata_var) input_aval_var <- as.vector(anl_m$columns_source$aval_var) @@ -797,7 +804,7 @@ srv_t_tte <- function(id, # check that there is at least one record with no missing data shiny::validate(shiny::need( - !all(is.na(anl_m$data()[[input_aval_var]])), + !all(is.na(anl[[input_aval_var]])), "ANCOVA table cannot be calculated as all values are missing." )) @@ -811,19 +818,11 @@ srv_t_tte <- function(id, # The R-code corresponding to the analysis. - call_preparation <- shiny::reactive({ + output_q <- shiny::reactive({ validate_checks() - teal.code::chunks_reset() - anl_m <- anl_merged() - teal.code::chunks_push_data_merge(anl_m) - teal.code::chunks_push_new_line() - - anl_adsl <- adsl_merged() - teal.code::chunks_push_data_merge(anl_adsl) - teal.code::chunks_push_new_line() - - ANL <- teal.code::chunks_get_var("ANL") # nolint + anl_m <- anl_merge_inputs() + q1 <- merged_q() strata_var <- as.vector(anl_m$columns_source$strata_var) @@ -861,27 +860,18 @@ srv_t_tte <- function(id, add_total = input$add_total, basic_table_args = basic_table_args ) - mapply(expression = my_calls, id = paste(names(my_calls), "call", sep = "_"), teal.code::chunks_push) - }) - table_r <- shiny::reactive({ - call_preparation() - teal.code::chunks_safe_eval() - teal.code::chunks_get_var("result") + teal.code::eval_code(q1, as.expression(my_calls)) }) - teal.widgets::table_with_settings_srv( - id = "table", - table_r = table_r - ) + table_r <- shiny::reactive(output_q()[["table"]]) + + teal.widgets::table_with_settings_srv(id = "table", table_r = table_r) - teal::get_rcode_srv( + teal.widgets::verbatim_popup_srv( id = "rcode", - datasets = datasets, - datanames = teal.transform::get_extract_datanames( - list(arm_var, paramcd, strata_var, event_desc_var) - ), - modal_title = label + verbatim_content = reactive(teal.code::get_code(output_q())), + title = label ) ### REPORTER @@ -890,19 +880,16 @@ srv_t_tte <- function(id, card <- teal.reporter::TealReportCard$new() card$set_name("Time To Event Table") card$append_text("Time To Event Table", "header2") - card$append_fs(datasets$get_filter_state()) + if (with_filter) { + card$append_fs(filter_panel_api$get_filter_state()) + } card$append_text("Table", "header3") card$append_table(table_r()) if (!comment == "") { card$append_text("Comment", "header3") card$append_text(comment) } - card$append_src(paste(get_rcode( - chunks = teal.code::get_chunks_object(parent_idx = 2L), - datasets = datasets, - title = "", - description = "" - ), collapse = "\n")) + card$append_src(paste(teal.code::get_code(output_q()), collapse = "\n")) card } teal.reporter::simple_reporter_srv("simple_reporter", reporter = reporter, card_fun = card_fun) diff --git a/R/utils.R b/R/utils.R index 9caa961ac4..f157f53341 100644 --- a/R/utils.R +++ b/R/utils.R @@ -32,23 +32,20 @@ call_concatenate <- function(args, bin_op = "+") { } # needs columns like n_, n_ARM etc. to get count from -add_count_str_to_column <- function(chunk, column, n_column = NULL) { - n_column <- `if`(is.null(n_column), get_n_name(groupby_vars = column), n_column) +count_str_to_column_expr <- function(column, n_column = get_n_name(groupby_vars = column)) { checkmate::assert_string(column) - chunk$push( - substitute( - counts <- counts %>% dplyr::mutate( - column_name := paste0(column_name, " (n = ", n_column_name, ")") - ), - env = list(column_name = as.symbol(column), n_column_name = as.symbol(n_column)) + substitute_names( + expr = counts <- counts %>% dplyr::mutate( + column_name = paste0(column_name, " (n = ", n_column_name, ")") ), - id = paste0(column, "_add_count_str_to_column_call") + names = list(column_name = as.symbol(column), n_column_name = as.symbol(n_column)) ) } #' Get variable labels #' +#' @description `r lifecycle::badge("deprecated")` #' @param datasets (`teal::FilteredData`) Data built up by teal #' @param dataname (`character`) name of the dataset #' @param vars (`character`) Column names in the data @@ -57,6 +54,13 @@ add_count_str_to_column <- function(chunk, column, n_column = NULL) { #' #' @export get_var_labels <- function(datasets, dataname, vars) { + lifecycle::deprecate_warn( + when = "0.8.14", + what = "get_var_labels()", + with = "formatters::var_labels()", + details = "teal.modules.clinical won't export any utility functions except those which + are necessary to prepare shiny app." + ) labels <- datasets$get_varlabels(dataname, vars) labels <- vapply(vars, function(x) ifelse(is.na(labels[[x]]), x, labels[[x]]), character(1)) return(labels) @@ -793,10 +797,6 @@ color_lab_values <- function(x, } } -is_cdisc_data <- function(datasets) { - inherits(datasets, "CDISCFilteredData") -} - #' Clean a categorical variable descriptions #' #' Cleaning categorical variable descriptions before presenting. diff --git a/R/validate_standard_inputs.R b/R/validate_standard_inputs.R index 00207592a6..1fc19d8115 100644 --- a/R/validate_standard_inputs.R +++ b/R/validate_standard_inputs.R @@ -173,11 +173,11 @@ validate_standard_inputs <- function(adsl, #' @keywords internal #' validate_arm <- function(arm_vec) { + shiny::validate(shiny::need(is.factor(arm_vec), "Treatment variable is not a factor")) shiny::validate( shiny::need( - all(trimws(as.character(arm_vec)) != ""), + all(trimws(levels(arm_vec)) != ""), "Treatment values cannot contain empty strings" ) ) - shiny::validate(shiny::need(is.factor(arm_vec), "Treatment variable is not a factor")) } diff --git a/man/arm_ref_comp_observer.Rd b/man/arm_ref_comp_observer.Rd index 4a4be61936..cfbd621f3c 100644 --- a/man/arm_ref_comp_observer.Rd +++ b/man/arm_ref_comp_observer.Rd @@ -11,8 +11,7 @@ arm_ref_comp_observer( id_ref = "Ref", id_comp = "Comp", id_arm_var, - datasets, - dataname = "ADSL", + data, arm_ref_comp, module, on_off = shiny::reactive(TRUE), @@ -33,9 +32,8 @@ arm_ref_comp_observer( \item{id_arm_var}{(\code{character}) id of Treatment variable input ui element} -\item{datasets}{(\code{FilteredData}) object from the module} - -\item{dataname}{(\code{character}) dataset name} +\item{data}{(\code{reactive} or \code{data.frame}) dataset used to validate Treatment reference inputs and +set \code{id_ref} input.} \item{arm_ref_comp}{(\code{unknown}) Treatment reference and compare variables provided as a nested list where each Treatment variable corresponds a list specifying the default levels for the diff --git a/man/get_var_labels.Rd b/man/get_var_labels.Rd index 0f11d2f182..bded08d4ec 100644 --- a/man/get_var_labels.Rd +++ b/man/get_var_labels.Rd @@ -17,5 +17,5 @@ get_var_labels(datasets, dataname, vars) \code{character} variable labels. } \description{ -Get variable labels +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } diff --git a/man/module_arguments.Rd b/man/module_arguments.Rd index 957d8afbf1..4d4d592fb0 100644 --- a/man/module_arguments.Rd +++ b/man/module_arguments.Rd @@ -7,7 +7,8 @@ \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{arm_ref_comp}{optional, (\code{list})\cr diff --git a/man/tm_a_mmrm.Rd b/man/tm_a_mmrm.Rd index c290760ed2..015223dff7 100644 --- a/man/tm_a_mmrm.Rd +++ b/man/tm_a_mmrm.Rd @@ -46,7 +46,8 @@ object specifying the variable name for subject id.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{visit_var}{(\code{choices_selected} or \code{data_extract_spec})\cr diff --git a/man/tm_g_forest_rsp.Rd b/man/tm_g_forest_rsp.Rd index 3d520670da..46434da273 100644 --- a/man/tm_g_forest_rsp.Rd +++ b/man/tm_g_forest_rsp.Rd @@ -41,7 +41,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{arm_ref_comp}{optional, (\code{list})\cr diff --git a/man/tm_g_forest_tte.Rd b/man/tm_g_forest_tte.Rd index fd1471196d..e1f6368842 100644 --- a/man/tm_g_forest_tte.Rd +++ b/man/tm_g_forest_tte.Rd @@ -44,7 +44,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{arm_ref_comp}{optional, (\code{list})\cr diff --git a/man/tm_g_km.Rd b/man/tm_g_km.Rd index 0b289676e8..b4ef158f45 100644 --- a/man/tm_g_km.Rd +++ b/man/tm_g_km.Rd @@ -42,7 +42,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{arm_ref_comp}{optional, (\code{list})\cr diff --git a/man/tm_t_abnormality.Rd b/man/tm_t_abnormality.Rd index e8e54c9218..00ae27116f 100644 --- a/man/tm_t_abnormality.Rd +++ b/man/tm_t_abnormality.Rd @@ -46,7 +46,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{by_vars}{(\code{choices_selected} or \code{data_extract_spec})\cr diff --git a/man/tm_t_abnormality_by_worst_grade.Rd b/man/tm_t_abnormality_by_worst_grade.Rd index 79f49bed41..5a9c5fd10a 100644 --- a/man/tm_t_abnormality_by_worst_grade.Rd +++ b/man/tm_t_abnormality_by_worst_grade.Rd @@ -45,7 +45,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{id_var}{(\code{choices_selected} or \code{data_extract_spec})\cr diff --git a/man/tm_t_ancova.Rd b/man/tm_t_ancova.Rd index f0b58b71e2..ff097f73c7 100644 --- a/man/tm_t_ancova.Rd +++ b/man/tm_t_ancova.Rd @@ -35,7 +35,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{arm_ref_comp}{optional, (\code{list})\cr diff --git a/man/tm_t_binary_outcome.Rd b/man/tm_t_binary_outcome.Rd index ca68793a54..94360d35b7 100644 --- a/man/tm_t_binary_outcome.Rd +++ b/man/tm_t_binary_outcome.Rd @@ -40,7 +40,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{arm_ref_comp}{optional, (\code{list})\cr diff --git a/man/tm_t_coxreg.Rd b/man/tm_t_coxreg.Rd index 56f33e43af..f0efa44785 100644 --- a/man/tm_t_coxreg.Rd +++ b/man/tm_t_coxreg.Rd @@ -39,7 +39,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{arm_ref_comp}{optional, (\code{list})\cr diff --git a/man/tm_t_events.Rd b/man/tm_t_events.Rd index 760ccc5a52..126ed457cb 100644 --- a/man/tm_t_events.Rd +++ b/man/tm_t_events.Rd @@ -36,7 +36,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{hlt}{(\code{choices_selected} or \code{data_extract_spec})\cr diff --git a/man/tm_t_events_by_grade.Rd b/man/tm_t_events_by_grade.Rd index 9633c6f053..ca60caaf9f 100644 --- a/man/tm_t_events_by_grade.Rd +++ b/man/tm_t_events_by_grade.Rd @@ -38,7 +38,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{hlt}{(\code{choices_selected} or \code{data_extract_spec})\cr diff --git a/man/tm_t_events_patyear.Rd b/man/tm_t_events_patyear.Rd index 7e59d227ea..6b9dd4a725 100644 --- a/man/tm_t_events_patyear.Rd +++ b/man/tm_t_events_patyear.Rd @@ -38,7 +38,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{events_var}{(\code{\link[teal.transform:choices_selected]{teal.transform::choices_selected()}} or \code{\link[teal.transform:data_extract_spec]{teal.transform::data_extract_spec()}})\cr diff --git a/man/tm_t_events_summary.Rd b/man/tm_t_events_summary.Rd index 0d36cfebd0..10503aa4fb 100644 --- a/man/tm_t_events_summary.Rd +++ b/man/tm_t_events_summary.Rd @@ -44,7 +44,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{flag_var_anl}{(\code{\link[teal.transform:choices_selected]{teal.transform::choices_selected()}} or \code{\link[teal.transform:data_extract_spec]{teal.transform::data_extract_spec()}})\cr diff --git a/man/tm_t_mult_events.Rd b/man/tm_t_mult_events.Rd index bcd57d56aa..9ed4a520a1 100644 --- a/man/tm_t_mult_events.Rd +++ b/man/tm_t_mult_events.Rd @@ -34,7 +34,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{seq_var}{(\code{\link[teal.transform:choices_selected]{teal.transform::choices_selected()}} or \code{\link[teal.transform:data_extract_spec]{teal.transform::data_extract_spec()}})\cr diff --git a/man/tm_t_shift_by_arm.Rd b/man/tm_t_shift_by_arm.Rd index f3fc34d60a..07d14f653b 100644 --- a/man/tm_t_shift_by_arm.Rd +++ b/man/tm_t_shift_by_arm.Rd @@ -41,7 +41,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{paramcd}{(\code{choices_selected} or \code{data_extract_spec})\cr diff --git a/man/tm_t_shift_by_arm_by_worst.Rd b/man/tm_t_shift_by_arm_by_worst.Rd index 65c7c6c1af..c92b616e59 100644 --- a/man/tm_t_shift_by_arm_by_worst.Rd +++ b/man/tm_t_shift_by_arm_by_worst.Rd @@ -42,7 +42,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{paramcd}{(\code{choices_selected} or \code{data_extract_spec})\cr diff --git a/man/tm_t_shift_by_grade.Rd b/man/tm_t_shift_by_grade.Rd index 8e1b0287dd..24de753bfc 100644 --- a/man/tm_t_shift_by_grade.Rd +++ b/man/tm_t_shift_by_grade.Rd @@ -49,7 +49,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{visit_var}{(\code{\link[teal.transform:choices_selected]{teal.transform::choices_selected()}} or \code{\link[teal.transform:data_extract_spec]{teal.transform::data_extract_spec()}})\cr diff --git a/man/tm_t_smq.Rd b/man/tm_t_smq.Rd index 922f23be85..95d6d7a49b 100644 --- a/man/tm_t_smq.Rd +++ b/man/tm_t_smq.Rd @@ -38,7 +38,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{id_var}{(\code{choices_selected} or \code{data_extract_spec})\cr diff --git a/man/tm_t_summary_by.Rd b/man/tm_t_summary_by.Rd index dff34c369d..ac3b63af82 100644 --- a/man/tm_t_summary_by.Rd +++ b/man/tm_t_summary_by.Rd @@ -43,7 +43,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{by_vars}{(\code{choices_selected} or \code{data_extract_spec})\cr diff --git a/man/tm_t_tte.Rd b/man/tm_t_tte.Rd index 04a4a7576b..9157813648 100644 --- a/man/tm_t_tte.Rd +++ b/man/tm_t_tte.Rd @@ -45,7 +45,8 @@ parent analysis data used in teal module, usually this refers to \code{ADSL}.} \item{arm_var}{(\code{choices_selected} or \code{data_extract_spec})\cr object with all available choices and preselected option for variable names that can be used as \code{arm_var}. -It defines the grouping variable(s) in the results table. If there are two elements selected for \code{arm_var}, +It defines the grouping variable(s) in the results table. +If there are two elements selected for \code{arm_var}, second variable will be nested under the first variable.} \item{arm_ref_comp}{optional, (\code{list})\cr diff --git a/tests/testthat/test-tm_g_km.R b/tests/testthat/test-tm_g_km.R index a8a5042ebe..bf70c4f41d 100644 --- a/tests/testthat/test-tm_g_km.R +++ b/tests/testthat/test-tm_g_km.R @@ -14,7 +14,7 @@ testthat::test_that("template_g_km works as expected with default arguments", { lyt <- grid::grid.layout(nrow = nlevels(ANL$SEX), ncol = 1) %>% grid::viewport(layout = .) %>% grid::pushViewport() - result <- mapply( + plot_list <- mapply( df = split(anl, f = anl$SEX), nrow = seq_along(levels(anl$SEX)), FUN = function(df_i, nrow_i) { if (nrow(df_i) == 0) { @@ -55,8 +55,8 @@ testthat::test_that("template_g_km works as expected with default arguments", { } }, SIMPLIFY = FALSE ) - km_grobs <- tern::stack_grobs(grobs = result) - km_grobs + plot <- tern::stack_grobs(grobs = plot_list) + plot }) ) testthat::expect_equal(result, expected) diff --git a/tests/testthat/test-tm_g_lineplot.R b/tests/testthat/test-tm_g_lineplot.R index a2bc9f3715..a18b509575 100644 --- a/tests/testthat/test-tm_g_lineplot.R +++ b/tests/testthat/test-tm_g_lineplot.R @@ -14,7 +14,7 @@ testthat::test_that("template_g_lineplot works as expected with default argument ), graph = quote({ grid::grid.newpage() - result <- g_lineplot( + plot <- g_lineplot( df = anl, variables = variables, interval = "mean_ci", @@ -34,7 +34,7 @@ testthat::test_that("template_g_lineplot works as expected with default argument subtitle_add_paramcd = FALSE, subtitle_add_unit = FALSE ) - result + plot }) ) testthat::expect_equal(result, expected) @@ -66,7 +66,7 @@ testthat::test_that("template_g_lineplot gives correct data expression with cust ), graph = quote({ grid::grid.newpage() - result <- g_lineplot( + plot <- g_lineplot( df = anl, variables = variables, interval = "median_ci", @@ -85,7 +85,7 @@ testthat::test_that("template_g_lineplot gives correct data expression with cust subtitle_add_paramcd = FALSE, subtitle_add_unit = FALSE ) - result + plot }) ) testthat::expect_equal(result, expected) diff --git a/tests/testthat/test-tm_t_tte.R b/tests/testthat/test-tm_t_tte.R index 53245589f7..2cb93f002c 100644 --- a/tests/testthat/test-tm_t_tte.R +++ b/tests/testthat/test-tm_t_tte.R @@ -94,8 +94,8 @@ testthat::test_that("template_tte produces healthy standard output", { ) ), table = quote({ - result <- rtables::build_table(lyt = lyt, df = anl, alt_counts_df = ANL_ADSL) - result + table <- rtables::build_table(lyt = lyt, df = anl, alt_counts_df = ANL_ADSL) + table }) ) @@ -254,8 +254,8 @@ testthat::test_that("template_tte produces correct data expression when comparin ) ), table = quote({ - result <- rtables::build_table(lyt = lyt, df = anl, alt_counts_df = ANL_ADSL) - result + table <- rtables::build_table(lyt = lyt, df = anl, alt_counts_df = ANL_ADSL) + table }) ) testthat::expect_equal(result, expected) @@ -365,8 +365,8 @@ testthat::test_that("template_tte produces correct data expression when comparin ) ), table = quote({ - result <- rtables::build_table(lyt = lyt, df = anl, alt_counts_df = ANL_ADSL) - result + table <- rtables::build_table(lyt = lyt, df = anl, alt_counts_df = ANL_ADSL) + table }) ) testthat::expect_equal(result, expected) diff --git a/tests/testthat/test-validate_standard_inputs.R b/tests/testthat/test-validate_standard_inputs.R index 258876e56f..fb69ab3d3c 100644 --- a/tests/testthat/test-validate_standard_inputs.R +++ b/tests/testthat/test-validate_standard_inputs.R @@ -15,13 +15,13 @@ testthat::test_that("validate_arm throws shiny error if arm_vec is not a factor" testthat::test_that("validate_arm throws specific shiny error if arm_vec has just whitespace strings", { testthat::expect_error( - validate_arm(c("A", " ")), + validate_arm(as.factor(c("A", " "))), "Treatment values cannot contain empty strings", class = "shiny.silent.error" ) testthat::expect_error( - validate_arm(c("A", "")), + validate_arm(as.factor(c("A", ""))), "Treatment values cannot contain empty strings", class = "shiny.silent.error" )