1313# ' It controls the font size for plot titles, axis labels, and legends.
1414# ' - If vector of `length == 1` then the font sizes will have a fixed size.
1515# ' - while vector of `value`, `min`, and `max` allows dynamic adjustment.
16- # ' @templateVar ggnames "Elbow plot", "Circle plot", "Biplot", "Eigenvector plot"
17- # ' @template ggplot2_args_multi
16+ # ' @param ggplot2_args `r roxygen_ggplot2_args_param( "Elbow plot", "Circle plot", "Biplot", "Eigenvector plot")`
17+ # ' @param decorators `r roxygen_decorators_param("tm_a_pca")`
1818# '
1919# ' @inherit shared_params return
2020# '
21+ # ' @section Decorating `tm_a_pca`:
22+ # '
23+ # ' This module generates the following objects, which can be modified in place using decorators:
24+ # ' - `elbow_plot` (`ggplot2`)
25+ # ' - `circle_plot` (`ggplot2`)
26+ # ' - `biplot` (`ggplot2`)
27+ # ' - `eigenvector_plot` (`ggplot2`)
28+ # '
29+ # ' Decorators can be applied to all outputs or only to specific objects using a
30+ # ' named list of `teal_transform_module` objects.
31+ # ' The `"default"` name is reserved for decorators that are applied to all outputs.
32+ # ' See code snippet below:
33+ # '
34+ # ' ```
35+ # ' tm_a_pca(
36+ # ' ..., # arguments for module
37+ # ' decorators = list(
38+ # ' default = list(teal_transform_module(...)), # applied to all outputs
39+ # ' elbow_plot = list(teal_transform_module(...)), # applied only to `elbow_plot` output
40+ # ' circle_plot = list(teal_transform_module(...)) # applied only to `circle_plot` output
41+ # ' biplot = list(teal_transform_module(...)) # applied only to `biplot` output
42+ # ' eigenvector_plot = list(teal_transform_module(...)) # applied only to `eigenvector_plot` output
43+ # ' )
44+ # ' )
45+ # ' ```
46+ # '
47+ # ' For additional details and examples of decorators, refer to the vignette
48+ # ' `vignette("decorate-modules-output", package = "teal")` or the [`teal_transform_module()`] documentation.
49+ # '
2150# ' @examplesShinylive
2251# ' library(teal.modules.general)
2352# ' interactive <- function() TRUE
2453# ' {{ next_example }}
2554# ' @examples
55+ # '
2656# ' # general data example
2757# ' data <- teal_data()
2858# ' data <- within(data, {
5888# ' interactive <- function() TRUE
5989# ' {{ next_example }}
6090# ' @examples
91+ # '
6192# ' # CDISC data example
6293# ' data <- teal_data()
6394# ' data <- within(data, {
@@ -102,7 +133,8 @@ tm_a_pca <- function(label = "Principal Component Analysis",
102133 alpha = c(1 , 0 , 1 ),
103134 size = c(2 , 1 , 8 ),
104135 pre_output = NULL ,
105- post_output = NULL ) {
136+ post_output = NULL ,
137+ decorators = NULL ) {
106138 message(" Initializing tm_a_pca" )
107139
108140 # Normalize the parameters
@@ -152,6 +184,10 @@ tm_a_pca <- function(label = "Principal Component Analysis",
152184
153185 checkmate :: assert_multi_class(pre_output , c(" shiny.tag" , " shiny.tag.list" , " html" ), null.ok = TRUE )
154186 checkmate :: assert_multi_class(post_output , c(" shiny.tag" , " shiny.tag.list" , " html" ), null.ok = TRUE )
187+
188+ available_decorators <- c(" elbow_plot" , " circle_plot" , " biplot" , " eigenvector_plot" )
189+ decorators <- normalize_decorators(decorators )
190+ assert_decorators(decorators , null.ok = TRUE , available_decorators )
155191 # End of assertions
156192
157193 # Make UI args
@@ -169,7 +205,8 @@ tm_a_pca <- function(label = "Principal Component Analysis",
169205 list (
170206 plot_height = plot_height ,
171207 plot_width = plot_width ,
172- ggplot2_args = ggplot2_args
208+ ggplot2_args = ggplot2_args ,
209+ decorators = decorators
173210 )
174211 ),
175212 datanames = teal.transform :: get_extract_datanames(data_extract_list )
@@ -224,6 +261,34 @@ ui_a_pca <- function(id, ...) {
224261 label = " Plot type" ,
225262 choices = args $ plot_choices ,
226263 selected = args $ plot_choices [1 ]
264+ ),
265+ conditionalPanel(
266+ condition = sprintf(" input['%s'] == 'Elbow plot'" , ns(" plot_type" )),
267+ ui_decorate_teal_data(
268+ ns(" d_elbow_plot" ),
269+ decorators = select_decorators(args $ decorators , " elbow_plot" )
270+ )
271+ ),
272+ conditionalPanel(
273+ condition = sprintf(" input['%s'] == 'Circle plot'" , ns(" plot_type" )),
274+ ui_decorate_teal_data(
275+ ns(" d_circle_plot" ),
276+ decorators = select_decorators(args $ decorators , " circle_plot" )
277+ )
278+ ),
279+ conditionalPanel(
280+ condition = sprintf(" input['%s'] == 'Biplot'" , ns(" plot_type" )),
281+ ui_decorate_teal_data(
282+ ns(" d_biplot" ),
283+ decorators = select_decorators(args $ decorators , " biplot" )
284+ )
285+ ),
286+ conditionalPanel(
287+ condition = sprintf(" input['%s'] == 'Eigenvector plot'" , ns(" plot_type" )),
288+ ui_decorate_teal_data(
289+ ns(" d_eigenvector_plot" ),
290+ decorators = select_decorators(args $ decorators , " eigenvector_plot" )
291+ )
227292 )
228293 ),
229294 teal.widgets :: panel_item(
@@ -289,7 +354,7 @@ ui_a_pca <- function(id, ...) {
289354}
290355
291356# Server function for the PCA module
292- srv_a_pca <- function (id , data , reporter , filter_panel_api , dat , plot_height , plot_width , ggplot2_args ) {
357+ srv_a_pca <- function (id , data , reporter , filter_panel_api , dat , plot_height , plot_width , ggplot2_args , decorators ) {
293358 with_reporter <- ! missing(reporter ) && inherits(reporter , " Reporter" )
294359 with_filter <- ! missing(filter_panel_api ) && inherits(filter_panel_api , " FilterPanelAPI" )
295360 checkmate :: assert_class(data , " reactive" )
@@ -549,7 +614,7 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
549614 )
550615
551616 cols <- c(getOption(" ggplot2.discrete.colour" ), c(" lightblue" , " darkred" , " black" ))[1 : 3 ]
552- g <- ggplot(mapping = aes_string(x = " component" , y = " value" )) +
617+ elbow_plot <- ggplot(mapping = aes_string(x = " component" , y = " value" )) +
553618 geom_bar(
554619 aes(fill = " Single variance" ),
555620 data = dplyr :: filter(elb_dat , metric == " Proportion of Variance" ),
@@ -569,8 +634,6 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
569634 scale_fill_manual(values = c(" Cumulative variance" = cols [2 ], " Single variance" = cols [1 ])) +
570635 ggthemes +
571636 themes
572-
573- print(g )
574637 },
575638 env = list (
576639 ggthemes = parsed_ggplot2_args $ ggtheme ,
@@ -628,7 +691,7 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
628691 y = sin(seq(0 , 2 * pi , length.out = 100 ))
629692 )
630693
631- g <- ggplot(pca_rot ) +
694+ circle_plot <- ggplot(pca_rot ) +
632695 geom_point(aes_string(x = x_axis , y = y_axis )) +
633696 geom_label(
634697 aes_string(x = x_axis , y = y_axis , label = " label" ),
@@ -640,7 +703,6 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
640703 labs +
641704 ggthemes +
642705 themes
643- print(g )
644706 },
645707 env = list (
646708 x_axis = x_axis ,
@@ -861,8 +923,7 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
861923 qenv ,
862924 substitute(
863925 expr = {
864- g <- plot_call
865- print(g )
926+ biplot <- plot_call
866927 },
867928 env = list (
868929 plot_call = Reduce(function (x , y ) call(" +" , x , y ), pca_plot_biplot_expr )
@@ -871,8 +932,8 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
871932 )
872933 }
873934
874- # plot pc_var ----
875- plot_pc_var <- function (base_q ) {
935+ # plot eigenvector_plot ----
936+ plot_eigenvector <- function (base_q ) {
876937 pc <- input $ pc
877938 ggtheme <- input $ ggtheme
878939
@@ -938,10 +999,7 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
938999 expr = {
9391000 pca_rot <- pca $ rotation [, pc , drop = FALSE ] %> %
9401001 dplyr :: as_tibble(rownames = " Variable" )
941-
942- g <- plot_call
943-
944- print(g )
1002+ eigenvector_plot <- plot_call
9451003 },
9461004 env = list (
9471005 pc = pc ,
@@ -951,23 +1009,54 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
9511009 )
9521010 }
9531011
954- # plot final ----
955- output_q <- reactive({
956- req(computation())
957- teal :: validate_inputs(iv_r())
958- teal :: validate_inputs(iv_extra , header = " Plot settings are required" )
1012+ # qenvs ---
1013+ output_q <- lapply(
1014+ list (
1015+ elbow_plot = plot_elbow ,
1016+ circle_plot = plot_circle ,
1017+ biplot = plot_biplot ,
1018+ eigenvector_plot = plot_eigenvector
1019+ ),
1020+ function (fun ) {
1021+ reactive({
1022+ req(computation())
1023+ teal :: validate_inputs(iv_r())
1024+ teal :: validate_inputs(iv_extra , header = " Plot settings are required" )
1025+ fun(computation())
1026+ })
1027+ }
1028+ )
9591029
960- switch (input $ plot_type ,
961- " Elbow plot" = plot_elbow(computation()),
962- " Circle plot" = plot_circle(computation()),
963- " Biplot" = plot_biplot(computation()),
964- " Eigenvector plot" = plot_pc_var(computation()),
1030+ decorated_q <- mapply(
1031+ function (obj_name , q ) {
1032+ srv_decorate_teal_data(
1033+ id = sprintf(" d_%s" , obj_name ),
1034+ data = q ,
1035+ decorators = select_decorators(decorators , obj_name ),
1036+ expr = reactive({
1037+ substitute(print(.plot ), env = list (.plot = as.name(obj_name )))
1038+ }),
1039+ expr_is_reactive = TRUE
1040+ )
1041+ },
1042+ names(output_q ),
1043+ output_q
1044+ )
1045+
1046+ # plot final ----
1047+ decorated_output_q <- reactive({
1048+ switch (req(input $ plot_type ),
1049+ " Elbow plot" = decorated_q $ elbow_plot(),
1050+ " Circle plot" = decorated_q $ circle_plot(),
1051+ " Biplot" = decorated_q $ biplot(),
1052+ " Eigenvector plot" = decorated_q $ eigenvector_plot(),
9651053 stop(" Unknown plot" )
9661054 )
9671055 })
9681056
9691057 plot_r <- reactive({
970- output_q()[[" g" ]]
1058+ plot_name <- gsub(" " , " _" , tolower(req(input $ plot_type )))
1059+ req(decorated_output_q())[[plot_name ]]
9711060 })
9721061
9731062 pws <- teal.widgets :: plot_with_settings_srv(
@@ -1034,7 +1123,7 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
10341123
10351124 teal.widgets :: verbatim_popup_srv(
10361125 id = " rcode" ,
1037- verbatim_content = reactive(teal.code :: get_code(output_q( ))),
1126+ verbatim_content = reactive(teal.code :: get_code(req(decorated_output_q() ))),
10381127 title = " R Code for PCA"
10391128 )
10401129
@@ -1057,7 +1146,7 @@ srv_a_pca <- function(id, data, reporter, filter_panel_api, dat, plot_height, pl
10571146 card $ append_text(" Comment" , " header3" )
10581147 card $ append_text(comment )
10591148 }
1060- card $ append_src(teal.code :: get_code(output_q( )))
1149+ card $ append_src(teal.code :: get_code(req(decorated_output_q() )))
10611150 card
10621151 }
10631152 teal.reporter :: simple_reporter_srv(" simple_reporter" , reporter = reporter , card_fun = card_fun )
0 commit comments