@@ -73,7 +73,13 @@ forestcoxUI <- function(id, label = "forestplot") {
7373 uiOutput(ns(" cmp_eventtime" )),
7474 checkboxInput(ns(" custom_forest" ), " Custom X axis ticks in forest plot" ),
7575 uiOutput(ns(" hr_points" )),
76- uiOutput(ns(" numeric_inputs" ))
76+ uiOutput(ns(" numeric_inputs" )),
77+ # Checkbox to decide line or diamond shape for Overall defult is ???
78+ checkboxInput(ns(" summ" ), " Toggle Overall Shape" ),
79+ # Just like TT
80+ checkboxInput(ns(" tt" ), " Change Edge Shape" ),
81+ # Checkbox for show/hide KM rate. Default is hide
82+ checkboxInput(ns(" km" ), " Show KM rate" )
7783 )
7884}
7985
@@ -163,7 +169,7 @@ forestcoxServer <- function(id, data, data_label, data_varStruct = NULL, nfactor
163169 moduleServer(
164170 id ,
165171 function (input , output , session ) {
166- N <- V1 <- V2 <- .N <- HR <- Lower <- Upper <- level <- val_label <- variable <- NULL
172+ . <- N <- V1 <- V2 <- .N <- HR <- Lower <- Upper <- level <- val_label <- variable <- NULL
167173 fix_et <- ! is.null(vec.event ) && ! is.null(vec.time ) && (length(vec.event ) == length(vec.time ))
168174 if (is.null(data_varStruct )) {
169175 data_varStruct <- reactive(list (variable = names(data())))
@@ -324,12 +330,12 @@ forestcoxServer <- function(id, data, data_label, data_varStruct = NULL, nfactor
324330 )
325331 tagList(
326332 selectInput(session $ ns(" cmp_event_cox" ), " Competing Event" ,
327- choices = mklist(data_varStruct(), vlist()$ factor_01vars ), multiple = FALSE ,
328- selected = NULL
333+ choices = mklist(data_varStruct(), vlist()$ factor_01vars ), multiple = FALSE ,
334+ selected = NULL
329335 ),
330336 selectInput(session $ ns(" cmp_time_cox" ), " Competing Time" ,
331- choices = mklist(data_varStruct(), vlist()$ conti_vars_positive ), multiple = FALSE ,
332- selected = NULL
337+ choices = mklist(data_varStruct(), vlist()$ conti_vars_positive ), multiple = FALSE ,
338+ selected = NULL
333339 )
334340 )
335341 })
@@ -467,7 +473,6 @@ forestcoxServer <- function(id, data, data_label, data_varStruct = NULL, nfactor
467473
468474 colnames(tbsub )[1 : (2 + 2 * nrow(label [variable == group.tbsub ]))] <- c(" Subgroup" , paste0(" N(%): " , label [variable == group.tbsub , val_label ]), paste0(var.time [2 ], " -" , input $ day , " \n " , " KM rate(%): " , label [variable == group.tbsub , val_label ]), " HR" )
469475 }
470-
471476 return (tbsub )
472477 })
473478
@@ -489,37 +494,65 @@ forestcoxServer <- function(id, data, data_label, data_varStruct = NULL, nfactor
489494 figure <- reactive({
490495 group.tbsub <- input $ group
491496 label <- data_label()
492- data <- data.table :: setDT(tbsub())
497+ # Changed how we copy data; this is safer
498+ data <- data.table :: copy(tbsub())
493499 len <- ncol(data )
494500
495501 ll <- ifelse(group.tbsub %in% vlist()$ group_vars , nrow(label [variable == group.tbsub ]), 0 )
496- data [HR == 0 | Lower == 0 , " :=" (HR = NA , Lower = NA , Upper = NA )]
502+ # Copy rows to keep values for display
503+ data_for_display <- data [, .(HR , Lower , Upper )]
504+ # Now we can safely replace values for plotting
505+ data [HR == 0 | Lower == 0 , " :=" (HR = 0.001 , Lower = min(data [Lower > 0 , Lower ]), Upper = 999 )]
497506 data_est <- data $ `HR`
498507 data [is.na(data )] <- " "
499- data $ HR <- ifelse(data $ HR == " " , " " , paste0(data $ HR , " (" , data $ Lower , " -" , data $ Upper , " )" ))
508+ # Change row name selection to use copied row
509+ data $ HR <- ifelse(data $ HR == " " , " " , paste0(data_for_display $ HR , " (" , data_for_display $ Lower , " -" , data_for_display $ Upper , " )" ))
500510 data.table :: setnames(data , " HR" , " HR (95% CI)" )
501511 data $ ` ` <- paste(rep(" " , 20 ), collapse = " " )
502- tm <- forestploter :: forest_theme(base_size = input $ font , ci_Theight = 0.2 )
503- selected_columns <- c(c(1 : (2 + 2 * ll )), len + 1 , (len - 1 ): (len ))
504- xlim <- c(1 / input $ xMax , input $ xMax )
505- xlim <- round(xlim [order(xlim )], 2 )
506- if (is.null(input $ xMax ) || any(is.na(xlim ))) {
507- xlim <- c(0 , 2 )
512+ # Just like TT
513+ if (isTRUE(input $ tt )) {
514+ ci_Theight = FALSE
515+ } else {
516+ ci_Theight = 0.2
517+ }
518+ tm <- forestploter :: forest_theme(base_size = input $ font , ci_Theight = ci_Theight )
519+ # Now change row selection based on KM rate button
520+ if (isTRUE(input $ km )) {
521+ selected_columns <- c(c(1 : (2 + 2 * ll )), len + 1 , (len - 1 ): (len ))
522+ ci_column <- 3 + 2 * ll
523+ } else {
524+ selected_columns <- c(1 : (1 + ll ), 2 + 2 * ll , len + 1 , (len - 1 ): len )
525+ ci_column <- 3 + ll
526+ }
527+ # Determine Overall shape line vs diamond
528+ is_summary <- if (isTRUE(input $ summ )) {
529+ rep(FALSE , nrow(data ))
530+ } else {
531+ data $ Subgroup == " Overall"
532+ }
533+ # Rectangle size
534+ if (is.null(input $ rect ) || is.na(input $ rect )) {
535+ rect <- 0.5
536+ } else {
537+ rect <- input $ rect
508538 }
509539 forestploter :: forest(data [, .SD , .SDcols = selected_columns ],
510- lower = as.numeric(data $ Lower ),
511- upper = as.numeric(data $ Upper ),
512- ci_column = 3 + 2 * ll ,
513- est = as.numeric(data_est ),
514- ref_line = 1 ,
515- ticks_digits = 1 ,
516- x_trans = " log" ,
517- xlim = NULL ,
518- arrow_lab = c(input $ arrow_left , input $ arrow_right ),
519- ticks_at = ticks(),
520- theme = tm
540+ lower = as.numeric(data $ Lower ),
541+ upper = as.numeric(data $ Upper ),
542+ # Rectangle size
543+ sizes = rep(rect , nrow(data )),
544+ # Show summary which is the diamond shape here
545+ is_summary = is_summary ,
546+ ci_column = ci_column ,
547+ est = as.numeric(data_est ),
548+ ref_line = 1 ,
549+ ticks_digits = 1 ,
550+ x_trans = " log" ,
551+ xlim = NULL ,
552+ arrow_lab = c(input $ arrow_left , input $ arrow_right ),
553+ ticks_at = ticks(),
554+ theme = tm
521555 ) - > zz
522-
523556 l <- dim(zz )
524557 h <- zz $ height [(l [1 ] - 2 ): (l [1 ] - 1 )]
525558 zz <- print(zz [, 2 : (l [2 ] - 1 )], autofit = TRUE )
@@ -530,11 +563,11 @@ forestcoxServer <- function(id, data, data_label, data_varStruct = NULL, nfactor
530563 res <- reactive({
531564 list (
532565 datatable(tbsub(),
533- caption = paste0(input $ dep , " subgroup analysis" ), rownames = F , extensions = " Buttons" ,
534- options = c(
535- opt.tb1(paste0(" tbsub_" , input $ dep )),
536- list (scrollX = TRUE , columnDefs = list (list (className = " dt-right" , targets = 0 )))
537- )
566+ caption = paste0(input $ dep , " subgroup analysis" ), rownames = F , extensions = " Buttons" ,
567+ options = c(
568+ opt.tb1(paste0(" tbsub_" , input $ dep )),
569+ list (scrollX = TRUE , columnDefs = list (list (className = " dt-right" , targets = 0 )))
570+ )
538571 ),
539572 figure()
540573 )
@@ -543,6 +576,10 @@ forestcoxServer <- function(id, data, data_label, data_varStruct = NULL, nfactor
543576 output $ downloadControls <- renderUI({
544577 tagList(
545578 fluidRow(
579+ column(
580+ 3 ,
581+ numericInput(session $ ns(" rect" ), " rectangle-size" , value = 0.5 , step = 0.1 )
582+ ),
546583 column(
547584 3 ,
548585 numericInput(session $ ns(" font" ), " font-size" , value = 12 )
0 commit comments