Skip to content

Commit

Permalink
Update forest plots following refactor of g_forest (#911)
Browse files Browse the repository at this point in the history
# Pull Request

<!--- Replace `#nnn` with your issue link for reference. -->

Fixes #910

---------

Signed-off-by: Joe Zhu <sha.joe.zhu@gmail.com>
Co-authored-by: Joe Zhu <sha.joe.zhu@gmail.com>
Co-authored-by: Davide Garolini <davide.garolini@roche.com>
  • Loading branch information
3 people authored Jan 3, 2024
1 parent 3839434 commit 3339d51
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 75 deletions.
5 changes: 3 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ Depends:
R (>= 4.0),
teal (>= 0.14.0.9027),
teal.transform (>= 0.4.0.9011),
tern (>= 0.9.3)
tern (>= 0.9.3.9002)
Imports:
assertthat,
broom,
checkmate,
cowplot (>= 0.7.0),
dplyr,
DT,
formatters (>= 0.5.5),
Expand All @@ -44,7 +45,7 @@ Imports:
magrittr,
methods,
rlang,
rlistings (>= 0.2.4),
rlistings (>= 0.2.7),
rmarkdown,
rtables (>= 0.6.6),
scales,
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Added parameter `sort_freq_col` to `tm_t_events` to allow the user to select column to use when sorting by decreasing frequency.
* Added parameter `incl_overall_sum` to `tm_t_events` to allow the user to choose whether overall summary rows are included at the top of the table.
* Updated the documentation and vignettes to demonstrate method to pass `teal_data` object to `teal::init()`.
* Updated `tm_g_forest_rsp` and `tm_g_forest_tte` to use refactored version of `g_forest`. Plots are now displayed as `ggplot` objects instead of `grob` objects. Added parameters `font_size` and `rel_width_forest` to control font size and width of plot relative to table, respectively.

### Bug fixes
* Fixed bug in `tm_g_lineplot` forcing module to initialize with a table.
Expand Down
87 changes: 65 additions & 22 deletions R/tm_g_forest_rsp.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#'
#' Creates a valid expression for response forest plot.
#'
#' @inheritParams tern::g_forest
#' @inheritParams template_arguments
#' @param obj_var_name (`character`)\cr additional text string append to output title.
#' @param responders (`character`)\cr values of `aval_var` that are considered to be responders.
Expand Down Expand Up @@ -34,6 +35,8 @@ template_forest_rsp <- function(dataname = "ANL",
strata_var = NULL,
conf_level = 0.95,
col_symbol_size = NULL,
rel_width_forest = 0.25,
font_size = 15,
ggplot2_args = teal.widgets::ggplot2_args()) {
assertthat::assert_that(
assertthat::is.string(dataname),
Expand All @@ -43,6 +46,8 @@ template_forest_rsp <- function(dataname = "ANL",
assertthat::is.string(obj_var_name),
is.null(subgroup_var) || is.character(subgroup_var)
)
checkmate::assert_number(rel_width_forest, lower = 0, upper = 1)
checkmate::assert_number(font_size)

y <- list()
ref_arm_val <- paste(ref_arm, collapse = "/")
Expand Down Expand Up @@ -160,34 +165,55 @@ template_forest_rsp <- function(dataname = "ANL",
all_ggplot2_args <- teal.widgets::resolve_ggplot2_args(
user_plot = ggplot2_args,
module_plot = teal.widgets::ggplot2_args(
labs = list(title = paste0("Forest plot of best overall response for ", obj_var_name), caption = "")
labs = list(
title = paste("Forest Plot of Best Overall Response for", obj_var_name),
caption = ""
)
)
)

plot_call <- substitute(
expr = g_forest(
tbl = result,
col_symbol_size = col_s_size
),
env = list(col_s_size = col_symbol_size)
)
plot_list <- list()

plot_call <- substitute(
decorate_grob(p, titles = title, footnotes = caption, gp_footnotes = grid::gpar(fontsize = 12)),
env = list(title = all_ggplot2_args$labs$title, caption = all_ggplot2_args$labs$caption, p = plot_call)
plot_list <- add_expr(
plot_list,
substitute(
expr = {
f <- g_forest(
tbl = result,
col_symbol_size = col_s_size,
font_size = font_size,
as_list = TRUE
)
},
env = list(
col_s_size = col_symbol_size,
font_size = font_size
)
)
)

plot_call <- substitute(
expr = {
p <- plot_call
grid::grid.newpage()
grid::grid.draw(p)
},
env = list(plot_call = plot_call)
plot_list <- add_expr(
plot_list,
substitute(
expr = {
p <- cowplot::plot_grid(
f[["table"]] + ggplot2::labs(title = ggplot2_args_title),
f[["plot"]] + ggplot2::labs(caption = ggplot2_args_caption),
align = "h",
axis = "tblr",
rel_widths = c(1 - rel_width_forest, rel_width_forest)
)
},
env = list(
rel_width_forest = rel_width_forest,
ggplot2_args_title = all_ggplot2_args$labs$title,
ggplot2_args_caption = all_ggplot2_args$labs$caption
)
)
)

# Plot output.
y$plot <- plot_call
y$plot <- plot_list

y
}
Expand All @@ -196,6 +222,7 @@ template_forest_rsp <- function(dataname = "ANL",
#'
#' This teal module produces a grid style Forest plot for response data with `ADaM` structure.
#'
#' @inheritParams tern::g_forest
#' @inheritParams module_arguments
#' @inheritParams tm_t_binary_outcome
#' @param fixed_symbol_size (`logical`)\cr
Expand Down Expand Up @@ -314,8 +341,10 @@ tm_g_forest_rsp <- function(label,
fixed_symbol_size = TRUE,
conf_level = teal.transform::choices_selected(c(0.95, 0.9, 0.8), 0.95, keep_order = TRUE),
default_responses = c("CR", "PR", "Y", "Complete Response (CR)", "Partial Response (PR)"),
plot_height = c(700L, 200L, 2000L),
plot_width = c(1200L, 800L, 3000L),
plot_height = c(500L, 200L, 2000L),
plot_width = c(1500L, 800L, 3000L),
rel_width_forest = c(25L, 0L, 100L),
font_size = c(15L, 1L, 30L),
pre_output = NULL,
post_output = NULL,
ggplot2_args = teal.widgets::ggplot2_args()) {
Expand Down Expand Up @@ -442,7 +471,19 @@ ui_g_forest_rsp <- function(id, ...) {
multiple = FALSE,
fixed = a$conf_level$fixed
),
shiny::checkboxInput(ns("fixed_symbol_size"), "Fixed symbol size", value = TRUE)
shiny::checkboxInput(ns("fixed_symbol_size"), "Fixed symbol size", value = TRUE),
teal.widgets::optionalSliderInputValMinMax(
ns("rel_width_forest"),
"Relative Width of Forest Plot (%)",
a$rel_width_forest,
ticks = FALSE, step = 1
),
teal.widgets::optionalSliderInputValMinMax(
ns("font_size"),
"Table Font Size",
a$font_size,
ticks = FALSE, step = 1
)
)
)
),
Expand Down Expand Up @@ -692,6 +733,8 @@ srv_g_forest_rsp <- function(id,
strata_var = if (length(strata_var) != 0) strata_var else NULL,
conf_level = as.numeric(input$conf_level),
col_symbol_size = `if`(input$fixed_symbol_size, NULL, 1),
rel_width_forest = input$rel_width_forest / 100,
font_size = input$font_size,
ggplot2_args = ggplot2_args
)

Expand Down
96 changes: 65 additions & 31 deletions R/tm_g_forest_tte.R
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ template_forest_tte <- function(dataname = "ANL",
conf_level = 0.95,
col_symbol_size = NULL,
time_unit_var = "AVALU",
rel_width_forest = 0.25,
font_size = 15,
ggplot2_args = teal.widgets::ggplot2_args()) {
assertthat::assert_that(
assertthat::is.string(dataname),
assertthat::is.string(arm_var),
assertthat::is.string(obj_var_name),
is.character(subgroup_var) || is.null(subgroup_var)
)
checkmate::assert_number(rel_width_forest, lower = 0, upper = 1)
checkmate::assert_number(font_size)

y <- list()
ref_arm_val <- paste(ref_arm, collapse = "/")
Expand Down Expand Up @@ -162,45 +166,59 @@ template_forest_tte <- function(dataname = "ANL",
user_plot = ggplot2_args,
module_plot = teal.widgets::ggplot2_args(
labs = list(
title = paste("Forest Plot of Survival Duration for", obj_var_name),
subtitle = ifelse(is.null(strata_var), "", paste("Stratified by", paste(strata_var, collapse = " and "))),
title = paste(
paste("Forest Plot of Survival Duration for", obj_var_name),
ifelse(is.null(strata_var), "", paste("Stratified by", paste(strata_var, collapse = " and "))),
sep = "\n"
),
caption = ""
)
)
)

plot_call <- substitute(
expr = g_forest(
tbl = result,
col_symbol_size = col_s_size
),
env = list(col_s_size = col_symbol_size)
)
plot_list <- list()

plot_call <- substitute(
decorate_grob(p, titles = title, footnotes = caption, gp_footnotes = grid::gpar(fontsize = 12)),
env = list(
title = `if`(
all_ggplot2_args$labs$subtitle == "",
all_ggplot2_args$labs$title,
c(all_ggplot2_args$labs$title, all_ggplot2_args$labs$subtitle)
),
caption = all_ggplot2_args$labs$caption,
p = plot_call
plot_list <- add_expr(
plot_list,
substitute(
expr = {
f <- g_forest(
tbl = result,
col_symbol_size = col_s_size,
font_size = font_size,
as_list = TRUE
)
},
env = list(
col_s_size = col_symbol_size,
font_size = font_size
)
)
)

plot_call <- substitute(
env = list(plot_call = plot_call),
expr = {
p <- plot_call
grid::grid.newpage()
grid::grid.draw(p)
}
plot_list <- add_expr(
plot_list,
substitute(
expr = {
p <- cowplot::plot_grid(
f[["table"]] + ggplot2::labs(title = ggplot2_args_title, subtitle = ggplot2_args_subtitle),
f[["plot"]] + ggplot2::labs(caption = ggplot2_args_caption),
align = "h",
axis = "tblr",
rel_widths = c(1 - rel_width_forest, rel_width_forest)
)
},
env = list(
rel_width_forest = rel_width_forest,
ggplot2_args_title = all_ggplot2_args$labs$title,
ggplot2_args_subtitle = all_ggplot2_args$labs$subtitle,
ggplot2_args_caption = all_ggplot2_args$labs$caption
)
)
)

# Plot output.
y$plot <- plot_call
y$plot <- plot_list

y
}
Expand All @@ -210,6 +228,7 @@ template_forest_tte <- function(dataname = "ANL",
#' This teal module produces a grid style Forest plot for time-to-event data
#' with `ADaM` structure
#'
#' @inheritParams tern::g_forest
#' @inheritParams module_arguments
#' @inheritParams tm_g_forest_rsp
#' @param ggplot2_args optional, (`ggplot2_args`)\cr
Expand Down Expand Up @@ -271,8 +290,7 @@ template_forest_tte <- function(dataname = "ANL",
#' strata_var = choices_selected(
#' variable_choices(ADSL, c("STRATA1", "STRATA2")),
#' "STRATA2"
#' ),
#' plot_height = c(600, 200, 2000)
#' )
#' )
#' )
#' )
Expand Down Expand Up @@ -306,8 +324,10 @@ tm_g_forest_tte <- function(label,
fixed = TRUE
),
fixed_symbol_size = TRUE,
plot_height = c(700L, 200L, 2000L),
plot_width = c(1200L, 800L, 3000L),
plot_height = c(500L, 200L, 2000L),
plot_width = c(1500L, 800L, 3000L),
rel_width_forest = c(25L, 0L, 100L),
font_size = c(15L, 1L, 30L),
pre_output = NULL,
post_output = NULL,
ggplot2_args = teal.widgets::ggplot2_args()) {
Expand Down Expand Up @@ -443,6 +463,18 @@ ui_g_forest_tte <- function(id, ...) {
label = "Time Unit Variable",
data_extract_spec = a$time_unit_var,
is_single_dataset = is_single_dataset_value
),
teal.widgets::optionalSliderInputValMinMax(
ns("rel_width_forest"),
"Relative Width of Forest Plot (%)",
a$rel_width_forest,
ticks = FALSE, step = 1
),
teal.widgets::optionalSliderInputValMinMax(
ns("font_size"),
"Table Font Size",
a$font_size,
ticks = FALSE, step = 1
)
)
)
Expand Down Expand Up @@ -624,6 +656,8 @@ srv_g_forest_tte <- function(id,
conf_level = as.numeric(input$conf_level),
col_symbol_size = if (!input$fixed_symbol_size) 1,
time_unit_var = as.vector(anl_m$columns_source$time_unit_var),
rel_width_forest = input$rel_width_forest / 100,
font_size = input$font_size,
ggplot2_args = ggplot2_args
)
teal.code::eval_code(anl_q(), as.expression(my_calls))
Expand Down
7 changes: 7 additions & 0 deletions man/template_forest_rsp.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions man/template_forest_tte.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3339d51

Please sign in to comment.