1717# '
1818# ' @inherit shared_params return
1919# '
20+ # ' @section Decorating `tm_missing_data`:
21+ # '
22+ # ' This module generates the following objects, which can be modified in place using decorators:
23+ # ' - `summary_plot_top` (`ggplot2`)
24+ # ' - `summary_plot_bottom` (`ggplot2`)
25+ # ' - `combination_plot_top` (`ggplot2`)
26+ # ' - `combination_plot_bottom` (`ggplot2`)
27+ # ' - `table` ([DT::datatable()])
28+ # '
29+ # ' For additional details and examples of decorators, refer to the vignette
30+ # ' `vignette("decorate-modules-output", package = "teal")` or the [`teal_transform_module()`] documentation.
31+ # '
2032# ' @examplesShinylive
2133# ' library(teal.modules.general)
2234# ' interactive <- function() TRUE
@@ -87,7 +99,8 @@ tm_missing_data <- function(label = "Missing data",
8799 " Combinations Main" = teal.widgets :: ggplot2_args(labs = list (title = NULL ))
88100 ),
89101 pre_output = NULL ,
90- post_output = NULL ) {
102+ post_output = NULL ,
103+ decorators = NULL ) {
91104 message(" Initializing tm_missing_data" )
92105
93106 # Requires Suggested packages
@@ -121,14 +134,19 @@ tm_missing_data <- function(label = "Missing data",
121134
122135 checkmate :: assert_multi_class(pre_output , c(" shiny.tag" , " shiny.tag.list" , " html" ), null.ok = TRUE )
123136 checkmate :: assert_multi_class(post_output , c(" shiny.tag" , " shiny.tag.list" , " html" ), null.ok = TRUE )
137+ checkmate :: assert_list(decorators , " teal_transform_module" , null.ok = TRUE )
124138 # End of assertions
125139
126140 ans <- module(
127141 label ,
128142 server = srv_page_missing_data ,
129143 server_args = list (
130- parent_dataname = parent_dataname , plot_height = plot_height ,
131- plot_width = plot_width , ggplot2_args = ggplot2_args , ggtheme = ggtheme
144+ parent_dataname = parent_dataname ,
145+ plot_height = plot_height ,
146+ plot_width = plot_width ,
147+ ggplot2_args = ggplot2_args ,
148+ ggtheme = ggtheme ,
149+ decorators = decorators
132150 ),
133151 ui = ui_page_missing_data ,
134152 datanames = " all" ,
@@ -165,7 +183,7 @@ ui_page_missing_data <- function(id, pre_output = NULL, post_output = NULL) {
165183
166184# Server function for the missing data module (all datasets)
167185srv_page_missing_data <- function (id , data , reporter , filter_panel_api , parent_dataname ,
168- plot_height , plot_width , ggplot2_args , ggtheme ) {
186+ plot_height , plot_width , ggplot2_args , ggtheme , decorators ) {
169187 with_reporter <- ! missing(reporter ) && inherits(reporter , " Reporter" )
170188 with_filter <- ! missing(filter_panel_api ) && inherits(filter_panel_api , " FilterPanelAPI" )
171189 moduleServer(id , function (input , output , session ) {
@@ -215,7 +233,8 @@ srv_page_missing_data <- function(id, data, reporter, filter_panel_api, parent_d
215233 id = ns(x ),
216234 summary_per_patient = if_subject_plot ,
217235 ggtheme = ggtheme ,
218- datanames = datanames
236+ datanames = datanames ,
237+ decorators = decorators
219238 )
220239 )
221240 }
@@ -248,7 +267,8 @@ srv_page_missing_data <- function(id, data, reporter, filter_panel_api, parent_d
248267 parent_dataname = parent_dataname ,
249268 plot_height = plot_height ,
250269 plot_width = plot_width ,
251- ggplot2_args = ggplot2_args
270+ ggplot2_args = ggplot2_args ,
271+ decorators = decorators
252272 )
253273 }
254274 )
@@ -326,7 +346,7 @@ ui_missing_data <- function(id, by_subject_plot = FALSE) {
326346}
327347
328348# UI encoding for the missing data module (all datasets)
329- encoding_missing_data <- function (id , summary_per_patient = FALSE , ggtheme , datanames ) {
349+ encoding_missing_data <- function (id , summary_per_patient = FALSE , ggtheme , datanames , decorators ) {
330350 ns <- NS(id )
331351
332352 tagList(
@@ -401,6 +421,7 @@ encoding_missing_data <- function(id, summary_per_patient = FALSE, ggtheme, data
401421 )
402422 )
403423 ),
424+ ui_teal_transform_data(ns(" decorator" ), transformators = decorators ),
404425 teal.widgets :: panel_item(
405426 title = " Plot settings" ,
406427 selectInput(
@@ -416,7 +437,7 @@ encoding_missing_data <- function(id, summary_per_patient = FALSE, ggtheme, data
416437
417438# Server function for the missing data (single dataset)
418439srv_missing_data <- function (id , data , reporter , filter_panel_api , dataname , parent_dataname ,
419- plot_height , plot_width , ggplot2_args ) {
440+ plot_height , plot_width , ggplot2_args , decorators ) {
420441 with_reporter <- ! missing(reporter ) && inherits(reporter , " Reporter" )
421442 with_filter <- ! missing(filter_panel_api ) && inherits(filter_panel_api , " FilterPanelAPI" )
422443 checkmate :: assert_class(data , " reactive" )
@@ -718,7 +739,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
718739 qenv <- teal.code :: eval_code(
719740 qenv ,
720741 substitute(
721- p1 <- summary_plot_obs %> %
742+ summary_plot_top <- summary_plot_obs %> %
722743 ggplot() +
723744 aes(
724745 x = factor (create_cols_labels(col ), levels = x_levels ),
@@ -800,7 +821,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
800821 qenv <- teal.code :: eval_code(
801822 qenv ,
802823 substitute(
803- p2 <- summary_plot_patients %> %
824+ summary_plot_bottom <- summary_plot_patients %> %
804825 ggplot() +
805826 aes_(
806827 x = ~ factor (create_cols_labels(col ), levels = x_levels ),
@@ -833,33 +854,44 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
833854 ggthemes = parsed_ggplot2_args $ ggtheme
834855 )
835856 )
836- ) %> %
837- teal.code :: eval_code(
838- quote({
839- g1 <- ggplotGrob(p1 )
840- g2 <- ggplotGrob(p2 )
841- g <- gridExtra :: gtable_cbind(g1 , g2 , size = " first" )
842- g $ heights <- grid :: unit.pmax(g1 $ heights , g2 $ heights )
843- grid :: grid.newpage()
844- })
845- )
857+ )
858+ }
859+ qenv
860+ })
861+
862+
863+ decorated_summary_plot_q <- srv_teal_transform_data(id = " decorator" , data = summary_plot_q , transformators = decorators )
864+ decorated_summary_plot_grob_q <- reactive({
865+ q <- if (isTRUE(input $ if_patients_plot )) {
866+ within(
867+ decorated_summary_plot_q(),
868+ {
869+ g1 <- ggplotGrob(summary_plot_top )
870+ g2 <- ggplotGrob(summary_plot_bottom )
871+ g <- gridExtra :: gtable_cbind(g1 , g2 , size = " first" )
872+ g $ heights <- grid :: unit.pmax(g1 $ heights , g2 $ heights )
873+ grid :: grid.newpage()
874+ }
875+ )
846876 } else {
847- qenv <- teal.code :: eval_code (
848- qenv ,
849- quote( {
850- g <- ggplotGrob(p1 )
877+ within (
878+ decorated_summary_plot_q() ,
879+ {
880+ g <- ggplotGrob(summary_plot_top )
851881 grid :: grid.newpage()
852- })
882+ }
853883 )
854884 }
855-
856885 teal.code :: eval_code(
857- qenv ,
886+ q ,
858887 quote(grid :: grid.draw(g ))
859888 )
860889 })
861890
862- summary_plot_r <- reactive(summary_plot_q()[[" g" ]])
891+ summary_plot_r <- reactive({
892+ req(summary_plot_q())
893+ decorated_summary_plot_grob_q()[[" g" ]]
894+ })
863895
864896 combination_cutoff_q <- reactive({
865897 req(common_code_q())
@@ -976,7 +1008,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
9761008 qenv ,
9771009 substitute(
9781010 expr = {
979- p1 <- data_combination_plot_cutoff %> %
1011+ combination_plot_top <- data_combination_plot_cutoff %> %
9801012 dplyr :: select(id , n ) %> %
9811013 dplyr :: distinct() %> %
9821014 ggplot(aes(x = id , y = n )) +
@@ -994,7 +1026,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
9941026 graph_number_rows <- length(unique(data_combination_plot_cutoff $ id ))
9951027 graph_number_cols <- nrow(data_combination_plot_cutoff ) / graph_number_rows
9961028
997- p2 <- data_combination_plot_cutoff %> % ggplot() +
1029+ combination_plot_bottom <- data_combination_plot_cutoff %> % ggplot() +
9981030 aes(x = create_cols_labels(key ), y = id - 0.5 , fill = value ) +
9991031 geom_tile(alpha = 0.85 , height = 0.95 ) +
10001032 scale_fill_manual(
@@ -1009,13 +1041,6 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
10091041 ggthemes2 +
10101042 themes2
10111043
1012- g1 <- ggplotGrob(p1 )
1013- g2 <- ggplotGrob(p2 )
1014-
1015- g <- gridExtra :: gtable_rbind(g1 , g2 , size = " last" )
1016- g $ heights [7 ] <- grid :: unit(0.2 , " null" ) # rescale to get the bar chart smaller
1017- grid :: grid.newpage()
1018- grid :: grid.draw(g )
10191044 },
10201045 env = list (
10211046 labs1 = parsed_ggplot2_args1 $ labs ,
@@ -1029,7 +1054,26 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
10291054 )
10301055 })
10311056
1032- combination_plot_r <- reactive(combination_plot_q()[[" g" ]])
1057+ decorated_combination_plot_q <- srv_teal_transform_data(id = " decorator" , data = combination_plot_q , transformators = decorators )
1058+ decorated_combination_plot_grob_q <- reactive({
1059+ within(
1060+ decorated_combination_plot_q(),
1061+ {
1062+ g1 <- ggplotGrob(combination_plot_top )
1063+ g2 <- ggplotGrob(combination_plot_bottom )
1064+
1065+ g <- gridExtra :: gtable_rbind(g1 , g2 , size = " last" )
1066+ g $ heights [7 ] <- grid :: unit(0.2 , " null" ) # rescale to get the bar chart smaller
1067+ grid :: grid.newpage()
1068+ grid :: grid.draw(g )
1069+ }
1070+ )
1071+ })
1072+
1073+ combination_plot_r <- reactive({
1074+ req(combination_plot_q())
1075+ decorated_combination_plot_grob_q()[[" g" ]]
1076+ })
10331077
10341078 summary_table_q <- reactive({
10351079 req(
@@ -1108,10 +1152,15 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
11081152 )
11091153 }
11101154
1111- teal.code :: eval_code(qenv , quote(summary_data ))
1155+ teal.code :: eval_code(qenv , quote(table <- DT :: datatable( summary_data ) ))
11121156 })
11131157
1114- summary_table_r <- reactive(summary_table_q()[[" summary_data" ]])
1158+ decorated_summary_table_q <-
1159+ srv_teal_transform_data(id = " decorator" , data = summary_table_q , transformators = decorators )
1160+ summary_table_r <- reactive({
1161+ req(summary_table_q())
1162+ decorated_summary_table_q()[[" table" ]]
1163+ })
11151164
11161165 by_subject_plot_q <- reactive({
11171166 # needed to trigger show r code update on tab change
@@ -1188,7 +1237,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
11881237 teal.code :: eval_code(
11891238 substitute(
11901239 expr = {
1191- g <- ggplot(summary_plot_patients , aes(
1240+ plot <- ggplot(summary_plot_patients , aes(
11921241 x = factor (id , levels = order_subjects ),
11931242 y = factor (col , levels = ordered_columns [[" column" ]]),
11941243 fill = isna
@@ -1209,7 +1258,6 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
12091258 labs +
12101259 ggthemes +
12111260 themes
1212- print(g )
12131261 },
12141262 env = list (
12151263 labs = parsed_ggplot2_args $ labs ,
@@ -1220,7 +1268,13 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
12201268 )
12211269 })
12221270
1223- by_subject_plot_r <- reactive(by_subject_plot_q()[[" g" ]])
1271+ decorated_by_subject_plot_q <- srv_teal_transform_data(id = " decorator" , data = by_subject_plot_q , transformators = decorators )
1272+ decorated_by_subject_plot_print_q <- reactive(within(decorated_by_subject_plot_q(), print(plot )))
1273+
1274+ by_subject_plot_r <- reactive({
1275+ req(by_subject_plot_q()) # Ensure original errors are displayed
1276+ decorated_by_subject_plot_print_q()[[" plot" ]]
1277+ })
12241278
12251279 output $ levels_table <- DT :: renderDataTable(
12261280 expr = {
@@ -1272,7 +1326,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
12721326
12731327 teal.widgets :: verbatim_popup_srv(
12741328 id = " rcode" ,
1275- verbatim_content = reactive(teal.code :: get_code(final_q())),
1329+ verbatim_content = reactive(teal.code :: get_code(req( final_q() ))),
12761330 title = " Show R Code for Missing Data"
12771331 )
12781332
@@ -1308,7 +1362,7 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par
13081362 card $ append_text(" Comment" , " header3" )
13091363 card $ append_text(comment )
13101364 }
1311- card $ append_src(teal.code :: get_code(final_q()))
1365+ card $ append_src(teal.code :: get_code(req( final_q() )))
13121366 card
13131367 }
13141368 teal.reporter :: simple_reporter_srv(" simple_reporter" , reporter = reporter , card_fun = card_fun )
0 commit comments