# Detach previous packages
# invisible(lapply(paste0('package:', names(sessionInfo()$otherPkgs)), detach, character.only=TRUE, unload=TRUE))
# Remove all variables from memory
# rm(list=ls())
# Load the necessary packages ####
suppressWarnings({
  suppressMessages({
    # For writing the codes with shiny
    library(shiny)
    # For importing Excel data
    # library(readxl)
    # File management
    library(tools)
    library(zip)
    library(fs)
    # For meta-analysis
    library(meta)
    # Replace text
    library(tidyverse)
    library(stringr)
    # For reference screener 
    library(zoo)
    library(tidyr)
    library(XML)
    library(viridis)
    # For DEF
    library(openxlsx)
    library(openxlsx2)
    # For OCR
    library(tesseract)
    library(magick)
  })
})

# Limit the size of the upload to 40 MB
options(shiny.maxRequestSize = 40*1024^2)
# Set the digits to 2 for meta-analysis
settings.meta(digits=2)
# Format for forest plot
settings.meta("RevMan5")
# Turn off scientific notations
options(scipen=999)

# Functions to create graphs easily ####
f.ForestPlot<-function(KG, OutcomeType){
  plot.new()
  forest(KG, colgap = ifelse(OutcomeType == "Continuous","5mm","8mm"), digits = 2, digits.se = 2)
  title(main=KG$outclab)
  recordPlot()
}
f.ForestPlot.SA<-function(KG, OutcomeType,a){
  plot.new()
  forest(KG, colgap = ifelse(OutcomeType == "Continuous","5mm","8mm"), digits = 2, digits.se = 2)
  title(main=paste0(KG$outclab,' (',c("Informative Missingness Odds Ratio (IMOR)","Best-worst analysis","Worst-best analysis","Sensitivity analysis")[a],')'))
  recordPlot()
}
f.ForestPlot.SubA<-function(KG, OutcomeType, SubgroupTitle){
  plot.new()
  forest(KG, colgap = ifelse(OutcomeType == "Continuous","5mm","8mm"), digits = 2, digits.se = 2)
  title(main=paste0(KG$outclab,'\n','Moderator: ',SubgroupTitle))
  recordPlot()
}
f.FunnelPlot<-function(KG){
  funnel(
    KG, 
    level = 0.95, 
    contour.levels = c(0.9, 0.95, 0.99),
  )
  legend(x="topright",
         c("0.1 > p > 0.05", "0.05 > p > 0.01", "< 0.01"),
         fill = gray(seq(0.5, 0.9, len=3)),
  )
  title(main=KG$outclab)
  recordPlot()
}
f.BubblePlot<-function(KG1, KG2){
  if (KG2$sm %in% c("OR","RR","HR","ROM")){
    bubble(KG1,
           ylim = range(exp(KG2$TE), na.rm = TRUE)
    )
  } else {
    bubble(KG1,
           ylim = range(KG2$TE, na.rm = TRUE)
    )
  }
  title(
    main=paste0(KG2$outclab, ' (metaregression)'),
    sub = "Each bubble represents a study. Larger bubbles indicates smaller variance and viceversa"
  )
  recordPlot()
}
f.PlotText <- function(KG) {
  plot.new()
  title(main=KG)
  recordPlot()
}
# Sensitivity analysis ####
f.IMOR <- function(df_Outcome,MA, IMOR_E=1,IMOR_C=1) {
  # Intervention
  r.e <- as.vector(df_Outcome[,7])
  f.e <- as.vector(df_Outcome[,5]-df_Outcome[,7])
  m1.e <- as.vector(df_Outcome[,14])
  m2.e <- as.vector(df_Outcome[,15])
  m3.e <- as.vector(df_Outcome[,16])
  m4.e <- as.vector(df_Outcome[,17])
  m5.e <- as.vector(df_Outcome[,18])
  m6.e <- as.vector(df_Outcome[,19])
  m7.e <- as.vector(df_Outcome[,20])
  m.e <- rowSums(cbind(m1.e,m2.e,m3.e,m4.e,m5.e,m6.e),na.rm = TRUE)
  N.e <- rowSums(cbind(r.e,f.e,m.e),na.rm = TRUE)
  # Control
  r.c <- as.vector(df_Outcome[,8])
  f.c <- as.vector(df_Outcome[,6]-df_Outcome[,8])
  m1.c <- as.vector(df_Outcome[,21])
  m2.c <- as.vector(df_Outcome[,22])
  m3.c <- as.vector(df_Outcome[,23])
  m4.c <- as.vector(df_Outcome[,24])
  m5.c <- as.vector(df_Outcome[,25])
  m6.c <- as.vector(df_Outcome[,26])
  m7.c <- as.vector(df_Outcome[,27])
  m.c <- rowSums(cbind(m1.c,m2.c,m3.c,m4.c,m5.c,m6.c),na.rm = TRUE)
  N.c <- rowSums(cbind(r.c,f.c,m.c),na.rm = TRUE)
  
  IMOR <- data.frame(cbind(r.e,f.e,m1.e,m2.e,m3.e,m4.e,m5.e,m6.e,m.e,N.e,
                           r.c,f.c,m1.c,m2.c,m3.c,m4.c,m5.c,m6.c,m.c,N.c
  ))
  
  # Zero event trials increase by 0.5 for each cell
  IMOR[IMOR$r.e == 0 | IMOR$f.e == 0 | IMOR$r.c == 0 | IMOR$f.c ==0,c(1:2,11:12)] <- 
    lapply(IMOR[IMOR$r.e == 0 | IMOR$f.e == 0 | IMOR$r.c == 0 | IMOR$f.c ==0,c(1:2,11:12)],function(x) {x+0.5})
  
  # If the trial did not state whether the data is missing, m7 should be based on the proportion of drop-outs in remaining trials (in the group) and then distributed as for m6
  # But for this, we need at least one study to report the drop out
  if (sum(is.na(IMOR[,c(3:8, 13:18)])) != 12*nrow(IMOR)) {
    # if drop out is reported only in the intervention assume similar drop-outs in control group and vice versa; otherwise calculate the drop-outs from the respective groups
    if (sum(is.na(IMOR[,c(3:8)])) == 6*nrow(IMOR)) {
      IMOR$m6.c <- ifelse(is.na(IMOR$m6.c),ifelse(m7.c !=0, sum(IMOR$m.c[m7.c == 0],na.rm = TRUE)/sum(IMOR$N.c[m7.c == 0],na.rm = TRUE)*IMOR$N.c,IMOR$m6.c),IMOR$m6.c)
      IMOR$m6.e <- IMOR$m6.c
    } else if (sum(is.na(IMOR[,c(13:18)])) == 6*nrow(IMOR)) {
      IMOR$m6.e <- ifelse(is.na(IMOR$m6.e),ifelse(m7.e !=0, sum(IMOR$m.e[m7.e == 0],na.rm = TRUE)/sum(IMOR$N.e[m7.e == 0],na.rm = TRUE)*IMOR$N.e,IMOR$m6.e),IMOR$m6.e)
      IMOR$m6.c <- IMOR$m6.e
    } else {
      IMOR$m6.e <- ifelse(is.na(IMOR$m6.e),ifelse(m7.e !=0, sum(IMOR$m.e[m7.e == 0],na.rm = TRUE)/sum(IMOR$N.e[m7.e == 0],na.rm = TRUE)*IMOR$N.e,IMOR$m6.e),IMOR$m6.e)
      IMOR$m6.c <- ifelse(is.na(IMOR$m6.c),ifelse(m7.c !=0, sum(IMOR$m.c[m7.c == 0],na.rm = TRUE)/sum(IMOR$N.c[m7.c == 0],na.rm = TRUE)*IMOR$N.c,IMOR$m6.c),IMOR$m6.c)
    }
  }
  
  # Now replace NA with 0
  IMOR[is.na(IMOR)] <- 0
  
  # update the IMOR$m.e and IMOR.m.c and N.e, N.c
  IMOR$m.e <- rowSums(IMOR[,3:8])
  IMOR$m.c <- rowSums(IMOR[,13:18])
  IMOR$N.e <- rowSums(IMOR[,c(1:2,9)])
  IMOR$N.c <- rowSums(IMOR[,c(11:12,19)])
  
  # If the reasons were not stated m6 should be distributed according to the median proportions of m1 to m5 (in the group) 
  # Again the trials where number missing was not stated should be excluded
  # Since we are redistributing the unknown cases to known cases, the proportions should be based on m - m6
  # Means rather than medians: if we choose medians, the proportions can come from different studies and the sum may not be one
  # Because of the formula used, if m6 =0, m1 = m1, m2 = m2, etc
  # How if the only value provided is m6 in all trials, then move m6 to m5 to allow standard IMOR
  if (sum(IMOR[,c(3:7)]) == 0){
    IMOR$m5.e <- IMOR$m6.e
  } else {
    IMOR$m1.e <- IMOR$m1.e + sum(IMOR$m1.e[m7.e == 0],na.rm = TRUE)/(sum(IMOR$m.e[m7.e == 0],na.rm = TRUE)-sum(IMOR$m6.e[m7.e == 0],na.rm = TRUE))*IMOR$m6.e
    IMOR$m2.e <- IMOR$m2.e + sum(IMOR$m2.e[m7.e == 0],na.rm = TRUE)/(sum(IMOR$m.e[m7.e == 0],na.rm = TRUE)-sum(IMOR$m6.e[m7.e == 0],na.rm = TRUE))*IMOR$m6.e
    IMOR$m3.e <- IMOR$m3.e + sum(IMOR$m3.e[m7.e == 0],na.rm = TRUE)/(sum(IMOR$m.e[m7.e == 0],na.rm = TRUE)-sum(IMOR$m6.e[m7.e == 0],na.rm = TRUE))*IMOR$m6.e
    IMOR$m4.e <- IMOR$m4.e + sum(IMOR$m4.e[m7.e == 0],na.rm = TRUE)/(sum(IMOR$m.e[m7.e == 0],na.rm = TRUE)-sum(IMOR$m6.e[m7.e == 0],na.rm = TRUE))*IMOR$m6.e
    IMOR$m5.e <- IMOR$m5.e + sum(IMOR$m5.e[m7.e == 0],na.rm = TRUE)/(sum(IMOR$m.e[m7.e == 0],na.rm = TRUE)-sum(IMOR$m6.e[m7.e == 0],na.rm = TRUE))*IMOR$m6.e
  }
  
  if (sum(IMOR[,c(13:17)]) == 0){
    IMOR$m5.c <- IMOR$m6.c
  } else {
    IMOR$m1.c <- IMOR$m1.c + sum(IMOR$m1.c[m7.c == 0],na.rm = TRUE)/(sum(IMOR$m.c[m7.c == 0],na.rm = TRUE)-sum(IMOR$m6.c[m7.c == 0],na.rm = TRUE))*IMOR$m6.c
    IMOR$m2.c <- IMOR$m2.c + sum(IMOR$m2.c[m7.c == 0],na.rm = TRUE)/(sum(IMOR$m.c[m7.c == 0],na.rm = TRUE)-sum(IMOR$m6.c[m7.c == 0],na.rm = TRUE))*IMOR$m6.c
    IMOR$m3.c <- IMOR$m3.c + sum(IMOR$m3.c[m7.c == 0],na.rm = TRUE)/(sum(IMOR$m.c[m7.c == 0],na.rm = TRUE)-sum(IMOR$m6.c[m7.c == 0],na.rm = TRUE))*IMOR$m6.c
    IMOR$m4.c <- IMOR$m4.c + sum(IMOR$m4.c[m7.c == 0],na.rm = TRUE)/(sum(IMOR$m.c[m7.c == 0],na.rm = TRUE)-sum(IMOR$m6.c[m7.c == 0],na.rm = TRUE))*IMOR$m6.c
    IMOR$m5.c <- IMOR$m5.c + sum(IMOR$m5.c[m7.c == 0],na.rm = TRUE)/(sum(IMOR$m.c[m7.c == 0],na.rm = TRUE)-sum(IMOR$m6.c[m7.c == 0],na.rm = TRUE))*IMOR$m6.c
  }
  # To avoid confusion, drop m6.e, m6.e
  IMOR <- IMOR[,-c(8,18)]
  
  IMOR$p.e <- IMOR$r.e/(IMOR$r.e+IMOR$f.e)
  IMOR$a.e <- IMOR$m.e/IMOR$N.e
  IMOR$m1.a.e <- IMOR$m1.e/IMOR$N.e
  IMOR$m2.a.e <- IMOR$m2.e/IMOR$N.e 
  IMOR$m3.a.e <- IMOR$m3.e/IMOR$N.e 
  IMOR$m4.a.e <- IMOR$m4.e/IMOR$N.e 
  IMOR$m5.a.e <- IMOR$m5.e/IMOR$N.e 
  IMOR$p.c <- IMOR$r.c/(IMOR$r.c+IMOR$f.c)
  IMOR$a.c <- IMOR$m.c/IMOR$N.c
  IMOR$m1.a.c <- IMOR$m1.c/IMOR$N.c 
  IMOR$m2.a.c <- IMOR$m2.c/IMOR$N.c 
  IMOR$m3.a.c <- IMOR$m3.c/IMOR$N.c 
  IMOR$m4.a.c <- IMOR$m4.c/IMOR$N.c 
  IMOR$m5.a.c <- IMOR$m5.c/IMOR$N.c
  
  # At this stage make three more: IMOR_01, IMOR_10 for best case and worst case analysis (for bad outcomes) and IMOR-M where IMOR is used for all missing causes
  IMOR_01 <- IMOR
  IMOR_10 <- IMOR
  IMOR_M <- IMOR
  
  # m1= Missing failure (Intervention): p = 0
  # m2 = Missing success (Intervention): p = 1
  # m3 = Missing unrelated (Intervention): p = p.e
  # m4 = Missing protocol violation (Intervention) (receives Control): p = p.c
  # m5 = Missing other (Intervention): p based on IMOR (user provided)
  
  # Calcuate IMORs for m1 to m4 from p and p from IMOR for m5
  IMOR$m1.p.e <- ifelse(tolower(df_Outcome[1,3])=="worse",1,0)
  IMOR$m2.p.e <- ifelse(tolower(df_Outcome[1,3])=="worse",0,1)
  IMOR$m3.p.e <- IMOR$p.e
  IMOR$m4.p.e <- IMOR$p.c
  
  # IMOR = odds of m1 (m2,m3, m4) by odds of not missing
  # Odds = Risk/(1-Risk)
  IMOR$m1.IMOR.e <- ifelse(IMOR$m1.p.e == 1,1e8,(IMOR$m1.p.e/(1-IMOR$m1.p.e))/(IMOR$p.e/(1-IMOR$p.e)))
  IMOR$m2.IMOR.e <- ifelse(IMOR$m2.p.e == 1,1e8,(IMOR$m2.p.e/(1-IMOR$m2.p.e))/(IMOR$p.e/(1-IMOR$p.e)))
  IMOR$m3.IMOR.e <- ifelse(IMOR$m3.p.e == 1,1e8,(IMOR$m3.p.e/(1-IMOR$m3.p.e))/(IMOR$p.e/(1-IMOR$p.e)))
  IMOR$m4.IMOR.e <- ifelse(IMOR$m4.p.e == 1,1e8,(IMOR$m4.p.e/(1-IMOR$m4.p.e))/(IMOR$p.e/(1-IMOR$p.e)))
  
  # IMOR of m5 directly given, but we still need p for later calculations
  IMOR$m5.IMOR.e <- IMOR_E
  IMOR$m5.p.e <- IMOR$p.e*IMOR$m5.IMOR.e/(IMOR$p.e*IMOR$m5.IMOR.e + 1 - IMOR$p.e)
  
  # m1= Missing failure (Control): p = 0
  # m2 = Missing success (Control): p = 1
  # m3 = Missing unrelated (Control): p = p.c
  # m4 = Missing protocol violation (Control) (receives Intervention): p = p.e
  # m5 = Missing other (Control): p based on IMOR (user provided)
  
  # Calcuate IMORs for m1 to m4 from p and p from IMOR for m5
  IMOR$m1.p.c <- ifelse(tolower(df_Outcome[1,3])=="worse",1,0)
  IMOR$m2.p.c <- ifelse(tolower(df_Outcome[1,3])=="worse",0,1)
  IMOR$m3.p.c <- IMOR$p.c
  IMOR$m4.p.c <- IMOR$p.e
  
  # IMOR = odds of m1 (m2,m3, m4) by odds of not missing
  # Odds = Risk/(1-Risk)
  IMOR$m1.IMOR.c <- ifelse(IMOR$m1.p.c == 1,1e8,(IMOR$m1.p.c/(1-IMOR$m1.p.c))/(IMOR$p.c/(1-IMOR$p.c)))
  IMOR$m2.IMOR.c <- ifelse(IMOR$m2.p.c == 1,1e8,(IMOR$m2.p.c/(1-IMOR$m2.p.c))/(IMOR$p.c/(1-IMOR$p.c)))
  IMOR$m3.IMOR.c <- ifelse(IMOR$m3.p.c == 1,1e8,(IMOR$m3.p.c/(1-IMOR$m3.p.c))/(IMOR$p.c/(1-IMOR$p.c)))
  IMOR$m4.IMOR.c <- ifelse(IMOR$m4.p.c == 1,1e8,(IMOR$m4.p.c/(1-IMOR$m4.p.c))/(IMOR$p.c/(1-IMOR$p.c)))
  
  # IMOR of m5 directly given, but we still need p for later calculations
  IMOR$m5.IMOR.c <- IMOR_C
  IMOR$m5.p.c <- IMOR$p.c*IMOR$m5.IMOR.c/(IMOR$p.c*IMOR$m5.IMOR.c + 1 - IMOR$p.c)
  
  IMOR$p.star.e <- IMOR$p.e*(1-IMOR$a.e) + 
    IMOR$m1.a.e * (IMOR$p.e*IMOR$m1.IMOR.e)/(IMOR$p.e*IMOR$m1.IMOR.e+1-IMOR$p.e) +
    IMOR$m2.a.e * (IMOR$p.e*IMOR$m2.IMOR.e)/(IMOR$p.e*IMOR$m2.IMOR.e+1-IMOR$p.e) +
    IMOR$m3.a.e * (IMOR$p.e*IMOR$m3.IMOR.e)/(IMOR$p.e*IMOR$m3.IMOR.e+1-IMOR$p.e) +
    IMOR$m4.a.e * (IMOR$p.e*IMOR$m4.IMOR.e)/(IMOR$p.e*IMOR$m4.IMOR.e+1-IMOR$p.e) +
    IMOR$m5.a.e * (IMOR$p.e*IMOR$m5.IMOR.e)/(IMOR$p.e*IMOR$m5.IMOR.e+1-IMOR$p.e)
  
  IMOR$p.star.c <- IMOR$p.c*(1-IMOR$a.c) + 
    IMOR$m1.a.c * (IMOR$p.c*IMOR$m1.IMOR.c)/(IMOR$p.c*IMOR$m1.IMOR.c+1-IMOR$p.c) +
    IMOR$m2.a.c * (IMOR$p.c*IMOR$m2.IMOR.c)/(IMOR$p.c*IMOR$m2.IMOR.c+1-IMOR$p.c) +
    IMOR$m3.a.c * (IMOR$p.c*IMOR$m3.IMOR.c)/(IMOR$p.c*IMOR$m3.IMOR.c+1-IMOR$p.c) +
    IMOR$m4.a.c * (IMOR$p.c*IMOR$m4.IMOR.c)/(IMOR$p.c*IMOR$m4.IMOR.c+1-IMOR$p.c) +
    IMOR$m5.a.c * (IMOR$p.c*IMOR$m5.IMOR.c)/(IMOR$p.c*IMOR$m5.IMOR.c+1-IMOR$p.c)
  
  IMOR$var.p.star.e <- IMOR$p.e*(1-IMOR$p.e)/(IMOR$N.e-IMOR$m.e) *
    (1 +
       IMOR$m1.a.e * (IMOR$m1.IMOR.e/(IMOR$p.e * IMOR$m1.IMOR.e + 1-IMOR$p.e)^2-1) +
       IMOR$m2.a.e * (IMOR$m2.IMOR.e/(IMOR$p.e * IMOR$m2.IMOR.e + 1-IMOR$p.e)^2-1) +
       IMOR$m3.a.e * (IMOR$m3.IMOR.e/(IMOR$p.e * IMOR$m3.IMOR.e + 1-IMOR$p.e)^2-1) +
       IMOR$m4.a.e * (IMOR$m4.IMOR.e/(IMOR$p.e * IMOR$m4.IMOR.e + 1-IMOR$p.e)^2-1) +
       IMOR$m5.a.e * (IMOR$m5.IMOR.e/(IMOR$p.e * IMOR$m5.IMOR.e + 1-IMOR$p.e)^2-1)
    )^2 +
    (1/IMOR$N.e) * 
    ((IMOR$p.e - IMOR$p.star.e)^2 +
       IMOR$m1.a.e * ((IMOR$m1.p.e-IMOR$p.star.e)^2-(IMOR$p.e-IMOR$p.star.e)^2) +
       IMOR$m2.a.e * ((IMOR$m2.p.e-IMOR$p.star.e)^2-(IMOR$p.e-IMOR$p.star.e)^2) +
       IMOR$m3.a.e * ((IMOR$m3.p.e-IMOR$p.star.e)^2-(IMOR$p.e-IMOR$p.star.e)^2) +
       IMOR$m4.a.e * ((IMOR$m4.p.e-IMOR$p.star.e)^2-(IMOR$p.e-IMOR$p.star.e)^2) +
       IMOR$m5.a.e * ((IMOR$m5.p.e-IMOR$p.star.e)^2-(IMOR$p.e-IMOR$p.star.e)^2)
    )
  
  IMOR$var.p.star.c <- IMOR$p.c*(1-IMOR$p.c)/(IMOR$N.c-IMOR$m.c) *
    (1 +
       IMOR$m1.a.c * (IMOR$m1.IMOR.c/(IMOR$p.c * IMOR$m1.IMOR.c + 1-IMOR$p.c)^2-1) +
       IMOR$m2.a.c * (IMOR$m2.IMOR.c/(IMOR$p.c * IMOR$m2.IMOR.c + 1-IMOR$p.c)^2-1) +
       IMOR$m3.a.c * (IMOR$m3.IMOR.c/(IMOR$p.c * IMOR$m3.IMOR.c + 1-IMOR$p.c)^2-1) +
       IMOR$m4.a.c * (IMOR$m4.IMOR.c/(IMOR$p.c * IMOR$m4.IMOR.c + 1-IMOR$p.c)^2-1) +
       IMOR$m5.a.c * (IMOR$m5.IMOR.c/(IMOR$p.c * IMOR$m5.IMOR.c + 1-IMOR$p.c)^2-1)
    )^2 +
    (1/IMOR$N.c) * 
    ((IMOR$p.c - IMOR$p.star.c)^2 +
       IMOR$m1.a.c * ((IMOR$m1.p.c-IMOR$p.star.c)^2-(IMOR$p.c-IMOR$p.star.c)^2) +
       IMOR$m2.a.c * ((IMOR$m2.p.c-IMOR$p.star.c)^2-(IMOR$p.c-IMOR$p.star.c)^2) +
       IMOR$m3.a.c * ((IMOR$m3.p.c-IMOR$p.star.c)^2-(IMOR$p.c-IMOR$p.star.c)^2) +
       IMOR$m4.a.c * ((IMOR$m4.p.c-IMOR$p.star.c)^2-(IMOR$p.c-IMOR$p.star.c)^2) +
       IMOR$m5.a.c * ((IMOR$m5.p.c-IMOR$p.star.c)^2-(IMOR$p.c-IMOR$p.star.c)^2)
    )
  
  IMOR$var.p.e <- IMOR$p.e*(1-IMOR$p.e)/(IMOR$N.e-IMOR$m.e)
  IMOR$var.p.c <- IMOR$p.c*(1-IMOR$p.c)/(IMOR$N.c-IMOR$m.c)
  
  IMOR$logOR <- log((IMOR$p.e/(1-IMOR$p.e))/(IMOR$p.c/(1-IMOR$p.c)))
  IMOR$var.logOR <- 
    IMOR$var.p.e/(IMOR$p.e*(1-IMOR$p.e))^2 +
    IMOR$var.p.c/(IMOR$p.c*(1-IMOR$p.c))^2
  
  IMOR$logOR.star <- log((IMOR$p.star.e/(1-IMOR$p.star.e))/(IMOR$p.star.c/(1-IMOR$p.star.c)))
  IMOR$var.logOR.star <- 
    IMOR$var.p.star.e/(IMOR$p.star.e*(1-IMOR$p.star.e))^2 +
    IMOR$var.p.star.c/(IMOR$p.star.c*(1-IMOR$p.star.c))^2
  
  IMOR$logRR <- log(IMOR$p.e/IMOR$p.c)
  IMOR$var.logRR <- 
    IMOR$var.p.e/(IMOR$p.e)^2 +
    IMOR$var.p.c/(IMOR$p.c)^2
  
  IMOR$logRR.star <- log(IMOR$p.star.e/IMOR$p.star.c)
  IMOR$var.logRR.star <- 
    IMOR$var.p.star.e/(IMOR$p.star.e)^2 +
    IMOR$var.p.star.c/(IMOR$p.star.c)^2
  
  # Now IMOR_01
  IMOR_01$m1.p.e <- 0
  IMOR_01$m2.p.e <- 0
  IMOR_01$m3.p.e <- 0
  IMOR_01$m4.p.e <- 0
  IMOR_01$m5.p.e <- 0
  
  # IMOR = odds of m1 (m2,m3, m4) by odds of not missing
  # Odds = Risk/(1-Risk)
  IMOR_01$m1.IMOR.e <- ifelse(IMOR_01$m1.p.e == 1,1e8,(IMOR_01$m1.p.e/(1-IMOR_01$m1.p.e))/(IMOR_01$p.e/(1-IMOR_01$p.e)))
  IMOR_01$m2.IMOR.e <- ifelse(IMOR_01$m2.p.e == 1,1e8,(IMOR_01$m2.p.e/(1-IMOR_01$m2.p.e))/(IMOR_01$p.e/(1-IMOR_01$p.e)))
  IMOR_01$m3.IMOR.e <- ifelse(IMOR_01$m3.p.e == 1,1e8,(IMOR_01$m3.p.e/(1-IMOR_01$m3.p.e))/(IMOR_01$p.e/(1-IMOR_01$p.e)))
  IMOR_01$m4.IMOR.e <- ifelse(IMOR_01$m4.p.e == 1,1e8,(IMOR_01$m4.p.e/(1-IMOR_01$m4.p.e))/(IMOR_01$p.e/(1-IMOR_01$p.e)))
  IMOR_01$m5.IMOR.e <- ifelse(IMOR_01$m5.p.e == 1,1e8,(IMOR_01$m5.p.e/(1-IMOR_01$m5.p.e))/(IMOR_01$p.e/(1-IMOR_01$p.e)))
  
  IMOR_01$m1.p.c <- 1
  IMOR_01$m2.p.c <- 1
  IMOR_01$m3.p.c <- 1
  IMOR_01$m4.p.c <- 1
  IMOR_01$m5.p.c <- 1
  
  IMOR_01$m1.IMOR.c <- ifelse(IMOR_01$m1.p.c == 1,1e8,(IMOR_01$m1.p.c/(1-IMOR_01$m1.p.c))/(IMOR_01$p.c/(1-IMOR_01$p.c)))
  IMOR_01$m2.IMOR.c <- ifelse(IMOR_01$m2.p.c == 1,1e8,(IMOR_01$m2.p.c/(1-IMOR_01$m2.p.c))/(IMOR_01$p.c/(1-IMOR_01$p.c)))
  IMOR_01$m3.IMOR.c <- ifelse(IMOR_01$m3.p.c == 1,1e8,(IMOR_01$m3.p.c/(1-IMOR_01$m3.p.c))/(IMOR_01$p.c/(1-IMOR_01$p.c)))
  IMOR_01$m4.IMOR.c <- ifelse(IMOR_01$m4.p.c == 1,1e8,(IMOR_01$m4.p.c/(1-IMOR_01$m4.p.c))/(IMOR_01$p.c/(1-IMOR_01$p.c)))
  IMOR_01$m5.IMOR.c <- ifelse(IMOR_01$m5.p.c == 1,1e8,(IMOR_01$m5.p.c/(1-IMOR_01$m5.p.c))/(IMOR_01$p.c/(1-IMOR_01$p.c)))
  
  IMOR_01$p.star.e <- IMOR_01$p.e*(1-IMOR_01$a.e) + 
    IMOR_01$m1.a.e * (IMOR_01$p.e*IMOR_01$m1.IMOR.e)/(IMOR_01$p.e*IMOR_01$m1.IMOR.e+1-IMOR_01$p.e) +
    IMOR_01$m2.a.e * (IMOR_01$p.e*IMOR_01$m2.IMOR.e)/(IMOR_01$p.e*IMOR_01$m2.IMOR.e+1-IMOR_01$p.e) +
    IMOR_01$m3.a.e * (IMOR_01$p.e*IMOR_01$m3.IMOR.e)/(IMOR_01$p.e*IMOR_01$m3.IMOR.e+1-IMOR_01$p.e) +
    IMOR_01$m4.a.e * (IMOR_01$p.e*IMOR_01$m4.IMOR.e)/(IMOR_01$p.e*IMOR_01$m4.IMOR.e+1-IMOR_01$p.e) +
    IMOR_01$m5.a.e * (IMOR_01$p.e*IMOR_01$m5.IMOR.e)/(IMOR_01$p.e*IMOR_01$m5.IMOR.e+1-IMOR_01$p.e)
  
  IMOR_01$p.star.c <- IMOR_01$p.c*(1-IMOR_01$a.c) + 
    IMOR_01$m1.a.c * (IMOR_01$p.c*IMOR_01$m1.IMOR.c)/(IMOR_01$p.c*IMOR_01$m1.IMOR.c+1-IMOR_01$p.c) +
    IMOR_01$m2.a.c * (IMOR_01$p.c*IMOR_01$m2.IMOR.c)/(IMOR_01$p.c*IMOR_01$m2.IMOR.c+1-IMOR_01$p.c) +
    IMOR_01$m3.a.c * (IMOR_01$p.c*IMOR_01$m3.IMOR.c)/(IMOR_01$p.c*IMOR_01$m3.IMOR.c+1-IMOR_01$p.c) +
    IMOR_01$m4.a.c * (IMOR_01$p.c*IMOR_01$m4.IMOR.c)/(IMOR_01$p.c*IMOR_01$m4.IMOR.c+1-IMOR_01$p.c) +
    IMOR_01$m5.a.c * (IMOR_01$p.c*IMOR_01$m5.IMOR.c)/(IMOR_01$p.c*IMOR_01$m5.IMOR.c+1-IMOR_01$p.c)
  
  IMOR_01$var.p.star.e <- IMOR_01$p.e*(1-IMOR_01$p.e)/(IMOR_01$N.e-IMOR_01$m.e) *
    (1 +
       IMOR_01$m1.a.e * (IMOR_01$m1.IMOR.e/(IMOR_01$p.e * IMOR_01$m1.IMOR.e + 1-IMOR_01$p.e)^2-1) +
       IMOR_01$m2.a.e * (IMOR_01$m2.IMOR.e/(IMOR_01$p.e * IMOR_01$m2.IMOR.e + 1-IMOR_01$p.e)^2-1) +
       IMOR_01$m3.a.e * (IMOR_01$m3.IMOR.e/(IMOR_01$p.e * IMOR_01$m3.IMOR.e + 1-IMOR_01$p.e)^2-1) +
       IMOR_01$m4.a.e * (IMOR_01$m4.IMOR.e/(IMOR_01$p.e * IMOR_01$m4.IMOR.e + 1-IMOR_01$p.e)^2-1) +
       IMOR_01$m5.a.e * (IMOR_01$m5.IMOR.e/(IMOR_01$p.e * IMOR_01$m5.IMOR.e + 1-IMOR_01$p.e)^2-1)
    )^2 +
    (1/IMOR_01$N.e) * 
    ((IMOR_01$p.e - IMOR_01$p.star.e)^2 +
       IMOR_01$m1.a.e * ((IMOR_01$m1.p.e-IMOR_01$p.star.e)^2-(IMOR_01$p.e-IMOR_01$p.star.e)^2) +
       IMOR_01$m2.a.e * ((IMOR_01$m2.p.e-IMOR_01$p.star.e)^2-(IMOR_01$p.e-IMOR_01$p.star.e)^2) +
       IMOR_01$m3.a.e * ((IMOR_01$m3.p.e-IMOR_01$p.star.e)^2-(IMOR_01$p.e-IMOR_01$p.star.e)^2) +
       IMOR_01$m4.a.e * ((IMOR_01$m4.p.e-IMOR_01$p.star.e)^2-(IMOR_01$p.e-IMOR_01$p.star.e)^2) +
       IMOR_01$m5.a.e * ((IMOR_01$m5.p.e-IMOR_01$p.star.e)^2-(IMOR_01$p.e-IMOR_01$p.star.e)^2)
    )
  
  IMOR_01$var.p.star.c <- IMOR_01$p.c*(1-IMOR_01$p.c)/(IMOR_01$N.c-IMOR_01$m.c) *
    (1 +
       IMOR_01$m1.a.c * (IMOR_01$m1.IMOR.c/(IMOR_01$p.c * IMOR_01$m1.IMOR.c + 1-IMOR_01$p.c)^2-1) +
       IMOR_01$m2.a.c * (IMOR_01$m2.IMOR.c/(IMOR_01$p.c * IMOR_01$m2.IMOR.c + 1-IMOR_01$p.c)^2-1) +
       IMOR_01$m3.a.c * (IMOR_01$m3.IMOR.c/(IMOR_01$p.c * IMOR_01$m3.IMOR.c + 1-IMOR_01$p.c)^2-1) +
       IMOR_01$m4.a.c * (IMOR_01$m4.IMOR.c/(IMOR_01$p.c * IMOR_01$m4.IMOR.c + 1-IMOR_01$p.c)^2-1) +
       IMOR_01$m5.a.c * (IMOR_01$m5.IMOR.c/(IMOR_01$p.c * IMOR_01$m5.IMOR.c + 1-IMOR_01$p.c)^2-1)
    )^2 +
    (1/IMOR_01$N.c) * 
    ((IMOR_01$p.c - IMOR_01$p.star.c)^2 +
       IMOR_01$m1.a.c * ((IMOR_01$m1.p.c-IMOR_01$p.star.c)^2-(IMOR_01$p.c-IMOR_01$p.star.c)^2) +
       IMOR_01$m2.a.c * ((IMOR_01$m2.p.c-IMOR_01$p.star.c)^2-(IMOR_01$p.c-IMOR_01$p.star.c)^2) +
       IMOR_01$m3.a.c * ((IMOR_01$m3.p.c-IMOR_01$p.star.c)^2-(IMOR_01$p.c-IMOR_01$p.star.c)^2) +
       IMOR_01$m4.a.c * ((IMOR_01$m4.p.c-IMOR_01$p.star.c)^2-(IMOR_01$p.c-IMOR_01$p.star.c)^2) +
       IMOR_01$m5.a.c * ((IMOR_01$m5.p.c-IMOR_01$p.star.c)^2-(IMOR_01$p.c-IMOR_01$p.star.c)^2)
    )
  
  IMOR_01$var.p.e <- IMOR_01$p.e*(1-IMOR_01$p.e)/(IMOR_01$N.e-IMOR_01$m.e)
  IMOR_01$var.p.c <- IMOR_01$p.c*(1-IMOR_01$p.c)/(IMOR_01$N.c-IMOR_01$m.c)
  
  IMOR_01$logOR <- log((IMOR_01$p.e/(1-IMOR_01$p.e))/(IMOR_01$p.c/(1-IMOR_01$p.c)))
  IMOR_01$var.logOR <- 
    IMOR_01$var.p.e/(IMOR_01$p.e*(1-IMOR_01$p.e))^2 +
    IMOR_01$var.p.c/(IMOR_01$p.c*(1-IMOR_01$p.c))^2
  
  IMOR_01$logOR.star <- log((IMOR_01$p.star.e/(1-IMOR_01$p.star.e))/(IMOR_01$p.star.c/(1-IMOR_01$p.star.c)))
  IMOR_01$var.logOR.star <- 
    IMOR_01$var.p.star.e/(IMOR_01$p.star.e*(1-IMOR_01$p.star.e))^2 +
    IMOR_01$var.p.star.c/(IMOR_01$p.star.c*(1-IMOR_01$p.star.c))^2
  
  IMOR_01$logRR <- log(IMOR_01$p.e/IMOR_01$p.c)
  IMOR_01$var.logRR <- 
    IMOR_01$var.p.e/(IMOR_01$p.e)^2 +
    IMOR_01$var.p.c/(IMOR_01$p.c)^2
  
  IMOR_01$logRR.star <- log(IMOR_01$p.star.e/IMOR_01$p.star.c)
  IMOR_01$var.logRR.star <- 
    IMOR_01$var.p.star.e/(IMOR_01$p.star.e)^2 +
    IMOR_01$var.p.star.c/(IMOR_01$p.star.c)^2
  
  # Now IMOR_10
  IMOR_10$m1.p.e <- 1
  IMOR_10$m2.p.e <- 1
  IMOR_10$m3.p.e <- 1
  IMOR_10$m4.p.e <- 1
  IMOR_10$m5.p.e <- 1
  
  # IMOR = odds of m1 (m2,m3, m4) by odds of not missing
  # Odds = Risk/(1-Risk)
  IMOR_10$m1.IMOR.e <- ifelse(IMOR_10$m1.p.e == 1,1e8,(IMOR_10$m1.p.e/(1-IMOR_10$m1.p.e))/(IMOR_10$p.e/(1-IMOR_10$p.e)))
  IMOR_10$m2.IMOR.e <- ifelse(IMOR_10$m2.p.e == 1,1e8,(IMOR_10$m2.p.e/(1-IMOR_10$m2.p.e))/(IMOR_10$p.e/(1-IMOR_10$p.e)))
  IMOR_10$m3.IMOR.e <- ifelse(IMOR_10$m3.p.e == 1,1e8,(IMOR_10$m3.p.e/(1-IMOR_10$m3.p.e))/(IMOR_10$p.e/(1-IMOR_10$p.e)))
  IMOR_10$m4.IMOR.e <- ifelse(IMOR_10$m4.p.e == 1,1e8,(IMOR_10$m4.p.e/(1-IMOR_10$m4.p.e))/(IMOR_10$p.e/(1-IMOR_10$p.e)))
  IMOR_10$m5.IMOR.e <- ifelse(IMOR_10$m5.p.e == 1,1e8,(IMOR_10$m5.p.e/(1-IMOR_10$m5.p.e))/(IMOR_10$p.e/(1-IMOR_10$p.e)))
  
  IMOR_10$m1.p.c <- 0
  IMOR_10$m2.p.c <- 0
  IMOR_10$m3.p.c <- 0
  IMOR_10$m4.p.c <- 0
  IMOR_10$m5.p.c <- 0
  
  IMOR_10$m1.IMOR.c <- ifelse(IMOR_10$m1.p.c == 1,1e8,(IMOR_10$m1.p.c/(1-IMOR_10$m1.p.c))/(IMOR_10$p.c/(1-IMOR_10$p.c)))
  IMOR_10$m2.IMOR.c <- ifelse(IMOR_10$m2.p.c == 1,1e8,(IMOR_10$m2.p.c/(1-IMOR_10$m2.p.c))/(IMOR_10$p.c/(1-IMOR_10$p.c)))
  IMOR_10$m3.IMOR.c <- ifelse(IMOR_10$m3.p.c == 1,1e8,(IMOR_10$m3.p.c/(1-IMOR_10$m3.p.c))/(IMOR_10$p.c/(1-IMOR_10$p.c)))
  IMOR_10$m4.IMOR.c <- ifelse(IMOR_10$m4.p.c == 1,1e8,(IMOR_10$m4.p.c/(1-IMOR_10$m4.p.c))/(IMOR_10$p.c/(1-IMOR_10$p.c)))
  IMOR_10$m5.IMOR.c <- ifelse(IMOR_10$m5.p.c == 1,1e8,(IMOR_10$m5.p.c/(1-IMOR_10$m5.p.c))/(IMOR_10$p.c/(1-IMOR_10$p.c)))
  
  IMOR_10$p.star.e <- IMOR_10$p.e*(1-IMOR_10$a.e) + 
    IMOR_10$m1.a.e * (IMOR_10$p.e*IMOR_10$m1.IMOR.e)/(IMOR_10$p.e*IMOR_10$m1.IMOR.e+1-IMOR_10$p.e) +
    IMOR_10$m2.a.e * (IMOR_10$p.e*IMOR_10$m2.IMOR.e)/(IMOR_10$p.e*IMOR_10$m2.IMOR.e+1-IMOR_10$p.e) +
    IMOR_10$m3.a.e * (IMOR_10$p.e*IMOR_10$m3.IMOR.e)/(IMOR_10$p.e*IMOR_10$m3.IMOR.e+1-IMOR_10$p.e) +
    IMOR_10$m4.a.e * (IMOR_10$p.e*IMOR_10$m4.IMOR.e)/(IMOR_10$p.e*IMOR_10$m4.IMOR.e+1-IMOR_10$p.e) +
    IMOR_10$m5.a.e * (IMOR_10$p.e*IMOR_10$m5.IMOR.e)/(IMOR_10$p.e*IMOR_10$m5.IMOR.e+1-IMOR_10$p.e)
  
  IMOR_10$p.star.c <- IMOR_10$p.c*(1-IMOR_10$a.c) + 
    IMOR_10$m1.a.c * (IMOR_10$p.c*IMOR_10$m1.IMOR.c)/(IMOR_10$p.c*IMOR_10$m1.IMOR.c+1-IMOR_10$p.c) +
    IMOR_10$m2.a.c * (IMOR_10$p.c*IMOR_10$m2.IMOR.c)/(IMOR_10$p.c*IMOR_10$m2.IMOR.c+1-IMOR_10$p.c) +
    IMOR_10$m3.a.c * (IMOR_10$p.c*IMOR_10$m3.IMOR.c)/(IMOR_10$p.c*IMOR_10$m3.IMOR.c+1-IMOR_10$p.c) +
    IMOR_10$m4.a.c * (IMOR_10$p.c*IMOR_10$m4.IMOR.c)/(IMOR_10$p.c*IMOR_10$m4.IMOR.c+1-IMOR_10$p.c) +
    IMOR_10$m5.a.c * (IMOR_10$p.c*IMOR_10$m5.IMOR.c)/(IMOR_10$p.c*IMOR_10$m5.IMOR.c+1-IMOR_10$p.c)
  
  IMOR_10$var.p.star.e <- IMOR_10$p.e*(1-IMOR_10$p.e)/(IMOR_10$N.e-IMOR_10$m.e) *
    (1 +
       IMOR_10$m1.a.e * (IMOR_10$m1.IMOR.e/(IMOR_10$p.e * IMOR_10$m1.IMOR.e + 1-IMOR_10$p.e)^2-1) +
       IMOR_10$m2.a.e * (IMOR_10$m2.IMOR.e/(IMOR_10$p.e * IMOR_10$m2.IMOR.e + 1-IMOR_10$p.e)^2-1) +
       IMOR_10$m3.a.e * (IMOR_10$m3.IMOR.e/(IMOR_10$p.e * IMOR_10$m3.IMOR.e + 1-IMOR_10$p.e)^2-1) +
       IMOR_10$m4.a.e * (IMOR_10$m4.IMOR.e/(IMOR_10$p.e * IMOR_10$m4.IMOR.e + 1-IMOR_10$p.e)^2-1) +
       IMOR_10$m5.a.e * (IMOR_10$m5.IMOR.e/(IMOR_10$p.e * IMOR_10$m5.IMOR.e + 1-IMOR_10$p.e)^2-1)
    )^2 +
    (1/IMOR_10$N.e) * 
    ((IMOR_10$p.e - IMOR_10$p.star.e)^2 +
       IMOR_10$m1.a.e * ((IMOR_10$m1.p.e-IMOR_10$p.star.e)^2-(IMOR_10$p.e-IMOR_10$p.star.e)^2) +
       IMOR_10$m2.a.e * ((IMOR_10$m2.p.e-IMOR_10$p.star.e)^2-(IMOR_10$p.e-IMOR_10$p.star.e)^2) +
       IMOR_10$m3.a.e * ((IMOR_10$m3.p.e-IMOR_10$p.star.e)^2-(IMOR_10$p.e-IMOR_10$p.star.e)^2) +
       IMOR_10$m4.a.e * ((IMOR_10$m4.p.e-IMOR_10$p.star.e)^2-(IMOR_10$p.e-IMOR_10$p.star.e)^2) +
       IMOR_10$m5.a.e * ((IMOR_10$m5.p.e-IMOR_10$p.star.e)^2-(IMOR_10$p.e-IMOR_10$p.star.e)^2)
    )
  
  IMOR_10$var.p.star.c <- IMOR_10$p.c*(1-IMOR_10$p.c)/(IMOR_10$N.c-IMOR_10$m.c) *
    (1 +
       IMOR_10$m1.a.c * (IMOR_10$m1.IMOR.c/(IMOR_10$p.c * IMOR_10$m1.IMOR.c + 1-IMOR_10$p.c)^2-1) +
       IMOR_10$m2.a.c * (IMOR_10$m2.IMOR.c/(IMOR_10$p.c * IMOR_10$m2.IMOR.c + 1-IMOR_10$p.c)^2-1) +
       IMOR_10$m3.a.c * (IMOR_10$m3.IMOR.c/(IMOR_10$p.c * IMOR_10$m3.IMOR.c + 1-IMOR_10$p.c)^2-1) +
       IMOR_10$m4.a.c * (IMOR_10$m4.IMOR.c/(IMOR_10$p.c * IMOR_10$m4.IMOR.c + 1-IMOR_10$p.c)^2-1) +
       IMOR_10$m5.a.c * (IMOR_10$m5.IMOR.c/(IMOR_10$p.c * IMOR_10$m5.IMOR.c + 1-IMOR_10$p.c)^2-1)
    )^2 +
    (1/IMOR_10$N.c) * 
    ((IMOR_10$p.c - IMOR_10$p.star.c)^2 +
       IMOR_10$m1.a.c * ((IMOR_10$m1.p.c-IMOR_10$p.star.c)^2-(IMOR_10$p.c-IMOR_10$p.star.c)^2) +
       IMOR_10$m2.a.c * ((IMOR_10$m2.p.c-IMOR_10$p.star.c)^2-(IMOR_10$p.c-IMOR_10$p.star.c)^2) +
       IMOR_10$m3.a.c * ((IMOR_10$m3.p.c-IMOR_10$p.star.c)^2-(IMOR_10$p.c-IMOR_10$p.star.c)^2) +
       IMOR_10$m4.a.c * ((IMOR_10$m4.p.c-IMOR_10$p.star.c)^2-(IMOR_10$p.c-IMOR_10$p.star.c)^2) +
       IMOR_10$m5.a.c * ((IMOR_10$m5.p.c-IMOR_10$p.star.c)^2-(IMOR_10$p.c-IMOR_10$p.star.c)^2)
    )
  
  IMOR_10$var.p.e <- IMOR_10$p.e*(1-IMOR_10$p.e)/(IMOR_10$N.e-IMOR_10$m.e)
  IMOR_10$var.p.c <- IMOR_10$p.c*(1-IMOR_10$p.c)/(IMOR_10$N.c-IMOR_10$m.c)
  
  IMOR_10$logOR <- log((IMOR_10$p.e/(1-IMOR_10$p.e))/(IMOR_10$p.c/(1-IMOR_10$p.c)))
  IMOR_10$var.logOR <- 
    IMOR_10$var.p.e/(IMOR_10$p.e*(1-IMOR_10$p.e))^2 +
    IMOR_10$var.p.c/(IMOR_10$p.c*(1-IMOR_10$p.c))^2
  
  IMOR_10$logOR.star <- log((IMOR_10$p.star.e/(1-IMOR_10$p.star.e))/(IMOR_10$p.star.c/(1-IMOR_10$p.star.c)))
  IMOR_10$var.logOR.star <- 
    IMOR_10$var.p.star.e/(IMOR_10$p.star.e*(1-IMOR_10$p.star.e))^2 +
    IMOR_10$var.p.star.c/(IMOR_10$p.star.c*(1-IMOR_10$p.star.c))^2
  
  IMOR_10$logRR <- log(IMOR_10$p.e/IMOR_10$p.c)
  IMOR_10$var.logRR <- 
    IMOR_10$var.p.e/(IMOR_10$p.e)^2 +
    IMOR_10$var.p.c/(IMOR_10$p.c)^2
  
  IMOR_10$logRR.star <- log(IMOR_10$p.star.e/IMOR_10$p.star.c)
  IMOR_10$var.logRR.star <- 
    IMOR_10$var.p.star.e/(IMOR_10$p.star.e)^2 +
    IMOR_10$var.p.star.c/(IMOR_10$p.star.c)^2
  
  # IMOR for all missing causes (IMOR_M)
  # Here IMOR is given and p has to be calculated
  IMOR_M$m1.IMOR.e <- IMOR_E
  IMOR_M$m2.IMOR.e <- IMOR_E
  IMOR_M$m3.IMOR.e <- IMOR_E
  IMOR_M$m4.IMOR.e <- IMOR_E
  IMOR_M$m5.IMOR.e <- IMOR_E
  IMOR_M$m1.p.e <- IMOR_M$p.e*IMOR_M$m1.IMOR.e/(IMOR_M$p.e*IMOR_M$m1.IMOR.e + 1 - IMOR_M$p.e)
  IMOR_M$m2.p.e <- IMOR_M$p.e*IMOR_M$m2.IMOR.e/(IMOR_M$p.e*IMOR_M$m2.IMOR.e + 1 - IMOR_M$p.e)
  IMOR_M$m3.p.e <- IMOR_M$p.e*IMOR_M$m3.IMOR.e/(IMOR_M$p.e*IMOR_M$m3.IMOR.e + 1 - IMOR_M$p.e)
  IMOR_M$m4.p.e <- IMOR_M$p.e*IMOR_M$m4.IMOR.e/(IMOR_M$p.e*IMOR_M$m4.IMOR.e + 1 - IMOR_M$p.e)
  IMOR_M$m5.p.e <- IMOR_M$p.e*IMOR_M$m5.IMOR.e/(IMOR_M$p.e*IMOR_M$m5.IMOR.e + 1 - IMOR_M$p.e)
  
  IMOR_M$m1.IMOR.c <- IMOR_C
  IMOR_M$m2.IMOR.c <- IMOR_C
  IMOR_M$m3.IMOR.c <- IMOR_C
  IMOR_M$m4.IMOR.c <- IMOR_C
  IMOR_M$m5.IMOR.c <- IMOR_C
  IMOR_M$m1.p.c <- IMOR_M$p.c*IMOR_M$m1.IMOR.c/(IMOR_M$p.c*IMOR_M$m1.IMOR.c + 1 - IMOR_M$p.c)
  IMOR_M$m2.p.c <- IMOR_M$p.c*IMOR_M$m2.IMOR.c/(IMOR_M$p.c*IMOR_M$m2.IMOR.c + 1 - IMOR_M$p.c)
  IMOR_M$m3.p.c <- IMOR_M$p.c*IMOR_M$m3.IMOR.c/(IMOR_M$p.c*IMOR_M$m3.IMOR.c + 1 - IMOR_M$p.c)
  IMOR_M$m4.p.c <- IMOR_M$p.c*IMOR_M$m4.IMOR.c/(IMOR_M$p.c*IMOR_M$m4.IMOR.c + 1 - IMOR_M$p.c)
  IMOR_M$m5.p.c <- IMOR_M$p.c*IMOR_M$m5.IMOR.c/(IMOR_M$p.c*IMOR_M$m5.IMOR.c + 1 - IMOR_M$p.c)
  
  IMOR_M$p.star.e <- IMOR_M$p.e*(1-IMOR_M$a.e) + 
    IMOR_M$m1.a.e * (IMOR_M$p.e*IMOR_M$m1.IMOR.e)/(IMOR_M$p.e*IMOR_M$m1.IMOR.e+1-IMOR_M$p.e) +
    IMOR_M$m2.a.e * (IMOR_M$p.e*IMOR_M$m2.IMOR.e)/(IMOR_M$p.e*IMOR_M$m2.IMOR.e+1-IMOR_M$p.e) +
    IMOR_M$m3.a.e * (IMOR_M$p.e*IMOR_M$m3.IMOR.e)/(IMOR_M$p.e*IMOR_M$m3.IMOR.e+1-IMOR_M$p.e) +
    IMOR_M$m4.a.e * (IMOR_M$p.e*IMOR_M$m4.IMOR.e)/(IMOR_M$p.e*IMOR_M$m4.IMOR.e+1-IMOR_M$p.e) +
    IMOR_M$m5.a.e * (IMOR_M$p.e*IMOR_M$m5.IMOR.e)/(IMOR_M$p.e*IMOR_M$m5.IMOR.e+1-IMOR_M$p.e)
  
  IMOR_M$p.star.c <- IMOR_M$p.c*(1-IMOR_M$a.c) + 
    IMOR_M$m1.a.c * (IMOR_M$p.c*IMOR_M$m1.IMOR.c)/(IMOR_M$p.c*IMOR_M$m1.IMOR.c+1-IMOR_M$p.c) +
    IMOR_M$m2.a.c * (IMOR_M$p.c*IMOR_M$m2.IMOR.c)/(IMOR_M$p.c*IMOR_M$m2.IMOR.c+1-IMOR_M$p.c) +
    IMOR_M$m3.a.c * (IMOR_M$p.c*IMOR_M$m3.IMOR.c)/(IMOR_M$p.c*IMOR_M$m3.IMOR.c+1-IMOR_M$p.c) +
    IMOR_M$m4.a.c * (IMOR_M$p.c*IMOR_M$m4.IMOR.c)/(IMOR_M$p.c*IMOR_M$m4.IMOR.c+1-IMOR_M$p.c) +
    IMOR_M$m5.a.c * (IMOR_M$p.c*IMOR_M$m5.IMOR.c)/(IMOR_M$p.c*IMOR_M$m5.IMOR.c+1-IMOR_M$p.c)
  
  IMOR_M$var.p.star.e <- IMOR_M$p.e*(1-IMOR_M$p.e)/(IMOR_M$N.e-IMOR_M$m.e) *
    (1 +
       IMOR_M$m1.a.e * (IMOR_M$m1.IMOR.e/(IMOR_M$p.e * IMOR_M$m1.IMOR.e + 1-IMOR_M$p.e)^2-1) +
       IMOR_M$m2.a.e * (IMOR_M$m2.IMOR.e/(IMOR_M$p.e * IMOR_M$m2.IMOR.e + 1-IMOR_M$p.e)^2-1) +
       IMOR_M$m3.a.e * (IMOR_M$m3.IMOR.e/(IMOR_M$p.e * IMOR_M$m3.IMOR.e + 1-IMOR_M$p.e)^2-1) +
       IMOR_M$m4.a.e * (IMOR_M$m4.IMOR.e/(IMOR_M$p.e * IMOR_M$m4.IMOR.e + 1-IMOR_M$p.e)^2-1) +
       IMOR_M$m5.a.e * (IMOR_M$m5.IMOR.e/(IMOR_M$p.e * IMOR_M$m5.IMOR.e + 1-IMOR_M$p.e)^2-1)
    )^2 +
    (1/IMOR_M$N.e) * 
    ((IMOR_M$p.e - IMOR_M$p.star.e)^2 +
       IMOR_M$m1.a.e * ((IMOR_M$m1.p.e-IMOR_M$p.star.e)^2-(IMOR_M$p.e-IMOR_M$p.star.e)^2) +
       IMOR_M$m2.a.e * ((IMOR_M$m2.p.e-IMOR_M$p.star.e)^2-(IMOR_M$p.e-IMOR_M$p.star.e)^2) +
       IMOR_M$m3.a.e * ((IMOR_M$m3.p.e-IMOR_M$p.star.e)^2-(IMOR_M$p.e-IMOR_M$p.star.e)^2) +
       IMOR_M$m4.a.e * ((IMOR_M$m4.p.e-IMOR_M$p.star.e)^2-(IMOR_M$p.e-IMOR_M$p.star.e)^2) +
       IMOR_M$m5.a.e * ((IMOR_M$m5.p.e-IMOR_M$p.star.e)^2-(IMOR_M$p.e-IMOR_M$p.star.e)^2)
    )
  
  IMOR_M$var.p.star.c <- IMOR_M$p.c*(1-IMOR_M$p.c)/(IMOR_M$N.c-IMOR_M$m.c) *
    (1 +
       IMOR_M$m1.a.c * (IMOR_M$m1.IMOR.c/(IMOR_M$p.c * IMOR_M$m1.IMOR.c + 1-IMOR_M$p.c)^2-1) +
       IMOR_M$m2.a.c * (IMOR_M$m2.IMOR.c/(IMOR_M$p.c * IMOR_M$m2.IMOR.c + 1-IMOR_M$p.c)^2-1) +
       IMOR_M$m3.a.c * (IMOR_M$m3.IMOR.c/(IMOR_M$p.c * IMOR_M$m3.IMOR.c + 1-IMOR_M$p.c)^2-1) +
       IMOR_M$m4.a.c * (IMOR_M$m4.IMOR.c/(IMOR_M$p.c * IMOR_M$m4.IMOR.c + 1-IMOR_M$p.c)^2-1) +
       IMOR_M$m5.a.c * (IMOR_M$m5.IMOR.c/(IMOR_M$p.c * IMOR_M$m5.IMOR.c + 1-IMOR_M$p.c)^2-1)
    )^2 +
    (1/IMOR_M$N.c) * 
    ((IMOR_M$p.c - IMOR_M$p.star.c)^2 +
       IMOR_M$m1.a.c * ((IMOR_M$m1.p.c-IMOR_M$p.star.c)^2-(IMOR_M$p.c-IMOR_M$p.star.c)^2) +
       IMOR_M$m2.a.c * ((IMOR_M$m2.p.c-IMOR_M$p.star.c)^2-(IMOR_M$p.c-IMOR_M$p.star.c)^2) +
       IMOR_M$m3.a.c * ((IMOR_M$m3.p.c-IMOR_M$p.star.c)^2-(IMOR_M$p.c-IMOR_M$p.star.c)^2) +
       IMOR_M$m4.a.c * ((IMOR_M$m4.p.c-IMOR_M$p.star.c)^2-(IMOR_M$p.c-IMOR_M$p.star.c)^2) +
       IMOR_M$m5.a.c * ((IMOR_M$m5.p.c-IMOR_M$p.star.c)^2-(IMOR_M$p.c-IMOR_M$p.star.c)^2)
    )
  
  IMOR_M$var.p.e <- IMOR_M$p.e*(1-IMOR_M$p.e)/(IMOR_M$N.e-IMOR_M$m.e)
  IMOR_M$var.p.c <- IMOR_M$p.c*(1-IMOR_M$p.c)/(IMOR_M$N.c-IMOR_M$m.c)
  
  IMOR_M$logOR <- log((IMOR_M$p.e/(1-IMOR_M$p.e))/(IMOR_M$p.c/(1-IMOR_M$p.c)))
  IMOR_M$var.logOR <- 
    IMOR_M$var.p.e/(IMOR_M$p.e*(1-IMOR_M$p.e))^2 +
    IMOR_M$var.p.c/(IMOR_M$p.c*(1-IMOR_M$p.c))^2
  
  IMOR_M$logOR.star <- log((IMOR_M$p.star.e/(1-IMOR_M$p.star.e))/(IMOR_M$p.star.c/(1-IMOR_M$p.star.c)))
  IMOR_M$var.logOR.star <- 
    IMOR_M$var.p.star.e/(IMOR_M$p.star.e*(1-IMOR_M$p.star.e))^2 +
    IMOR_M$var.p.star.c/(IMOR_M$p.star.c*(1-IMOR_M$p.star.c))^2
  
  IMOR_M$logRR <- log(IMOR_M$p.e/IMOR_M$p.c)
  IMOR_M$var.logRR <- 
    IMOR_M$var.p.e/(IMOR_M$p.e)^2 +
    IMOR_M$var.p.c/(IMOR_M$p.c)^2
  
  IMOR_M$logRR.star <- log(IMOR_M$p.star.e/IMOR_M$p.star.c)
  IMOR_M$var.logRR.star <- 
    IMOR_M$var.p.star.e/(IMOR_M$p.star.e)^2 +
    IMOR_M$var.p.star.c/(IMOR_M$p.star.c)^2
  
  # Meta-analysis generic inverse variance random-effects meta-analysis
  # Effect measure from the meta-analysis
  EffectMeasure <- MA$sm
  # add the study labels to the front of IMORs
  IMOR <- cbind(Study=as.character(df_Outcome[,4]),IMOR)
  IMOR_01 <- cbind(Study=as.character(df_Outcome[,4]),IMOR_01)
  IMOR_10 <- cbind(Study=as.character(df_Outcome[,4]),IMOR_10)
  IMOR_M <- cbind(Study=as.character(df_Outcome[,4]),IMOR_M)
  
  if (EffectMeasure == "OR" | EffectMeasure == "RR") {
    MA_IMOR <- metagen(
      IMOR[,match(ifelse(EffectMeasure == "OR","logOR.star","logRR.star"),colnames(IMOR))],
      IMOR[,match(ifelse(EffectMeasure == "OR","var.logOR.star","var.logRR.star"),colnames(IMOR))],
      n.e = IMOR$N.e,
      n.c = IMOR$N.c,
      data = IMOR,
      studlab = IMOR$Study,
      text.common = "Fixed effect model",
      text.w.common = "fixed",
      common = MA$common,
      sm = EffectMeasure,
      method.random.ci = MA$method.random.ci,
      method.predict = ifelse(MA$method == "GLMM","HTS","HK"),
      prediction = MA$prediction,
      outclab = MA$outclab,
      label.e = MA$label.e,
      label.c = MA$label.c,
      label.left = MA$label.left,
      label.right = MA$label.right
    )
    MA_IMOR_01 <- metagen(
      IMOR_01[,match(ifelse(EffectMeasure == "OR","logOR.star","logRR.star"),colnames(IMOR_01))],
      IMOR_01[,match(ifelse(EffectMeasure == "OR","var.logOR.star","var.logRR.star"),colnames(IMOR_01))],
      n.e = IMOR_01$N.e,
      n.c = IMOR_01$N.c,
      data = IMOR_01,
      studlab = IMOR_01$Study,
      text.common = "Fixed effect model",
      text.w.common = "fixed",
      common = MA$common,
      sm = EffectMeasure,
      method.random.ci = MA$method.random.ci,
      method.predict = ifelse(MA$method == "GLMM","HTS","HK"),
      prediction = MA$prediction,
      outclab = MA$outclab,
      label.e = MA$label.e,
      label.c = MA$label.c,
      label.left = MA$label.left,
      label.right = MA$label.right
    )
    MA_IMOR_10 <- metagen(
      IMOR_10[,match(ifelse(EffectMeasure == "OR","logOR.star","logRR.star"),colnames(IMOR_10))],
      IMOR_10[,match(ifelse(EffectMeasure == "OR","var.logOR.star","var.logRR.star"),colnames(IMOR_10))],
      n.e = IMOR_10$N.e,
      n.c = IMOR_10$N.c,
      data = IMOR_10,
      studlab = IMOR_10$Study,
      text.common = "Fixed effect model",
      text.w.common = "fixed",
      common = MA$common,
      sm = EffectMeasure,
      method.random.ci = MA$method.random.ci,
      method.predict = ifelse(MA$method == "GLMM","HTS","HK"),
      prediction = MA$prediction,
      outclab = MA$outclab,
      label.e = MA$label.e,
      label.c = MA$label.c,
      label.left = MA$label.left,
      label.right = MA$label.right
    )
    MA_IMOR_M <- metagen(
      IMOR_M[,match(ifelse(EffectMeasure == "OR","logOR.star","logRR.star"),colnames(IMOR_M))],
      IMOR_M[,match(ifelse(EffectMeasure == "OR","var.logOR.star","var.logRR.star"),colnames(IMOR_M))],
      n.e = IMOR_M$N.e,
      n.c = IMOR_M$N.c,
      data = IMOR_M,
      studlab = IMOR_M$Study,
      text.common = "Fixed effect model",
      text.w.common = "fixed",
      common = MA$common,
      sm = EffectMeasure,
      method.random.ci = MA$method.random.ci,
      method.predict = ifelse(MA$method == "GLMM","HTS","HK"),
      prediction = MA$prediction,
      outclab = MA$outclab,
      label.e = MA$label.e,
      label.c = MA$label.c,
      label.left = MA$label.left,
      label.right = MA$label.right
    )
    
  } else {
    MA_IMOR <- as.character("Sensitivity analysis is usually conducted for the effect measure used in the primary analysis only")
    MA_IMOR_01 <- as.character("Sensitivity analysis is usually conducted for the effect measure used in the primary analysis only")
    MA_IMOR_10 <- as.character("Sensitivity analysis is usually conducted for the effect measure used in the primary analysis only")
    MA_IMOR_M <- as.character("Sensitivity analysis is usually conducted for the effect measure used in the primary analysis only")
  }
  
  ifelse(tolower(df_Outcome[1,3]) == "worse",
         return(list("Missing outcome analysis (according to reason)" = MA_IMOR,"Best-worst analysis" = MA_IMOR_01,"Worst-best analysis" = MA_IMOR_10,"Missing outcome analysis (no reasons provided)" = MA_IMOR_M)),
         return(list("Missing outcome analysis (according to reason)" = MA_IMOR,"Best-worst analysis" = MA_IMOR_10,"Worst-best analysis" = MA_IMOR_01,"Missing outcome analysis (no reasons provided)" = MA_IMOR_M))
  )
}
# Functions for reference screener ####
rbind.missing <- function(x,y) {
  # With Pubmed, when multiple files are uploaded, some fields may be missing in some of the files
  # This causes error with rbind
  # To avoid this error, create new missing columns in both files and then combine
  p = colnames(x)
  q = colnames(y)
  r = p[is.na(match(p,q))] # Columns in x missing in y
  s = q[is.na(match(q,p))] # Columns in y missing in x
  # Add columns in y missing in x
  if (length(s)>0){
    t = data.frame(matrix(NA,nrow = nrow(x), ncol = length(s)))
    colnames(t) <- s
    x <- data.frame(cbind(x, t))
  }
  # Add columns in x missing in y
  if (length(r)>0){
    u = data.frame(matrix(NA,nrow = nrow(y), ncol = length(r)))
    colnames(u) <- r
    y <- data.frame(cbind(y, u))
  }
  # Now add the rows
  rbind(x,y)
}
cbind.missing <- function(x,y) {
  # When summarising the results from databases, the import summary and individual files have different lengths
  # This causes error with cbind
  # To avoid this error, create new rows in the dataframe with fewer rows and then combine
  if (nrow(x) == nrow(y)) {
    data.frame(cbind(x, y))
  } else if (nrow(x) < nrow(y)) {
    x[nrow(x)+(nrow(y) - nrow(x)),]<-NA
    data.frame(cbind(x, y))
  } else {
    y[nrow(y)+(nrow(x) - nrow(y)),]<-NA
    data.frame(cbind(x, y))
  }
}
# Convert pmid format to csv
import.pmid <- function(p) {
  p <- data.frame(p)
  colnames(p) <- "initial"
  p$tag <- NA
  p$pmid <- NA
  p$content <- p$initial
  p$content[substr(p$initial,5,5) == "-"] <- substr(p$initial[substr(p$initial,5,5) == "-"],6,nchar(p$initial[substr(p$initial,5,5) == "-"])) 
  p$tag[substr(p$initial,5,5) == "-"] <- substr(p$initial[substr(p$initial,5,5) == "-"],1,4) 
  p$tag = trimws(p$tag)
  p$tag <- na.locf(na.locf(p$tag),fromLast=TRUE)
  p$content <- trimws(p$content)
  p$pmid[p$tag == "PMID"] <- trimws(
    substr(p$initial[p$tag == "PMID"],6,nchar(p$initial[p$tag == "PMID"]))
  )
  p$pmid <- na.locf(na.locf(p$pmid),fromLast=TRUE)
  # For article identifier, keep only the doi
  p$content[
    (
      (p$tag == "AID") & 
        (substr(p$content,
                (nchar(p$content)-4),
                nchar(p$content)
        ) != "[doi]"
        )
    )
  ] <- ""
  p <- p[p$content !="",]
  p$content[p$tag == "AID"] <- paste0("https://doi.org/",
                                      trimws(
                                        substr(p$content[p$tag == "AID"],
                                               1, (nchar(p$content[p$tag == "AID"])-5)
                                        )
                                      )
  )
  # Convert data to wide format
  suppressWarnings(
    suppressMessages(
      q <- pivot_wider(p[,c("pmid","tag","content")], names_from = tag, values_from = content)
    )
  )
  # The output is in the form of a list because of multiple rows for some fields
  # Convert this into one row per reference
  r <- data.frame(matrix(nrow = length(q[[1]]), ncol = 0))
  for (i in 2:length(q)) {
    s <- vector()
    for (j in 1:length(q[[i]])) {
      if (is.null(q[[i]][[j]])) {
        s <- c(s, NA)
      } else {
        if (!is.na(q[[i]][[j]][1])) {
          if (length(q[[i]][[j]][1] > 1)){
            s <- c(s, substr(trimws(paste0(q[[i]][[j]], collapse = "\n")),1,20000))
          } else {
            s <- c(s, trimws(q[[i]][[j]][1]))
          }
        } else {
          s <- c(s, NA)
        }
      }
    }
    r <- data.frame(cbind(r, s))
    colnames(r)[ncol(r)] <- colnames(q)[i]
  }
  # Remove the dots from the column names
  colnames(r) <- str_remove_all(colnames(r),"\\.")
  r
}
import.embase <- function(x) {
  x$AE <- trimws(x$AE)
  x$AE[x$AE == ""] <- trimws(x$AD[x$AE == ""])
  x
}
import.wos <- function(x) {
  # The doi in DL is not correct (insecure link) - Create a secure link from DI
  x$DI <- trimws(x$DI)
  x$DL[x$DI != ""] <- paste0(
    "https://doi.org/",
    x$DI[x$DI != ""]  
  )
  # If author email is missing, get the author address
  x$EM[x$EM == ""] <- x$C3[x$EM == ""]
  # Page numbers have to be calculated. This can be stored in a new field "PGN" (as PG is used for number of pages)
  x$PGN <- ""
  # If start page and end page are the same (or if end page is missing with start page not missing), then only the start page should be mentioned
  x$PGN[
    (
      (x$BP != "") &
        ((x$EP == "") | (x$EP == x$BP))
    )
  ] <- 
    x$BP[
      (
        (x$BP != "") &
          ((x$EP == "") | (x$EP == x$BP))
      )
    ]
  # If start page is present and end page is simply '+' then the end page has to be obtained from start page + number of pages
  x$PGN[
    (
      (x$BP != "") &
        (x$EP == "+")
    )
  ] <-
    paste0(
      x$BP[
        (
          (x$BP != "") &
            (x$EP == "+")
        )
      ],
      "-",
      as.numeric(x$PG[
        (
          (x$BP != "") &
            (x$EP == "+")
        )
      ]) + 
        as.numeric(x$BP[
          (
            (x$BP != "") &
              (x$EP == "+")
          )
        ]) - 1
    )
  # If start page is present and above conditions are not met, it is start page to end page
  x$PGN[
    (
      (x$BP != "") &
        (x$PGN == "")
    )
  ] <-
    paste0(
      x$BP[
        (
          (x$BP != "") &
            (x$PGN == "")
        )
      ],
      "-",
      x$EP[
        (
          (x$BP != "") &
            (x$PGN == "")
        )
      ]
    )
  # If none of the above conditions are met, the page is obtained from "AR"
  x$PGN[
    (x$PGN == "")
  ] <-
    x$AR[
      (x$PGN == "")
    ] 
  # If none of the above conditions are met, the page is obtained from "DL"
  x$PGN[
    (x$PGN == "")
  ] <-
    x$DL[
      (x$PGN == "")
    ] 
  x  
}
import.cochrane <- function(x) {
  x$DOI <- trimws(x$DOI)
  x$DOI[x$DOI != ""] <- paste0(
    "https://doi.org/",
    x$DOI[x$DOI != ""]  
  )
  x
}
import.ictrp <- function(p, x) {
  p <- na.omit(p)
  colnames(p) <- "initial"
  # Identify each record
  p$trial <- NA
  p$tag <- NA
  p$content <- p$initial
  p[!is.na(str_locate(p$initial, "<Trial>")[,1]),2] <- 
    1:length(p[!is.na(str_locate(p$initial, "<Trial>")[,1]),1])
  p$content <- 
    trimws(
      str_remove_all(
        str_remove_all(
          str_remove_all(
            p$content,fixed("<Trial>")
          ), fixed("<Trial/>")
        ), fixed("</Trial>")
      )
    )
  p[,1] <- trimws(p[,1])
  p <- p[p[,1] !="",]
  # Now remove all the data before the first trial and the last row should be removed too
  p <- data.frame(p[(match(1,p$trial):(nrow(p)-1)),])
  p$trial <- na.locf(na.locf(p$trial),fromLast=TRUE)
  # If there is no data, the start and end tags for absent data is denoted differently from the usual start and end tags
  q <- list(
    paste0("<",colnames(xmlToDataFrame(x)), ">"), # Start tags
    paste0("<",colnames(xmlToDataFrame(x)), "/>"), # Start and end tags combined if there is no data
    paste0("</",colnames(xmlToDataFrame(x)), ">"), # End tag if there is data
    colnames(xmlToDataFrame(x)) # Simply the column names
  )            
  for (i in 1:length(q[[1]])) {
    p$tag[str_detect(p$initial,fixed(q[[1]][i]))] <-q[[1]][i] 
    p$tag[str_detect(p$initial,fixed(q[[2]][i]))] <-q[[1]][i] # Even if the start and end tags are combined, for correct transformation, we need the standard start tag
    # Remove the tags from the content
    p$content <- 
      trimws(
        str_remove_all(
          str_remove_all(
            str_remove_all(
              p$content,fixed(q[[1]][i])
            ), fixed(q[[2]][i])
          ), fixed(q[[3]][i])
        )
      )
  }
  p$tag <- na.locf(na.locf(p$tag),fromLast=TRUE)
  # Convert data to wide format 
  suppressWarnings(
    suppressMessages(
      r <- pivot_wider(p[,c("trial","tag","content")], names_from = tag, values_from = content)
    )
  )
  # The output is in the form of a list because of multiple rows for some fields
  # Convert this into one row per reference
  s <- data.frame(matrix(nrow = length(r[[1]]), ncol = 0))
  for (i in 1:length(r)) {
    t <- vector()
    for (j in 1:length(r[[i]])) {
      if (is.null(r[[i]][[j]])) {
        t <- c(t, NA)
      } else {
        if (!is.na(r[[i]][[j]][1])) {
          if (length(r[[i]][[j]][1] > 1)){
            t <- c(t, substr(trimws(paste0(r[[i]][[j]], collapse = "\n")),1,20000))
          } else {
            t <- c(t, trimws(r[[i]][[j]][1]))
          }
        } else {
          t <- c(t, NA)
        }
      }
    }
    s <- data.frame(cbind(s, t))
    colnames(s)[ncol(s)] <- c("Trial", q[[4]])[i]
  }
  # Now change the insecure links to secure links
  s$web_address <- str_replace(s$web_address,
                               "http:",
                               "https:"
  )
  s
}
Author.list.PubMed <- function(x) {
  paste0(trimws(str_split(x,"\n")[[1]]), collapse = ", ")
}
Abstract.PubMed <- function(x) {
  paste0(trimws(str_split(x,"\n")[[1]]), collapse = " ")
}
Author.list.Ovid <- function(x) {
  x <- str_replace_all(x, "\n\n","\n")
  x <- str_replace_all(x, "\\.","")
  paste0(trimws(str_split(x,"\n")[[1]]), collapse = ", ")
}
Author.list.wos <- function(x) {
  x <- str_replace_all(x, "\\,","")
  str_replace_all(x, "\\;",",")
}
Author.list.ICTRP <- function(x) {
  # Remove space character described as &#x20; in XML parsing
  # Keep only the first author when there are multiple authors to manage the combination of names
  y1 <- x[,1]
  y1[is.na(y1)] <- "" 
  y1 <- str_remove_all(y1, "&#x20;")
  y1 <- str_replace_all(y1, "\n", " ")
  y1[((nchar(y1) == 1) & (y1 == ";"))] <- ""
  y1[str_detect(y1,";")] <- 
    substr(y1[str_detect(y1,";")],1,((str_locate(y1[str_detect(y1,";")],";")[,1])-1))
  y2 <- x[,2]
  y2[is.na(y2)] <- "" 
  y2 <- str_remove_all(y2, "&#x20;")
  y2 <- str_replace_all(y2, "\n", " ")
  y2[((nchar(y2) == 1) & (y2 == ";"))] <- ""
  y2[str_detect(y2,";")] <- 
    substr(y2[str_detect(y2,";")],1,((str_locate(y2[str_detect(y2,";")],";")[,1])-1))
  trimws(paste0(y1, " ", y2))  
}
Author.Contact.ICTRP <- function(x) {
  # Remove space character described as &#x20; in XML parsing
  # Keep only the first author when there are multiple authors to manage the combination of names
  y1 <- x[,1]
  y1[is.na(y1)] <- "" 
  y1 <- str_remove_all(y1, "&#x20;")
  y1 <- str_replace_all(y1, "\n", " ")
  y1[((nchar(y1) == 1) & (y1 == ";"))] <- ""
  y1[str_detect(y1,";")] <- 
    substr(y1[str_detect(y1,";")],1,((str_locate(y1[str_detect(y1,";")],";")[,1])-1))
  y2 <- x[,2]
  y2[is.na(y2)] <- "" 
  y2 <- str_remove_all(y2, "&#x20;")
  y2 <- str_replace_all(y2, "\n", " ")
  y2[((nchar(y2) == 1) & (y2 == ";"))] <- ""
  y2[str_detect(y2,";")] <- 
    substr(y2[str_detect(y2,";")],1,((str_locate(y2[str_detect(y2,";")],";")[,1])-1))
  # If email not present get main address
  y1[y1==""] <- y2[y1==""]
  trimws(y1)  
}
keywords.pubmed <- function(x) {
  y = trimws(x)
  if ((y=="") | (is.na(y))) {
    ""
  } else {
    paste0(trimws(str_split(y,"\n")[[1]]), collapse = "; ")    
  }
}
keywords.embase <- function(x) {
  y = trimws(x)
  if ((y=="") | (is.na(y))) {
    ""
  } else {
    y = str_remove_all(
      y,
      "\\[m\\]"
    )
    z = paste0(
      unique(trimws(str_split(y,"\n\n")[[1]])), 
      collapse = "; ")
    str_replace_all(z, ";;",";")
  }
}
keywords.wos <- function(x) {
  x[,1] <- str_to_title(trimws(x[,1]))
  x[,2] <- trimws(x[,2])
  x[,3] <- ""
  x[
    ((x[,1] != "") & (!is.na(x[,1]))) &
      ((x[,2] == "") | (is.na(x[,2])))
    , 3] <- 
    x[
      ((x[,1] != "") & (!is.na(x[,1]))) &
        ((x[,2] == "") | (is.na(x[,2])))
      , 1]
  x[
    ((x[,1] != "") & (!is.na(x[,1]))) &
      ((x[,2] != "") & (!is.na(x[,2])))
    , 3] <- 
    paste0(
      x[
        ((x[,1] != "") & (!is.na(x[,1]))) &
          ((x[,2] != "") & (!is.na(x[,2])))
        , 1], 
      "; ",
      x[
        ((x[,1] != "") & (!is.na(x[,1]))) &
          ((x[,2] != "") & (!is.na(x[,2])))
        , 2]
      
    )
  trimws(x[,3])
}
CTgov.Summary <- function(x) {
  y <- list()
  for (i in 1:7) {
    y[[i]] <- str_replace_all(trimws(x[,i]), "\\|","<br>")
    y[[i]][is.na(y[[i]])] <- ""
    if (i == 7) {
      y[[6]] <- paste0(y[[6]],"<br>",y[[7]])
    }
    y[[i]][y[[i]] == ""] <- "No information"
  }
  z <- paste0("<strong>","Brief summary", "</strong>","<br>", trimws(y[[1]]), "<br>", 
              "<strong>","Study design", "</strong>", "<br>", trimws(y[[2]]), "<br>", 
              "<strong>","Condition", "</strong>", "<br>", trimws(y[[3]]), "<br>", 
              "<strong>","Intervention", "</strong>", "<br>", trimws(y[[4]]), "<br>", 
              "<strong>","Primary outcome", "</strong>", "<br>", trimws(y[[5]]), "<br>", 
              "<strong>","Secondary outcome", "</strong>", "<br>", trimws(y[[6]])
  )
  trimws(str_replace_all(z,"<br><br>","<br>"))
}
ICTRP.Summary <- function(x) {
  # Remove some characters which are errors in XML parsing with some html codes retained
  y <- list()
  for (i in 1:7) {
    y[[i]] <- x[,i]
    y[[i]][is.na(y[[i]])] <- "" 
    y[[i]] <- str_remove_all(y[[i]], "&#x20;")
    y[[i]] <- str_replace_all(y[[i]], "&lt;br&gt;", "<br>")
    y[[i]] <- str_replace_all(y[[i]], "&#x0D;", "<br>")
    y[[i]] <- str_replace_all(y[[i]], "  ", " ")
    y[[i]] <- str_replace_all(y[[i]], "  ", " ")
    y[[i]] <- str_replace_all(y[[i]], "  ", " ")
    y[[i]] <- str_replace_all(y[[i]], "  ", " ")
    y[[i]] <- str_replace_all(y[[i]], "  ", " ")
    y[[i]] <- str_replace_all(y[[i]], "&gt;", ">")
    y[[i]] <- str_replace_all(y[[i]], "&lt;", "<")
    y[[i]][((nchar(y[[i]]) == 1) & (y[[i]] == ";"))] <- ""
    y[[i]][y[[i]] == ""] <- "No information"
  }
  y[[1]] <- str_replace_all(y[[1]], "\n", "<br>")
  
  z <- paste0("<strong>","Study design", "</strong>","<br>", trimws(y[[1]]), "<br>", 
              "<strong>","Inclusion criteria", "</strong>", "<br>", trimws(y[[2]]), "<br>", 
              "<strong>","Exclusion criteria", "</strong>", "<br>", trimws(y[[3]]), "<br>", 
              "<strong>","Condition", "</strong>", "<br>", trimws(y[[4]]), "<br>", 
              "<strong>","Intervention", "</strong>", "<br>", trimws(y[[5]]), "<br>", 
              "<strong>","Primary outcome", "</strong>", "<br>", trimws(y[[6]]), "<br>", 
              "<strong>","Secondary outcome", "</strong>", "<br>", trimws(y[[7]])
  )
  z <- str_replace_all(z, "<br><br>", "<br>")
  z <- str_replace_all(z, "<br><br>", "<br>")
  z <- str_replace_all(z, "<br><br>", "<br>")
  z <- str_replace_all(z, "<br><br>", "<br>")
  z <- str_replace_all(z, "<br><br>", "<br>")
  str_replace_all(z, "<br><br>", "<br>")
}
# Replace hyphen not working well in Cochrane
Replace.hyphen <- function(x) {
  y <- utf8ToInt(x)
  y[match(8208,y)] <- 45
  intToUtf8(y)
}
# Create reference
Create.reference <- function(x) {
  authors <- trimws(x[,1])
  authors[is.na(authors)] <- ""
  authors[authors !=""] <- paste0(authors[authors !=""], ". ")
  article.title <- trimws(x[,2])
  article.title[is.na(article.title)] <- ""
  article.title[article.title !=""] <- paste0(article.title[article.title !=""], ". ")
  journal.title <- trimws(x[,3])
  journal.title[is.na(journal.title)] <- ""
  journal.title[journal.title !=""] <- paste0("<em>", journal.title[journal.title !=""], "</em>", ". ")
  publication.year <- trimws(x[,4])
  publication.year[is.na(publication.year)] <- ""
  publication.year[publication.year !=""] <- paste0(publication.year[publication.year !=""], ";")
  volume <- trimws(x[,5])
  volume[is.na(volume)] <- ""
  issue <- trimws(x[,6])
  issue[is.na(issue)] <- ""
  issue[issue !=""] <- paste0("(", issue[issue !=""], ")")
  pages <- trimws(x[,7])
  pages[is.na(pages)] <- ""
  pages[pages == "no pagination"] <- ""
  pages[pages !=""] <- paste0(pages[pages !=""], ". ")
  article.url <- trimws(x[,8])
  article.url[is.na(article.url)] <- ""
  article.url[article.url != ""] <- paste0("url: ", 
                                           "<a href=", 
                                           '"', article.url[article.url != ""],'" ', 
                                           'target="_blank">',
                                           article.url[article.url != ""],
                                           "</a>"
  )
  reference <- paste0(
    authors, article.title, journal.title,
    publication.year, volume, issue, ":", 
    pages, article.url,
    "."
  )
  reference = str_replace_all(reference, "\\.\\.","\\.")
  reference = str_replace_all(reference, "\\.\\ \\.","\\.")
  reference = str_replace_all(reference, "\\(\\)","")
  reference = str_replace_all(reference, "\\(\\ \\)","")
  reference = str_replace_all(reference, "\\;\\.",".")
  reference = str_replace_all(reference, "\\;\\:",":")
  reference = str_replace_all(reference, "\\:\\.",".")
  reference = str_replace_all(reference, "\n"," ")
  trimws(reference)
}
# Get details of data import
import.references <- function(index.file.full.name, reference.files.full.names) {
  index.file <- read.csv(index.file.full.name,header = TRUE)
  if (str_detect(index.file.full.name, fixed("\\"))) {
    index.file.full.name <- str_replace_all(index.file.full.name, fixed("\\"), "/")
  }
  index.file.path <- substr(index.file.full.name,1,str_locate_all(index.file.full.name, fixed("/"))[[1]][nrow(str_locate_all(index.file.full.name, fixed("/"))[[1]]),1])
  if (str_detect(reference.files.full.names[1], fixed("\\"))) {
    reference.files.full.names <- str_replace_all(reference.files.full.names, fixed("\\"), "/")
  }
  reference.files.path <- substr(reference.files.full.names,1,str_locate_all(reference.files.full.names, fixed("/"))[[1]][nrow(str_locate_all(reference.files.full.names, fixed("/"))[[1]]),1])
  reference.files.path <- reference.files.path[1]
  if(!file.exists(paste0(index.file.path,"References_to_Screen"))){
    dir.create(paste0(index.file.path,"References_to_Screen"))
  } else {  
    unlink(paste0(index.file.path,"References_to_Screen"), recursive = TRUE)
    dir.create(paste0(index.file.path,"References_to_Screen"))
  }
  if(!file.exists(paste0(index.file.path,"FullDetails"))){
    dir.create(paste0(index.file.path,"FullDetails"))
  } else {  
    unlink(paste0(index.file.path,"FullDetails"), recursive = TRUE)
    dir.create(paste0(index.file.path,"FullDetails"))
  }
  import.summary <- data.frame(matrix(nrow =7, ncol = 5))
  colnames(import.summary) <- c("database", "file.names","number.of.files", "file.exists", "file.exists.number")
  import.summary$database <- c(
    "PubMed", "MEDLINE", "EMBASE", "WOS", "Cochrane", "CTgov", "ICTRP" 
  )
  import.list <- list()
  for (i in 1:nrow(import.summary)) {
    import.summary$file.names[i] <- paste0(reference.files.path,
                                           index.file$file.name[index.file$database == import.summary$database[i]], 
                                           collapse = "|")
    import.summary$number.of.files[i] <- length(index.file$file.name[index.file$database == import.summary$database[i]])
    import.list[[i]] <- list(
      import.summary$database[i],
      paste0(reference.files.path, index.file$file.name[index.file$database == import.summary$database[i]]),
      file.exists(paste0(reference.files.path, index.file$file.name[index.file$database == import.summary$database[i]]))
    )
    import.summary$file.exists[i] <- paste0(
      reference.files.path, index.file$file.name[index.file$database == import.summary$database[i]],
      ": ",
      file.exists(paste0(reference.files.path, index.file$file.name[index.file$database == import.summary$database[i]])),
      collapse = "|"
    )
  }
  import.summary$file.exists.number <- str_count(import.summary$file.exists,"TRUE")
  minimum.column.names <- list(
    c("PMID", "AID", "AU", "AD", "TI", "AB", "JT", "DP", "VI", "IP", "PG", "MH"),
    c("UI", "DO", "AU", "IN", "TI", "AB", "JN", "YR", "VO", "IP", "PG", "MH", "KW"),
    c("UI", "CN", "DO", "AU", "AE", "TI", "AB", "JN", "YR", "VO", "IP", "PG", "MH", "DJ", "DU", "OD", "KW"),
    c("UT", "PM", "DL", "AU", "EM", "TI", "AB", "SO", "PY", "VL", "IS", "PGN", "ID", "DE"),
    c("PubMed.ID", "Embase.ID", "CTgov.ID", "ICTRP.ID", "DOI", "Author.s.", "ICTRP.ID", "Title", "Abstract", "Source", "Year", "Volume", "Issue", "Pages", "Keywords"),
    c("NCT.Number", "Study.URL", "Sponsor", "Study.Title", "Brief.Summary", "Study.Design", "Conditions", "Interventions", "Primary.Outcome.Measures", "Secondary.Outcome.Measures", "Other.Outcome.Measures", "First.Posted"),
    c("Internal_Number", "TrialID", "web_address", "Contact_Firstname", "Contact_Lastname", "Contact_Email", "Contact_Address", "Scientific_title", "Study_design", "Inclusion_Criteria", "Exclusion_Criteria", "Condition", "Intervention", "Primary_outcome", "Secondary_outcome", "web_address", "Date_registration3")
  )
  names(minimum.column.names) <- import.summary$database
  
  # Import data
  withProgress(message = 'Importing files...', value = 0, {
    # PubMed
    PubMed <- data.frame()
    incProgress(0/7, detail = "Importing PubMed")
    k = 1
    if (import.summary$number.of.files[k] > 0) {
      import.list[[k]][[4]] <- list()
      import.list[[k]][[5]] <- list()
      import.list[[k]][[6]] <- list()
      import.list[[k]][[7]] <- list()
      for (i in 1:import.summary$number.of.files[k]) {
        if(import.list[[k]][[3]][i] == TRUE) {
          import.list[[k]][[4]][[i]] <- read.delim(import.list[[k]][[2]][i], header = FALSE,sep="\n")
          import.list[[k]][[5]][[i]] <- import.pmid(import.list[[k]][[4]][[i]])
          # Now check whether minimum column names are present
          if (!FALSE %in% !is.na (match(minimum.column.names[[k]], 
                                        colnames(import.list[[k]][[5]][[i]])))) {
            import.list[[k]][[6]][[i]] <- "Successfully imported"
            import.list[[k]][[7]][[i]] <- nrow(import.list[[k]][[5]][[i]])
            PubMed <- rbind.missing(PubMed, import.list[[k]][[5]][[i]])
            # remove any duplicates
            PubMed <- PubMed[match(unique(PubMed$PMID), PubMed$PMID),]
          } else {
            import.list[[k]][[6]][[i]] <- "Import not done because of absence of minimum column names"
            import.list[[k]][[7]][[i]] <- 0
          }
        } else {
          import.list[[k]][[6]][[i]] <- "Import not done because the file is absent"
          import.list[[k]][[7]][[i]] <- 0
        }
      }
    }
    incProgress(1/7, detail = "Importing MEDLINE")
    # MEDLINE
    # Import directly
    MEDLINE <- data.frame()
    k = 2
    if (import.summary$number.of.files[k] > 0) {
      import.list[[k]][[4]] <- list()
      import.list[[k]][[5]] <- list()
      import.list[[k]][[6]] <- list()
      import.list[[k]][[7]] <- list()
      for (i in 1:import.summary$number.of.files[k]) {
        if(import.list[[k]][[3]][i] == TRUE) {
          import.list[[k]][[4]][[i]] <- read.csv(import.list[[k]][[2]][i],skip = 1, header = TRUE)
          import.list[[k]][[5]][[i]] <- import.list[[k]][[4]][[i]]
          if (!FALSE %in% !is.na (match(minimum.column.names[[k]], 
                                        colnames(import.list[[k]][[5]][[i]])))) {
            import.list[[k]][[6]][[i]] <- "Successfully imported"
            import.list[[k]][[7]][[i]] <- nrow(import.list[[k]][[5]][[i]])
            MEDLINE <- rbind.missing(MEDLINE, import.list[[k]][[5]][[i]])
            # remove any duplicates
            MEDLINE <- MEDLINE[match(unique(MEDLINE$UI), MEDLINE$UI),]
          } else {
            import.list[[k]][[6]][[i]] <- "Import not done because of absence of minimum column names"
            import.list[[k]][[7]][[i]] <- 0
          }
        } else {
          import.list[[k]][[6]][[i]] <- "Import not done because the file is absent"
          import.list[[k]][[7]][[i]] <- 0
        }
      }
    }
    incProgress(1/7, detail = "Importing EMBASE")
    # EMBASE
    # Import directly
    EMBASE <- data.frame()
    k = 3
    if (import.summary$number.of.files[k] > 0) {
      import.list[[k]][[4]] <- list()
      import.list[[k]][[5]] <- list()
      import.list[[k]][[6]] <- list()
      import.list[[k]][[7]] <- list()
      for (i in 1:import.summary$number.of.files[k]) {
        if(import.list[[k]][[3]][i] == TRUE) {
          import.list[[k]][[4]][[i]] <- read.csv(import.list[[k]][[2]][i],skip = 1, header = TRUE)
          import.list[[k]][[5]][[i]] <- import.embase(import.list[[k]][[4]][[i]])
          if (!FALSE %in% !is.na (match(minimum.column.names[[k]], 
                                        colnames(import.list[[k]][[5]][[i]])))) {
            import.list[[k]][[6]][[i]] <- "Successfully imported"
            import.list[[k]][[7]][[i]] <- nrow(import.list[[k]][[5]][[i]])
            EMBASE <- rbind.missing(EMBASE, import.list[[k]][[5]][[i]])
            # remove any duplicates
            EMBASE <- EMBASE[match(unique(EMBASE$UI), EMBASE$UI),]
          } else {
            import.list[[k]][[6]][[i]] <- "Import not done because of absence of minimum column names"
            import.list[[k]][[7]][[i]] <- 0
          }
        } else {
          import.list[[k]][[6]][[i]] <- "Import not done because the file is absent"
          import.list[[k]][[7]][[i]] <- 0
        }
      }
    }
    incProgress(1/7, detail = "Importing Web of Science")
    # Web of science (conference proceedings)
    WOS <- data.frame()
    k = 4
    if (import.summary$number.of.files[k] > 0) {
      import.list[[k]][[4]] <- list()
      import.list[[k]][[5]] <- list()
      import.list[[k]][[6]] <- list()
      import.list[[k]][[7]] <- list()
      for (i in 1:import.summary$number.of.files[k]) {
        if(import.list[[k]][[3]][i] == TRUE) {
          import.list[[k]][[4]][[i]] <- read.delim(import.list[[k]][[2]][i], header = TRUE)
          import.list[[k]][[5]][[i]] <- import.wos(import.list[[k]][[4]][[i]])
          if (!FALSE %in% !is.na (match(minimum.column.names[[k]], 
                                        colnames(import.list[[k]][[5]][[i]])))) {
            import.list[[k]][[6]][[i]] <- "Successfully imported"
            import.list[[k]][[7]][[i]] <- nrow(import.list[[k]][[5]][[i]])
            WOS <- rbind.missing(WOS, import.list[[k]][[5]][[i]])
            # remove any duplicates
            WOS <- WOS[match(unique(WOS$UT), WOS$UT),]
          } else {
            import.list[[k]][[6]][[i]] <- "Import not done because of absence of minimum column names"
            import.list[[k]][[7]][[i]] <- 0
          }
        } else {
          import.list[[k]][[6]][[i]] <- "Import not done because the file is absent"
          import.list[[k]][[7]][[i]] <- 0
        }
      }
    }
    incProgress(1/7, detail = "Importing Cochrane")
    # Cochrane
    Cochrane <- data.frame()
    k = 5
    if (import.summary$number.of.files[k] > 0) {
      import.list[[k]][[4]] <- list()
      import.list[[k]][[5]] <- list()
      import.list[[k]][[6]] <- list()
      import.list[[k]][[7]] <- list()
      for (i in 1:import.summary$number.of.files[k]) {
        if(import.list[[k]][[3]][i] == TRUE) {
          import.list[[k]][[4]][[i]] <- read.csv(import.list[[k]][[2]][i], header = TRUE)
          import.list[[k]][[5]][[i]] <- import.cochrane(import.list[[k]][[4]][[i]])
          if (!FALSE %in% !is.na (match(minimum.column.names[[k]], 
                                        colnames(import.list[[k]][[5]][[i]])))) {
            import.list[[k]][[6]][[i]] <- "Successfully imported"
            import.list[[k]][[7]][[i]] <- nrow(import.list[[k]][[5]][[i]])
            Cochrane <- rbind.missing(Cochrane, import.list[[k]][[5]][[i]])
            # remove any duplicates
            Cochrane <- Cochrane[match(unique(Cochrane$CENTRAL.ID), Cochrane$CENTRAL.ID),]
          } else {
            import.list[[k]][[6]][[i]] <- "Import not done because of absence of minimum column names"
            import.list[[k]][[7]][[i]] <- 0
          }
        } else {
          import.list[[k]][[6]][[i]] <- "Import not done because the file is absent"
          import.list[[k]][[7]][[i]] <- 0
        }
      }
    }
    incProgress(1/7, detail = "Importing ClinicalTrials.gov")
    # ClinicalTrials.gov
    CTgov <- data.frame()
    k = 6
    if (import.summary$number.of.files[k] > 0) {
      import.list[[k]][[4]] <- list()
      import.list[[k]][[5]] <- list()
      import.list[[k]][[6]] <- list()
      import.list[[k]][[7]] <- list()
      for (i in 1:import.summary$number.of.files[k]) {
        if(import.list[[k]][[3]][i] == TRUE) {
          import.list[[k]][[4]][[i]] <- read.csv(import.list[[k]][[2]][i], header = TRUE)
          import.list[[k]][[5]][[i]] <- import.list[[k]][[4]][[i]]
          if (!FALSE %in% !is.na (match(minimum.column.names[[k]], 
                                        colnames(import.list[[k]][[5]][[i]])))) {
            import.list[[k]][[6]][[i]] <- "Successfully imported"
            import.list[[k]][[7]][[i]] <- nrow(import.list[[k]][[5]][[i]])
            CTgov <- rbind.missing(CTgov, import.list[[k]][[5]][[i]])
            # remove any duplicates
            CTgov <- CTgov[match(unique(CTgov$NCT.Number), CTgov$NCT.Number),]
          } else {
            import.list[[k]][[6]][[i]] <- "Import not done because of absence of minimum column names"
            import.list[[k]][[7]][[i]] <- 0
          }
        } else {
          import.list[[k]][[6]][[i]] <- "Import not done because the file is absent"
          import.list[[k]][[7]][[i]] <- 0
        }
      }
    }
    incProgress(1/7, detail = "Importing WHO ICTRP")
    # WHO ICTRP
    ICTRP <- data.frame()
    k = 7
    if (import.summary$number.of.files[k] > 0) {
      import.list[[k]][[4]] <- list()
      import.list[[k]][[5]] <- list()
      import.list[[k]][[6]] <- list()
      import.list[[k]][[7]] <- list()
      for (i in 1:import.summary$number.of.files[k]) {
        if(import.list[[k]][[3]][i] == TRUE) {
          import.list[[k]][[4]][[i]] <- read.csv(import.list[[k]][[2]][i], quote = "", blank.lines.skip = TRUE)
          import.list[[k]][[5]][[i]] <- import.ictrp(import.list[[k]][[4]][[i]], import.list[[k]][[2]][i])
          if (!FALSE %in% !is.na (match(minimum.column.names[[k]], 
                                        colnames(import.list[[k]][[5]][[i]])))) {
            import.list[[k]][[6]][[i]] <- "Successfully imported"
            import.list[[k]][[7]][[i]] <- nrow(import.list[[k]][[5]][[i]])
            ICTRP <- rbind.missing(ICTRP, import.list[[k]][[5]][[i]])
            # remove any duplicates
            ICTRP <- ICTRP[match(unique(ICTRP$Internal_Number), ICTRP$Internal_Number),]
          } else {
            import.list[[k]][[6]][[i]] <- "Import not done because of absence of minimum column names"
            import.list[[k]][[7]][[i]] <- 0
          }
        } else {
          import.list[[k]][[6]][[i]] <- "Import not done because the file is absent"
          import.list[[k]][[7]][[i]] <- 0
        }
      }
    }
    # Now make a summary of outcome of each file in index file
    import.summary.2 <- data.frame(matrix(nrow=0,ncol=3))
    colnames(import.summary.2) <- c("file.name", "import.status", "references.imported")
    for (k in 1:7) {
      if (import.summary$number.of.files[k] > 0) {
        for (i in 1:length(import.list[[k]][[2]])){
          import.summary.2 <- rbind(import.summary.2,
                                    c(import.list[[k]][[2]][[i]], 
                                      import.list[[k]][[6]][[i]], 
                                      import.list[[k]][[7]][[i]])
          )
        }
      }
    }
    colnames(import.summary.2) <- c("file.name", "import.status", "references.imported")
    import.summary.2$file.name <- str_remove_all(import.summary.2$file.name,
                                                 reference.files.path)
    import.summary <- cbind.missing(import.summary.2, import.summary)
    import.summary$file.names <- str_remove_all(import.summary$file.names,
                                                reference.files.path)
    import.summary$file.exists <- str_remove_all(import.summary$file.exists,
                                                 reference.files.path)
    
    # Write files to folder
    write.csv(import.summary,paste0(index.file.path, "FullDetails/1_Import_Summary.csv"), row.names = FALSE, na = "")
    for (k in 1:7) {
      if (import.summary$file.exists.number[k] > 0)
        eval(parse(text =
                     paste0(
                       "write.csv(", import.summary$database[k], ",",
                       '"' ,index.file.path, "FullDetails/","3_",k,"_", import.summary$database[k],".csv",'"', ",",
                       "row.names = FALSE,",
                       'na = ""',
                       ")"
                     )
        ))
    }
  })
  # Combine the databases and remove duplicates
  withProgress(message = 'Combining files and removing duplicates...', value = 0, {
    references.file.column.names <- c("database", 
                                      "unique.identifier", 
                                      "pmid", "embase.id", "ctgov.id","ictrp.id", "other.trial.identifier",
                                      "url",
                                      "authors", "authors.contact",
                                      "article.title", "article.abstract",
                                      "journal.name",
                                      "article.publication.year",
                                      "article.volume", "article.issue", "article.pages",
                                      "keywords"
    )
    references.file <- data.frame(matrix(nrow = 0, ncol = 18))
    colnames(references.file) <- references.file.column.names
    incProgress(0/7, detail = "PubMed")
    if (nrow(PubMed)>0) {
      temporary.references.file <-  data.frame(cbind(rep("PubMed",nrow(PubMed)), 
                                                     PubMed$PMID,
                                                     PubMed$PMID,
                                                     rep(NA,nrow(PubMed)),
                                                     rep(NA,nrow(PubMed)),
                                                     rep(NA,nrow(PubMed)),
                                                     rep(NA,nrow(PubMed)),
                                                     if(!is.na(match("AID",colnames(PubMed)))){
                                                       PubMed$AID
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("AU",colnames(PubMed)))){
                                                       sapply(PubMed$AU, Author.list.PubMed)
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("AD",colnames(PubMed)))){
                                                       sapply(PubMed$AD, Author.list.PubMed)
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("TI",colnames(PubMed)))){
                                                       PubMed$TI
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("AB",colnames(PubMed)))){
                                                       sapply(PubMed$AB, Abstract.PubMed)
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("JT",colnames(PubMed)))){
                                                       PubMed$JT
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("DP",colnames(PubMed)))){
                                                       substring(PubMed$DP,1,4)
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("VI",colnames(PubMed)))){
                                                       PubMed$VI
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("IP",colnames(PubMed)))){
                                                       PubMed$IP
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("PG",colnames(PubMed)))){
                                                       PubMed$PG
                                                     } else {
                                                       rep(NA,nrow(PubMed))
                                                     },
                                                     if(!is.na(match("MH",colnames(PubMed)))){
                                                       paste0("<strong>MeSH: </strong>",sapply(PubMed$MH, keywords.pubmed))
                                                     } else {
                                                       rep("",nrow(PubMed))
                                                     }
      )
      )
      colnames(temporary.references.file) <- references.file.column.names
      temporary.references.file$pmid[temporary.references.file$pmid == ""] <- NA
      temporary.references.file <- temporary.references.file[
        ((is.na(temporary.references.file$pmid)) | (is.na(match(temporary.references.file$pmid,references.file$pmid)))),
      ]
      if (nrow(temporary.references.file) > 0) {
        references.file <- rbind(references.file, temporary.references.file)
      }
    }
    incProgress(1/7, detail = "MEDLINE")
    if (nrow(MEDLINE)>0) {
      temporary.references.file <- data.frame(cbind(rep("Ovid MEDLINE",nrow(MEDLINE)),
                                                    MEDLINE$UI, 
                                                    MEDLINE$UI, 
                                                    rep(NA,nrow(MEDLINE)),
                                                    rep(NA,nrow(MEDLINE)),
                                                    rep(NA,nrow(MEDLINE)),
                                                    rep(NA,nrow(MEDLINE)),
                                                    MEDLINE$DO,
                                                    sapply(MEDLINE$AU, Author.list.Ovid),
                                                    str_replace_all(MEDLINE$IN, "\n\n","\n"),
                                                    MEDLINE$TI,
                                                    MEDLINE$AB,
                                                    MEDLINE$JN,
                                                    MEDLINE$YR,
                                                    MEDLINE$VO,
                                                    MEDLINE$IP,
                                                    MEDLINE$PG,
                                                    paste0("<strong>MeSH: </strong>",str_replace_all(MEDLINE$MH, "\n\n","; "),"<br>" ,"<strong>Keywords: </strong>",MEDLINE$KW)
      )
      )
      colnames(temporary.references.file) <- references.file.column.names
      temporary.references.file$pmid[temporary.references.file$pmid == ""] <- NA
      temporary.references.file <- temporary.references.file[
        ((is.na(temporary.references.file$pmid)) | (is.na(match(temporary.references.file$pmid,references.file$pmid)))),
      ]
      if (nrow(temporary.references.file) > 0) {
        references.file <- rbind(references.file, temporary.references.file)
      }
    }
    incProgress(1/7, detail = "EMBASE")
    if (nrow(EMBASE)>0) {
      temporary.references.file <- data.frame(cbind(rep("Ovid EMBASE",nrow(EMBASE)),
                                                    EMBASE$UI, 
                                                    trimws(substring(EMBASE$PM,1,(str_locate(EMBASE$PM,"\\[")[,1]-1))), 
                                                    EMBASE$UI,
                                                    rep(NA,nrow(EMBASE)),
                                                    rep(NA,nrow(EMBASE)),
                                                    EMBASE$CN,
                                                    EMBASE$DO,
                                                    sapply(EMBASE$AU, Author.list.Ovid),
                                                    str_replace_all(EMBASE$AE, "\n\n","\n"),
                                                    EMBASE$TI,
                                                    EMBASE$AB,
                                                    EMBASE$JN,
                                                    EMBASE$YR,
                                                    EMBASE$VO,
                                                    EMBASE$IP,
                                                    EMBASE$PG,
                                                    paste0("<strong>Descriptors: </strong>",
                                                           sapply(
                                                             paste0(
                                                               EMBASE$MH, "\n\n",
                                                               EMBASE$DJ, "\n\n",
                                                               EMBASE$DU, "\n\n",
                                                               EMBASE$OD
                                                             ),
                                                             keywords.embase
                                                           ),
                                                           "<br>" ,"<strong>Keywords: </strong>",
                                                           str_replace_all(EMBASE$KW, "\n\n","; ")
                                                    )
      )
      )
      colnames(temporary.references.file) <- references.file.column.names
      temporary.references.file$pmid[temporary.references.file$pmid == ""] <- NA
      temporary.references.file$embase.id[temporary.references.file$embase.id == ""] <- NA
      temporary.references.file <- temporary.references.file[
        ((is.na(temporary.references.file$pmid)) | (is.na(match(temporary.references.file$pmid,references.file$pmid)))),
      ]
      if (nrow(temporary.references.file) > 0) {
        references.file <- rbind(references.file, temporary.references.file)
      }
    }
    incProgress(1/7, detail = "World of Science")
    if (nrow(WOS)>0) {
      temporary.references.file <- data.frame(cbind(rep("Web of Science",nrow(WOS)),
                                                    WOS$UT, 
                                                    WOS$PM, 
                                                    rep(NA,nrow(WOS)),
                                                    rep(NA,nrow(WOS)),
                                                    rep(NA,nrow(WOS)),
                                                    rep(NA,nrow(WOS)),
                                                    WOS$DL,
                                                    sapply(WOS$AU, Author.list.wos),
                                                    WOS$EM,
                                                    WOS$TI,
                                                    WOS$AB,
                                                    str_to_title(WOS$SO),
                                                    WOS$PY,
                                                    WOS$VL,
                                                    WOS$IS,
                                                    WOS$PGN,
                                                    keywords.wos(
                                                      data.frame(cbind(
                                                        WOS$ID,
                                                        WOS$DE
                                                      ))
                                                    )
      )
      )
      colnames(temporary.references.file) <- references.file.column.names
      temporary.references.file$pmid[temporary.references.file$pmid == ""] <- NA
      temporary.references.file <- temporary.references.file[
        ((is.na(temporary.references.file$pmid)) | (is.na(match(temporary.references.file$pmid,references.file$pmid)))),
      ]
      if (nrow(temporary.references.file) > 0) {
        references.file <- rbind(references.file, temporary.references.file)
      }
    }
    # The trial registry entries are better than Cochrane; so first get these entries
    incProgress(1/7, detail = "ClinicalTrials.gov")
    if (nrow(CTgov)>0) {
      temporary.references.file <- data.frame(cbind(rep("ClinicalTrials.gov",nrow(CTgov)),
                                                    CTgov$NCT.Number, 
                                                    rep(NA,nrow(CTgov)),
                                                    rep(NA,nrow(CTgov)),
                                                    CTgov$NCT.Number, 
                                                    rep(NA,nrow(CTgov)),
                                                    rep(NA,nrow(CTgov)),
                                                    CTgov$Study.URL,
                                                    CTgov$Sponsor,
                                                    rep(NA,nrow(CTgov)),
                                                    CTgov$Study.Title,
                                                    CTgov.Summary(
                                                      data.frame(cbind(
                                                        CTgov$Brief.Summary, 
                                                        CTgov$Study.Design, 
                                                        CTgov$Conditions,
                                                        CTgov$Interventions,
                                                        CTgov$Primary.Outcome.Measures,
                                                        CTgov$Secondary.Outcome.Measures,
                                                        CTgov$Other.Outcome.Measures
                                                      ))
                                                    ),
                                                    CTgov$Study.URL,
                                                    substr(CTgov$First.Posted,1,4),
                                                    rep(NA,nrow(CTgov)),
                                                    rep(NA,nrow(CTgov)),
                                                    rep(NA,nrow(CTgov)),
                                                    rep("",nrow(CTgov))
      )
      )
      colnames(temporary.references.file) <- references.file.column.names
      if (nrow(temporary.references.file) > 0) {
        references.file <- rbind(references.file, temporary.references.file)
      }
    }
    incProgress(1/7, detail = "WHO ICTRP")
    if (nrow(ICTRP)>0) {
      temporary.references.file <- data.frame(cbind(rep("ICTRP",nrow(ICTRP)),
                                                    ICTRP$Internal_Number, 
                                                    rep(NA,nrow(ICTRP)),
                                                    rep(NA,nrow(ICTRP)),
                                                    rep(NA,nrow(ICTRP)),
                                                    ICTRP$TrialID, 
                                                    rep(NA,nrow(ICTRP)),
                                                    ICTRP$web_address,
                                                    Author.list.ICTRP(data.frame(cbind(ICTRP$Contact_Firstname, ICTRP$Contact_Lastname))),
                                                    Author.Contact.ICTRP(data.frame(cbind(ICTRP$Contact_Email, ICTRP$Contact_Address))),
                                                    ICTRP$Scientific_title,
                                                    ICTRP.Summary(
                                                      data.frame(cbind(
                                                        ICTRP$Study_design, 
                                                        ICTRP$Inclusion_Criteria, 
                                                        ICTRP$Exclusion_Criteria,
                                                        ICTRP$Condition,
                                                        ICTRP$Intervention,
                                                        ICTRP$Primary_outcome,
                                                        ICTRP$Secondary_outcome
                                                      ))
                                                    ),
                                                    ICTRP$web_address,
                                                    substr(ICTRP$Date_registration3,1,4),
                                                    rep(NA,nrow(ICTRP)),
                                                    rep(NA,nrow(ICTRP)),
                                                    rep(NA,nrow(ICTRP)),
                                                    rep("",nrow(ICTRP))
      )
      )
      colnames(temporary.references.file) <- references.file.column.names
      temporary.references.file <- temporary.references.file[
        ((is.na(temporary.references.file$other.trial.identifier)) | (is.na(match(temporary.references.file$other.trial.identifier,references.file$ctgov.id)))),
      ]
      if (nrow(temporary.references.file) > 0) {
        references.file <- rbind(references.file, temporary.references.file)
      }
    }
    incProgress(1/7, detail = "Cochrane")
    if (nrow(Cochrane)>0) {
      temporary.references.file <- data.frame(cbind(rep("Cochrane Library",nrow(Cochrane)),
                                                    Cochrane$CENTRAL.ID, 
                                                    str_replace_all(Cochrane$PubMed.ID, "PUBMED ",""), 
                                                    str_replace_all(Cochrane$Embase.ID, "EMBASE ",""), 
                                                    str_replace_all(Cochrane$CTgov.ID, "CTgov ",""), 
                                                    str_replace_all(Cochrane$ICTRP.ID, "ICTRP ",""), 
                                                    rep(NA,nrow(Cochrane)),
                                                    Cochrane$DOI,
                                                    sapply(Cochrane$Author.s.,Author.list.wos),
                                                    str_replace_all(Cochrane$ICTRP.ID, "ICTRP ",""), 
                                                    Cochrane$Title,
                                                    Cochrane$Abstract,
                                                    Cochrane$Source,
                                                    Cochrane$Year,
                                                    Cochrane$Volume,
                                                    Cochrane$Issue,
                                                    sapply(Cochrane$Pages, Replace.hyphen),
                                                    Cochrane$Keywords
      )
      )
      colnames(temporary.references.file) <- references.file.column.names
      temporary.references.file$pmid[temporary.references.file$pmid == ""] <- NA
      temporary.references.file$embase.id[temporary.references.file$embase.id == ""] <- NA
      temporary.references.file$ctgov.id[temporary.references.file$ctgov.id == ""] <- NA
      temporary.references.file$ictrp.id[temporary.references.file$ictrp.id == ""] <- NA
      temporary.references.file <- temporary.references.file[
        ((is.na(temporary.references.file$pmid)) | (is.na(match(temporary.references.file$pmid,references.file$pmid)))),
      ]
      temporary.references.file <- temporary.references.file[
        ((is.na(temporary.references.file$embase.id)) | (is.na(match(temporary.references.file$embase.id,references.file$embase.id)))),
      ]
      temporary.references.file <- temporary.references.file[
        ((is.na(temporary.references.file$ctgov.id)) | (is.na(match(temporary.references.file$ctgov.id,references.file$ctgov.id)))),
      ]
      temporary.references.file <- temporary.references.file[
        ((is.na(temporary.references.file$ictrp.id)) | (is.na(match(temporary.references.file$ictrp.id,references.file$ictrp.id)))),
      ]
      
      if (nrow(temporary.references.file) > 0) {
        references.file <- rbind(references.file, temporary.references.file)
      }
    }
    references.file$keywords[references.file$keywords == ""] <- "None" 
    references.file$article.reference <- Create.reference(
      data.frame(cbind(
        references.file$authors,
        references.file$article.title,
        references.file$journal.name,
        references.file$article.publication.year,
        references.file$article.volume,
        references.file$article.issue,
        references.file$article.pages,
        references.file$url
      ))
    )
    
    # Create copy for download without html codes
    references.file.nohtml <- references.file
    references.file.nohtml[,"article.abstract"] <-
      str_remove_all(
        str_remove_all(
          str_replace_all(references.file.nohtml[,"article.abstract"],
                          "<br>",
                          " "),
          "<strong>"
        ), "</strong>"
      )
    references.file.nohtml[,"keywords"] <- 
      str_remove_all(
        str_remove_all(
          str_replace_all(references.file.nohtml[, "keywords"],
                          "<br>",
                          " "),
          "<strong>"
        ), "</strong>"
      )
    write.csv(references.file.nohtml,paste0(index.file.path,"FullDetails/2_Deduplicated_References.csv"), row.names = FALSE, na = "")
    return(list(index.file.path = index.file.path, 
                references.file = references.file
    ))})
}
highlight.keywords <- function(index.file.path, keywords.file.full.name, references.file){
  keywords.file <- read.csv(keywords.file.full.name,header = TRUE)
  if (ncol(keywords.file) == 2){
    keywords.file$weight <- 1
  } else {
    keywords.file$weight[is.na(keywords.file$weight)] <- 1
  }
  # Number of keywords and colours
  withProgress(message = 'Highlighting key words...', value = 0, {
    concept <- keywords.file$concept[!is.na(keywords.file$concept)]
    concept <- unique(concept[concept != ""])
    concept.weight <- keywords.file$weight[match(concept, keywords.file$concept)]
    # Colour codes
    background <- viridis(length(concept))
    # For generating a suitable font colour, the algorithm from https://stackoverflow.com/questions/1855884/determine-font-color-based-on-background-color was used
    # However, this did not account for transparency (alpha); so revised the threshold based on luminance and transparency
    # Convert viridis colour to RGB
    # Alpha is needed last, so rearrange
    font <- paste0("#",substr(background,4,nchar(background)), substr(background,2,3))
    rgb.font <- col2rgb(font, alpha = TRUE)
    colnames(rgb.font) <- font
    rgb.font <- data.frame(t(rgb.font))
    rgb.font$luminance <- (0.299 * rgb.font$red + 0.587 * rgb.font$green + 0.114 * rgb.font$blue)/255
    # convert alpha to be between 0 and 1, one indicating very transparent
    rgb.font$alpha <- rgb.font$alpha/255
    # Get the basic font colour
    rgb.font$colour.1[rgb.font$luminance > 0.5] <- "black"
    rgb.font$colour.1[rgb.font$luminance <= 0.5] <- "white"
    # Get the font colour based on transparency
    rgb.font$colour.2[rgb.font$alpha > 0.5] <- "black"
    rgb.font$colour.2[rgb.font$alpha <= 0.5] <- "white"
    # If there is a match, choose the font colour
    # If there is a mismatch, choose medium colours
    rgb.font$colour[rgb.font$colour.1 == rgb.font$colour.2] <- rgb.font$colour.1[rgb.font$colour.1 == rgb.font$colour.2]
    rgb.font$colour[
      (rgb.font$colour.1 != rgb.font$colour.2) &
        (rgb.font$alpha <= 0.5)
    ] <- "lightcyan"
    rgb.font$colour[
      (rgb.font$colour.1 != rgb.font$colour.2) &
        (rgb.font$alpha > 0.5)
    ] <- "purple"
    font <- rgb.font$colour    
    colour.scheme <- data.frame(cbind(
      concept, concept.weight, background, font
    ))
    keywords.colours <- data.frame(keywords.file$keywords, keywords.file$concept, keywords.file$weight)
    keywords.colours <- keywords.colours[
      (! is.na(keywords.colours[,2])) &
        (keywords.colours[,2] != ""),
    ]
    keywords.colours <- data.frame(cbind(keywords.colours, 
                                         rep(NA,nrow(keywords.colours)),
                                         rep(NA,nrow(keywords.colours))
    ))
    colnames(keywords.colours) <- c("keywords", "concept", "concept.weight", "background", "font")
    for (i in 1:nrow(colour.scheme)) {
      keywords.colours[
        (keywords.colours$concept == colour.scheme$concept[i])
        ,4:5] <- colour.scheme[i,3:4]
    }
    # Three other variations for each keywords.colours: all lower, all upper, title case
    keywords.colours.new <- keywords.colours
    keywords.colours.new <- rbind(
      keywords.colours.new,
      cbind(
        keywords = str_to_lower(keywords.colours$keywords),
        keywords.colours[,2:5]
      )
    )
    keywords.colours.new <- rbind(
      keywords.colours.new,
      cbind(
        keywords = str_to_upper(keywords.colours$keywords),
        keywords.colours[,2:5]
      )
    )
    keywords.colours.new <- rbind(
      keywords.colours.new,
      cbind(
        keywords = str_to_title(keywords.colours$keywords),
        keywords.colours[,2:5]
      )
    )
    # Now remove the duplicates
    keywords.colours.new <- keywords.colours.new[
      match(unique(keywords.colours.new$keywords),keywords.colours.new$keywords)
      ,]
    
    references.file$article.abstract.highlighted <- references.file$article.abstract
    references.file$article.title.highlighted <- references.file$article.title
    references.file$keywords.highlighted <- references.file$keywords
    references.file$concept.times <- 0
    
    for (i in 1:nrow(keywords.colours.new)) {
      references.file$article.abstract.highlighted <- str_replace_all(references.file$article.abstract.highlighted,
                                                                      fixed(keywords.colours.new$keywords[i],ignore_case = FALSE),
                                                                      paste0(
                                                                        '<span style="background-color:', keywords.colours.new$background[i], 
                                                                        ';color:',keywords.colours.new$font[i],'">'
                                                                        , keywords.colours.new$keywords[i],
                                                                        '</span>'
                                                                      )           
      )
      references.file$article.title.highlighted <- str_replace_all(references.file$article.title.highlighted,
                                                                   fixed(keywords.colours.new$keywords[i],ignore_case = FALSE),
                                                                   paste0(
                                                                     '<span style="background-color:', keywords.colours.new$background[i], 
                                                                     ';color:',keywords.colours.new$font[i],'">'
                                                                     , keywords.colours.new$keywords[i],
                                                                     '</span>'
                                                                   )           
      )
      references.file$keywords.highlighted <- str_replace_all(references.file$keywords.highlighted,
                                                              fixed(keywords.colours.new$keywords[i],ignore_case = FALSE),
                                                              paste0(
                                                                '<span style="background-color:', keywords.colours.new$background[i], 
                                                                ';color:',keywords.colours.new$font[i],'">'
                                                                , keywords.colours.new$keywords[i],
                                                                '</span>'
                                                              )           
      )
      references.file$concept.times <- references.file$concept.times + 
        str_count(
          references.file$article.abstract.highlighted,
          keywords.colours.new$keywords[i]
        ) * as.numeric(keywords.colours.new$concept.weight[i]) + 
        str_count(
          references.file$article.title.highlighted,
          keywords.colours.new$keywords[i]
        ) * as.numeric(keywords.colours.new$concept.weight[i]) + 
        str_count(
          references.file$keywords.highlighted,
          keywords.colours.new$keywords[i]
        ) * as.numeric(keywords.colours.new$concept.weight[i])
      incProgress(1/nrow(keywords.colours.new), detail = paste0(i, " of ", nrow(keywords.colours.new)))
    }
    references.file$concepts.present <- ""
    references.file$concepts.present.true <- ""
    references.file$number.of.concepts <- 0
    for (i in 1:nrow(colour.scheme)) {
      references.file$concepts.present <- paste0(
        if (i>1) {
          paste0(references.file$concepts.present, "; ")
        },
        colour.scheme$concept[i], ": ",
        (
          (str_detect(references.file$article.abstract.highlighted, 
                      paste0('<span style=\\"background-color:', colour.scheme$background[i])
          )) |
            (str_detect(references.file$article.title.highlighted, 
                        paste0('<span style=\\"background-color:', colour.scheme$background[i])
            ))|
            (str_detect(references.file$keywords.highlighted, 
                        paste0('<span style=\\"background-color:', colour.scheme$background[i])
            ))
        )
      )
      references.file$concepts.present.true[
        (references.file$concepts.present.true == "") & 
          (
            (str_detect(references.file$article.abstract.highlighted, 
                        paste0('<span style=\\"background-color:', colour.scheme$background[i])
            )) |
              (str_detect(references.file$article.title.highlighted, 
                          paste0('<span style=\\"background-color:', colour.scheme$background[i])
              ))|
              (str_detect(references.file$keywords.highlighted, 
                          paste0('<span style=\\"background-color:', colour.scheme$background[i])
              ))
          )
      ] <- colour.scheme$concept[i]
      references.file$concepts.present.true[
        (references.file$concepts.present.true != "") &
          (! str_detect(
            references.file$concepts.present.true,
            colour.scheme$concept[i]
          )) & 
          (
            (str_detect(references.file$article.abstract.highlighted, 
                        paste0('<span style=\\"background-color:', colour.scheme$background[i])
            )) |
              (str_detect(references.file$article.title.highlighted, 
                          paste0('<span style=\\"background-color:', colour.scheme$background[i])
              ))|
              (str_detect(references.file$keywords.highlighted, 
                          paste0('<span style=\\"background-color:', colour.scheme$background[i])
              ))
          )
      ] <- paste0(
        references.file$concepts.present.true[
          (references.file$concepts.present.true != "") &
            (! str_detect(
              references.file$concepts.present.true,
              colour.scheme$concept[i]
            )) & 
            (
              (str_detect(references.file$article.abstract.highlighted, 
                          paste0('<span style=\\"background-color:', colour.scheme$background[i])
              )) |
                (str_detect(references.file$article.title.highlighted, 
                            paste0('<span style=\\"background-color:', colour.scheme$background[i])
                ))|
                (str_detect(references.file$keywords.highlighted, 
                            paste0('<span style=\\"background-color:', colour.scheme$background[i])
                ))
            )
        ], "; ",
        colour.scheme$concept[i]
      )
    }
    references.file$concepts.present.true[references.file$concepts.present.true == ""] <- "None"
    references.file$number.of.concepts <- str_count(
      references.file$concepts.present,
      "TRUE"
    )
    references.file$concepts.present.true.highlighted <- references.file$concepts.present.true
    references.file$score <- 0
    for (i in 1:nrow(colour.scheme)) {
      references.file$concepts.present.true.highlighted <- str_replace_all(references.file$concepts.present.true.highlighted,
                                                                           fixed(colour.scheme$concept[i],ignore_case = TRUE),
                                                                           paste0(
                                                                             '<span style="background-color:', colour.scheme$background[i], 
                                                                             ';color:',colour.scheme$font[i],'">'
                                                                             , colour.scheme$concept[i],
                                                                             '</span>'
                                                                           )           
      )
      references.file$score[
        str_detect(
          references.file$concepts.present.true,
          colour.scheme$concept[i]
        )
      ] <- references.file$score[
        str_detect(
          references.file$concepts.present.true,
          colour.scheme$concept[i]
        )
      ] + as.numeric(colour.scheme$concept.weight[i])
      
    }
    references.file <- references.file[with(references.file, order(-score, -concept.times)),]
    references.file$order <- 1:nrow(references.file)
    row.names(references.file) <- 1:nrow(references.file)
  })
  write.csv(references.file,paste0(index.file.path,"References_to_Screen/0_Deduplicated_References_ordered.csv"), row.names = FALSE, na = "")
  # Generate reports
  withProgress(message = 'Creating highlighted files...', value = 0, {
    split.references.file <- list()
    for (i in 1:ceiling(nrow(references.file)/100)){
      split.references.file[[i]] <- list()
      if ((nrow(references.file) > ((i-1)*100)) & (nrow(references.file) >= ((i)*100))) {
        split.references.file[[i]][[1]] <- references.file[(((i-1)*100+1):((i-1)*100+100)),]
      } else if ((nrow(references.file) > ((i-1)*100)) & (nrow(references.file) < ((i)*100))) {
        split.references.file[[i]][[1]] <- references.file[(((i-1)*100+1):nrow(references.file)),]
      }
      split.references.file[[i]][[2]] <-  paste0(index.file.path,"References_to_Screen/References_",i,".csv")
      write.csv(split.references.file[[i]][[1]], split.references.file[[i]][[2]][1], row.names = FALSE, na="")
    }
    # Export data to html format (100 rows per file to avoid errors)
    for (i in 1:ceiling(nrow(references.file)/100)){
      suppressMessages({
        suppressWarnings({
          rmarkdown::render("ImportReferencesReportTemplate.Rmd", 
                            output_file = paste0(index.file.path,"References_to_Screen/References_",i,".html"),
                            params = list(file.name = split.references.file[[i]][[2]][1])
          )
          file.remove(split.references.file[[i]][[2]][1])
          incProgress(1/ceiling(nrow(references.file)/100), detail = paste0(i, " of ", ceiling(nrow(references.file)/100)))
        })
      }) 
    }
  })
}

# Functions to create data extraction form ####
split_into_subsections <- function(df) {
  unique_ordered_sub_sections <- paste0(formatC(1:length(unique(df$sub_section)), width = 4, format = "d", flag = "0"), 
                                        '_', 
                                        unique(df$sub_section))
  df$ordered_sub_section <- unique_ordered_sub_sections[
    match(df$sub_section, unique(df$sub_section))
  ]
  df1 <- split.data.frame(
    df, as.factor(df$ordered_sub_section)
  )
  names(df1) <- unique(df$sub_section)
  list(df1,unique_ordered_sub_sections)
}
create_other_characteristics_text <- function(DEF_Design, Template, Customised_Template) {
  create_text_for_row2_each_row <- function(y) {
    if (substr(Customised_Template$other_characteristics$short_name[y],
               (nchar(Customised_Template$other_characteristics$short_name[y])-14),
               (nchar(Customised_Template$other_characteristics$short_name[y]))
    ) == "_intervention_1") {
      DEF_Design$short_names[
        !is.na(match(DEF_Design$variable,
                     substr(Customised_Template$other_characteristics$short_name[y],
                            1,
                            (nchar(Customised_Template$other_characteristics$short_name)-15)
                     )
        ))
      ]
    } else {
      NA
    }
  }
  other_characteristics <- data.frame(
    DEF_Design[
      ! is.na(
        match(DEF_Design$variable,
              substr(Customised_Template$other_characteristics$short_name,
                     1,
                     (nchar(Customised_Template$other_characteristics$short_name)-15)
              )
        )
      ),
    ]
  )
  create_other_characteristics_text_each_row <- function(y) {
    if (other_characteristics$type_1[y] == "number") {
      c(paste0('Enter the number of ',other_characteristics$variable_value[y]),NA)
    } else if (other_characteristics$type_1[y] == "score") {
      c(paste0('Enter the mean ',other_characteristics$variable_value[y]),NA)
    } else {
      c(paste0('Enter: ',other_characteristics$variable_value[y]),NA)    
    }
  }
  create_validity_text_each_row <- function(y) {
    if (other_characteristics$type_1[y] == "number") {
      rep("whole%_%greaterThanOrEqual%_%0",2)
    } else if (other_characteristics$type_1[y] == "score") {
      rep("decimal",2)
    } else {
      rep("",2)    
    }
  }
  list(
    unlist(lapply(1:nrow(Customised_Template$other_characteristics), create_text_for_row2_each_row)),
    unlist(lapply(1:nrow(other_characteristics), create_other_characteristics_text_each_row)),
    unlist(lapply(1:nrow(other_characteristics), create_validity_text_each_row))
  )
}
create_reference <- function(x) {
  authors <- trimws(x[,1])
  authors[is.na(authors)] <- ""
  authors[authors !=""] <- paste0(authors[authors !=""], ". ")
  article.title <- trimws(x[,2])
  article.title[is.na(article.title)] <- ""
  article.title[article.title !=""] <- paste0(article.title[article.title !=""], ". ")
  journal.title <- trimws(x[,3])
  journal.title[is.na(journal.title)] <- ""
  journal.title[journal.title !=""] <- paste0(journal.title[journal.title !=""], ". ")
  publication.year <- trimws(x[,4])
  publication.year[is.na(publication.year)] <- ""
  publication.year[publication.year !=""] <- paste0(publication.year[publication.year !=""], ";")
  volume <- trimws(x[,5])
  volume[is.na(volume)] <- ""
  issue <- trimws(x[,6])
  issue[is.na(issue)] <- ""
  issue[issue !=""] <- paste0("(", issue[issue !=""], ")")
  pages <- trimws(x[,7])
  pages[is.na(pages)] <- ""
  pages[pages == "no pagination"] <- ""
  pages[pages !=""] <- paste0(pages[pages !=""], ". ")
  article.url <- trimws(x[,8])
  article.url[is.na(article.url)] <- ""
  article.url[article.url != ""] <- paste0(article.url[article.url != ""])
  reference <- paste0(
    authors, article.title, journal.title,
    publication.year, volume, issue, ":", 
    pages, article.url,
    "."
  )
  reference = str_replace_all(reference, "\\.\\.","\\.")
  reference = str_replace_all(reference, "\\.\\ \\.","\\.")
  reference = str_replace_all(reference, "\\(\\)","")
  reference = str_replace_all(reference, "\\(\\ \\)","")
  reference = str_replace_all(reference, "\\;\\.",".")
  reference = str_replace_all(reference, "\\;\\:",":")
  reference = str_replace_all(reference, "\\:\\.",".")
  reference = str_replace_all(reference, "\n"," ")
  trimws(reference)
}
create_reference_id <- function(Searches) {
  create_reference_id_step_one <- function(x) {
    x_1 <- Searches$authors[x]
    x_2 <- Searches$article.publication.year[x]
    if (is.na(x_1)) {
      z <- "Anonymous "
    } else {
      if (str_detect(x_1, ",")) {
        y <- substr(x_1, 1,
                    (str_locate(x_1,",")[1]-1)
        )
      } else {
        y <- x_1
      }
      z <- ifelse(str_detect(y, " "),
                  substr(y, 1,
                         (unlist(str_locate_all(y, " "))[
                           length(unlist(str_locate_all(y, " ")))
                         ])
                  ),
                  y)
    }
    z <- paste0(z, x_2)
    return(z)
  }
  name_year <- as.vector(sapply(1:nrow(Searches), create_reference_id_step_one))
  counts <- as.vector(rep(1,length(name_year)))
  cumulative_counts <- as.vector(ave(
    counts,
    name_year,
    FUN = cumsum
  ))
  total_counts <- as.vector(sapply(1:length(name_year), function(x) length(name_year[name_year == name_year[x]])))
  suffix <- rep("",length(name_year))
  suffix[total_counts > 1] <- paste0(' (',cumulative_counts[total_counts > 1], ')')
  reference_id <- paste0(name_year, suffix)
  return(reference_id)  
}
create_dataextraction_form <- function(DEF_Design, StorageFolder, Import_summary, Searches) {
  withProgress(message = 'Creating data extraction form', value = 0, {
    if (missing(Import_summary)) {
      Import_summary <- data.frame(matrix(nrow = 0, ncol = 9))
      colnames(Import_summary) <- c("file.name", "import.status", "references.imported", "database", "file.names", "number.of.files", "file.exists", "file.exists.number", "references.each.database")
      Searches <- data.frame(matrix(nrow = 0, ncol = 21))
      colnames(Searches) <- c("database", "unique.identifier", "pmid", "embase.id", "ctgov.id", "ictrp.id", "other.trial.identifier", "url", "authors", "authors.contact", "article.title", "article.abstract", "journal.name", "article.publication.year", "article.volume", "article.issue", "article.pages", "keywords", "article.reference", "reference.id", "reference")
    }
    # Load the template
    Template <- read.csv("Template.csv", header = TRUE)
    # Process the files
    incProgress(amount = 0.01, detail = "Phase 1: customising the generic template")
    # Somethings need generic modification
    if (! is.na(match("intervention_1", DEF_Design$variable))) {
      Template$row_4_intervention <- str_replace_all(
        Template$row_4_intervention,
        "%_%intervention_1%_%",
        DEF_Design$variable_value[match("intervention_1", DEF_Design$variable)]
      )
      Template[match("outcome_data_additional_favours_intervention_time_to_event",
                     Template$short_name),] <- str_replace_all(
                       Template[match("outcome_data_additional_favours_intervention_time_to_event",
                                      Template$short_name),],
                       "%_%intervention_1%_%",
                       DEF_Design$variable_value[match("intervention_1", DEF_Design$variable)]
                     )
    }
    if (! is.na(match("intervention_2", DEF_Design$variable))) {
      Template$row_4_intervention <- str_replace_all(
        Template$row_4_intervention,
        "%_%intervention_2%_%",
        DEF_Design$variable_value[match("intervention_2", DEF_Design$variable)]
      )
      Template[match("outcome_data_additional_favours_intervention_time_to_event",
                     Template$short_name),] <- str_replace_all(
                       Template[match("outcome_data_additional_favours_intervention_time_to_event",
                                      Template$short_name),],
                       "%_%intervention_2%_%",
                       DEF_Design$variable_value[match("intervention_2", DEF_Design$variable)]
                     )
      
    }
    # Now split the file into subsections
    Customised_Template <- split_into_subsections(Template)[[1]]
    # Things that do not need modification: basic_details, study_inclusion_exclusion, study_author_details, data_extractor_details_comments, recruitment_period
    # Modify the inclusion and exclusion criteria
    # Keep only the rows which are included in the DEF_Design
    Customised_Template$inclusion_exclusion <- Customised_Template$inclusion_exclusion[
      ! is.na(
        match(Customised_Template$inclusion_exclusion$short_name,
              DEF_Design$variable
        )
      )
      ,]
    # Replace the %_%criterion%_% with corresponding text in DEF_Design
    if (nrow(Customised_Template$inclusion_exclusion) > 0) {
      Customised_Template$inclusion_exclusion$row_2_column_name <-
        str_replace_all(
          Customised_Template$inclusion_exclusion$row_2_column_name,
          paste0('%_%criterion_',
                 formatC(1:nrow(Customised_Template$inclusion_exclusion), width = 3, format = "d", flag = "0"), 
                 '%_%'),
          DEF_Design$short_names[match(
            Customised_Template$inclusion_exclusion$short_name,
            DEF_Design$variable
          )]
        )
      Customised_Template$inclusion_exclusion$row_3_details <-
        str_replace_all(
          Customised_Template$inclusion_exclusion$row_3_details,
          paste0('%_%criterion_',
                 formatC(1:nrow(Customised_Template$inclusion_exclusion), width = 3, format = "d", flag = "0"), 
                 '%_%'),
          DEF_Design$variable_value[match(
            Customised_Template$inclusion_exclusion$short_name,
            DEF_Design$variable
          )]
        )  
    }
    # Things that do not need modification: inclusion_exclusion_general, participant_flow_general, progress_plus_place_of_residence_country, progress_plus_place_of_residence_more_details, progress_plus_race, progress_plus_occupation, progress_plus_gender, progress_plus_religion, progress_plus_education, age
    Customised_Template$other_characteristics <- Customised_Template$other_characteristics[
      ! is.na(
        match(
          substr(Customised_Template$other_characteristics$short_name,
                 1,
                 (nchar(Customised_Template$other_characteristics$short_name)-15)
          ),
          DEF_Design$variable
        )
      )
      ,]
    # Replace the %_%characteristics%_% with corresponding text in DEF_Design
    if (nrow(Customised_Template$other_characteristics) > 0) {
      Customised_Template$other_characteristics$row_2_column_name <- create_other_characteristics_text(DEF_Design, Template, Customised_Template)[[1]]
      Customised_Template$other_characteristics$row_3_details <- create_other_characteristics_text(DEF_Design, Template, Customised_Template)[[2]]
      Customised_Template$other_characteristics$validation <- create_other_characteristics_text(DEF_Design, Template, Customised_Template)[[3]]
    }
    Customised_Template$other_characteristics$study_level_intervention_level <- DEF_Design$other_characteristics_study_level_intervention_level[
      match(
        substr(Customised_Template$other_characteristics$short_name,
               1,
               (nchar(Customised_Template$other_characteristics$short_name)-15)
        ),
        DEF_Design$variable
      )
    ]
    Customised_Template$other_characteristics$section[
      Customised_Template$other_characteristics$study_level_intervention_level == "study_level"
    ] <- "participant_characteristics_3"
    Customised_Template$other_characteristics$row_4_intervention[
      Customised_Template$other_characteristics$study_level_intervention_level == "study_level"
    ] <- ""
    Customised_Template$other_characteristics$keep <- ! (  
      (str_detect(Customised_Template$other_characteristics$short_name, "_intervention_2")) & 
        (Customised_Template$other_characteristics$study_level_intervention_level == "study_level")
    )
    Customised_Template$other_characteristics <- Customised_Template$other_characteristics[
      Customised_Template$other_characteristics$keep, 1:9
    ]
    # Things that do not need modification: follow-up
    # For all rob, it is the same scheme: some generic, some ITT, per-protocol, some objective versus subjective and some at outcome level
    # What tools we keep and what we remove depends upon the data extraction plan, otherwise no text revisions are required
    # Per-protocol effect
    if (!is.na(match("per_protocol", DEF_Design$variable))) {
      if(DEF_Design$variable_value[match("per_protocol", DEF_Design$variable)] == "no") {
        Customised_Template$rob2_PP_objective <- Customised_Template$rob2_PP_objective[NULL,]
        Customised_Template$rob2_PP_subjective <- Customised_Template$rob2_PP_subjective[NULL,]
        Customised_Template$rob2_cluster_PP_objective <- Customised_Template$rob2_cluster_PP_objective[NULL,]
        Customised_Template$rob2_cluster_PP_subjective <- Customised_Template$rob2_cluster_PP_subjective[NULL,]
        Customised_Template$rob2_cross_over_PP_objective <- Customised_Template$rob2_cross_over_PP_objective[NULL,]
        Customised_Template$rob2_cross_over_PP_subjective <- Customised_Template$rob2_cross_over_PP_subjective[NULL,]
        Customised_Template$rob2_PP_outcome <- Customised_Template$rob2_PP_outcome[NULL,]
        Customised_Template$rob2_cluster_PP_outcome <- Customised_Template$rob2_cluster_PP_outcome[NULL,]
        Customised_Template$rob2_cross_over_PP_outcome <- Customised_Template$rob2_cross_over_PP_outcome[NULL,]
        Customised_Template$robins_i_PP_most_outcomes <- Customised_Template$robins_i_PP_most_outcomes[NULL,]
        Customised_Template$robins_i_PP_outcome <- Customised_Template$robins_i_PP_outcome[NULL,]
      }
    }
    # Objective outcomes
    if (is.na(match("objective", DEF_Design$outcome_objective_subjective))) {
      Customised_Template$rob2_ITT_objective <- Customised_Template$rob2_ITT_objective[NULL,]
      Customised_Template$rob2_PP_objective <- Customised_Template$rob2_PP_objective[NULL,]
      Customised_Template$rob2_objective <- Customised_Template$rob2_objective[NULL,]
      Customised_Template$rob2_cluster_ITT_objective <- Customised_Template$rob2_cluster_ITT_objective[NULL,]
      Customised_Template$rob2_cluster_PP_objective <- Customised_Template$rob2_cluster_PP_objective[NULL,]
      Customised_Template$rob2_cluster_objective <- Customised_Template$rob2_cluster_objective[NULL,]
      Customised_Template$rob2_cross_over_ITT_objective <- Customised_Template$rob2_cross_over_ITT_objective[NULL,]
      Customised_Template$rob2_cross_over_PP_objective <- Customised_Template$rob2_cross_over_PP_objective[NULL,]
      Customised_Template$rob2_cross_over_objective <- Customised_Template$rob2_cross_over_objective[NULL,]
      Customised_Template$robins_i_objective <- Customised_Template$robins_i_objective[NULL,]
    }
    # Subjective outcomes
    if (is.na(match("subjective", DEF_Design$outcome_objective_subjective))) {
      Customised_Template$rob2_ITT_subjective <- Customised_Template$rob2_ITT_subjective[NULL,]
      Customised_Template$rob2_PP_subjective <- Customised_Template$rob2_PP_subjective[NULL,]
      Customised_Template$rob2_subjective <- Customised_Template$rob2_subjective[NULL,]
      Customised_Template$rob2_cluster_ITT_subjective <- Customised_Template$rob2_cluster_ITT_subjective[NULL,]
      Customised_Template$rob2_cluster_PP_subjective <- Customised_Template$rob2_cluster_PP_subjective[NULL,]
      Customised_Template$rob2_cluster_subjective <- Customised_Template$rob2_cluster_subjective[NULL,]
      Customised_Template$rob2_cross_over_ITT_subjective <- Customised_Template$rob2_cross_over_ITT_subjective[NULL,]
      Customised_Template$rob2_cross_over_PP_subjective <- Customised_Template$rob2_cross_over_PP_subjective[NULL,]
      Customised_Template$rob2_cross_over_subjective <- Customised_Template$rob2_cross_over_subjective[NULL,]
      Customised_Template$robins_i_subjective <- Customised_Template$robins_i_subjective[NULL,]
    }
    # ROB2 cluster
    if (!is.na(match("cluster", DEF_Design$variable))) {
      if(DEF_Design$variable_value[match("cluster", DEF_Design$variable)] == "no") {
        Customised_Template$rob2_cluster_generic <- Customised_Template$rob2_cluster_generic[NULL,]
        Customised_Template$rob2_cluster_ITT_objective <- Customised_Template$rob2_cluster_ITT_objective[NULL,]
        Customised_Template$rob2_cluster_PP_objective <- Customised_Template$rob2_cluster_PP_objective[NULL,]
        Customised_Template$rob2_cluster_most_outcomes_1 <- Customised_Template$rob2_cluster_most_outcomes_1[NULL,]
        Customised_Template$rob2_cluster_objective <- Customised_Template$rob2_cluster_objective[NULL,]
        Customised_Template$rob2_cluster_most_outcomes_2 <- Customised_Template$rob2_cluster_most_outcomes_2[NULL,]
        Customised_Template$rob2_cluster_ITT_subjective <- Customised_Template$rob2_cluster_ITT_subjective[NULL,]
        Customised_Template$rob2_cluster_PP_subjective <- Customised_Template$rob2_cluster_PP_subjective[NULL,]
        Customised_Template$rob2_cluster_subjective <- Customised_Template$rob2_cluster_subjective[NULL,]
        Customised_Template$rob2_cluster_ITT_outcome <- Customised_Template$rob2_cluster_ITT_outcome[NULL,]
        Customised_Template$rob2_cluster_PP_outcome <- Customised_Template$rob2_cluster_PP_outcome[NULL,]
        Customised_Template$rob2_cluster_outcome <- Customised_Template$rob2_cluster_outcome[NULL,]
      }
    }
    # ROB2 cross-over
    if (!is.na(match("cross_over", DEF_Design$variable))) {
      if(DEF_Design$variable_value[match("cross_over", DEF_Design$variable)] == "no") {
        Customised_Template$rob2_cross_over_generic <- Customised_Template$rob2_cross_over_generic[NULL,]
        Customised_Template$rob2_cross_over_ITT_objective <- Customised_Template$rob2_cross_over_ITT_objective[NULL,]
        Customised_Template$rob2_cross_over_PP_objective <- Customised_Template$rob2_cross_over_PP_objective[NULL,]
        Customised_Template$rob2_cross_over_most_outcomes_1 <- Customised_Template$rob2_cross_over_most_outcomes_1[NULL,]
        Customised_Template$rob2_cross_over_objective <- Customised_Template$rob2_cross_over_objective[NULL,]
        Customised_Template$rob2_cross_over_most_outcomes_2 <- Customised_Template$rob2_cross_over_most_outcomes_2[NULL,]
        Customised_Template$rob2_cross_over_ITT_subjective <- Customised_Template$rob2_cross_over_ITT_subjective[NULL,]
        Customised_Template$rob2_cross_over_PP_subjective <- Customised_Template$rob2_cross_over_PP_subjective[NULL,]
        Customised_Template$rob2_cross_over_subjective <- Customised_Template$rob2_cross_over_subjective[NULL,]
        Customised_Template$rob2_cross_over_ITT_outcome <- Customised_Template$rob2_cross_over_ITT_outcome[NULL,]
        Customised_Template$rob2_cross_over_PP_outcome <- Customised_Template$rob2_cross_over_PP_outcome[NULL,]
        Customised_Template$rob2_cross_over_outcome <- Customised_Template$rob2_cross_over_outcome[NULL,]
      }
    }
    # ROBINS-I
    if (!is.na(match("non_randomised_studies_intervention", DEF_Design$variable))) {
      if(DEF_Design$variable_value[match("non_randomised_studies_intervention", DEF_Design$variable)] == "no") {
        Customised_Template$robins_i_generic <- Customised_Template$robins_i_generic[NULL,]
        Customised_Template$robins_i_ITT_most_outcomes_1 <- Customised_Template$robins_i_ITT_most_outcomes_1[NULL,]
        Customised_Template$robins_i_objective <- Customised_Template$robins_i_objective[NULL,]
        Customised_Template$robins_i_most_outcomes_2 <- Customised_Template$robins_i_most_outcomes_2[NULL,]
        Customised_Template$robins_i_subjective <- Customised_Template$robins_i_subjective[NULL,]
        Customised_Template$robins_i_ITT_outcome <- Customised_Template$robins_i_ITT_outcome[NULL,]
        Customised_Template$robins_i_PP_outcome <- Customised_Template$robins_i_PP_outcome[NULL,]
        Customised_Template$robins_i_outcome <- Customised_Template$robins_i_outcome[NULL,]
      }
    }
    # None of the remaining sections need modifications except outcomes
    if (is.na(match("binary", DEF_Design$type_1))) {
      Customised_Template$outcome_data_for_analysis_1$row_3_details[
        match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
      ] <- 
        str_remove_all(
          Customised_Template$outcome_data_for_analysis_1$row_3_details[
            match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
          ],
          "Binary outcome: Enter the number of people with outcome; "
        )
      Customised_Template$outcome_data_for_analysis_additional_1 <- Customised_Template$outcome_data_for_analysis_additional_1[
        -c(
          match("outcome_data_additional_percentage_binary_intervention_1",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_percentage_binary_intervention_2",Customised_Template$outcome_data_for_analysis_additional_1$short_name)
        )
        ,]
    }
    if (is.na(match("continuous", DEF_Design$type_1))) {
      Customised_Template$outcome_data_for_analysis_1$row_3_details[
        match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
      ] <- 
        str_remove_all(
          Customised_Template$outcome_data_for_analysis_1$row_3_details[
            match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
          ],
          "Continuous outcome: Enter the mean value; "
        )
      Customised_Template$outcome_data_for_analysis_1 <- Customised_Template$outcome_data_for_analysis_1[
        -c(
          match("outcome_data_2_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name),
          match("outcome_data_2_intervention_2",Customised_Template$outcome_data_for_analysis_1$short_name),
          match("outcome_data_3",Customised_Template$outcome_data_for_analysis_1$short_name)
        )
        ,]
      Customised_Template$outcome_data_for_analysis_additional_1 <- Customised_Template$outcome_data_for_analysis_additional_1[
        -c(
          match("outcome_data_additional_se_continuous_intervention_1",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_se_continuous_intervention_2",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_median_continuous_intervention_1",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_median_continuous_intervention_2",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_lqr_continuous_intervention_1",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_lqr_continuous_intervention_2",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_uqr_continuous_intervention_1",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_uqr_continuous_intervention_2",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_minimum_continuous_intervention_1",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_minimum_continuous_intervention_2",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_maximum_continuous_intervention_1",Customised_Template$outcome_data_for_analysis_additional_1$short_name),
          match("outcome_data_additional_maximum_continuous_intervention_2",Customised_Template$outcome_data_for_analysis_additional_1$short_name)
        )
        ,]
      Customised_Template$outcome_data_for_analysis_additional_2 <- Customised_Template$outcome_data_for_analysis_additional_2[
        -c(
          match("outcome_data_additional_p_value_continuous",Customised_Template$outcome_data_for_analysis_additional_2$short_name)
        )
        ,]
    }
    if (is.na(match("count", DEF_Design$type_1))) {
      Customised_Template$outcome_data_for_analysis_1$row_3_details[
        match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
      ] <- 
        str_remove_all(
          Customised_Template$outcome_data_for_analysis_1$row_3_details[
            match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
          ],
          "Count outcome: Enter the number of events; "
        )
    }
    if (is.na(match("time-to-event", DEF_Design$type_1))) {
      Customised_Template$outcome_data_for_analysis_1$row_3_details[
        match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
      ] <- 
        str_remove_all(
          Customised_Template$outcome_data_for_analysis_1$row_3_details[
            match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
          ],
          "Time-to-event outcome: Leave this empty"
        )
      Customised_Template$outcome_data_for_analysis_additional_2 <- Customised_Template$outcome_data_for_analysis_additional_2[
        -c(
          match("outcome_data_additional_number_of_events_time_to_event",Customised_Template$outcome_data_for_analysis_additional_2$short_name),
          match("outcome_data_additional_favours_intervention_time_to_event",Customised_Template$outcome_data_for_analysis_additional_2$short_name),
          match("outcome_data_additional_p_value_time_to_event",Customised_Template$outcome_data_for_analysis_additional_2$short_name)
        )
        ,]
    } else {
      Customised_Template$outcome_data_for_analysis_additional_2$validation[
        Customised_Template$outcome_data_for_analysis_additional_2$short_name == "outcome_data_additional_favours_intervention_time_to_event"
      ] <- paste0("list%_%",
                  ifelse(
                    match("intervention_1", DEF_Design$variable),
                    DEF_Design$variable_value[match("intervention_1", DEF_Design$variable)],
                    "intervention_1"
                  ),
                  ", ",
                  ifelse(
                    match("intervention_2", DEF_Design$variable),
                    DEF_Design$variable_value[match("intervention_2", DEF_Design$variable)],
                    "intervention_2"
                  )
      )
      
    }
    # Tidy up the column heading
    Customised_Template$outcome_data_for_analysis_1$row_3_details[
      match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
    ] <- trimws(
      Customised_Template$outcome_data_for_analysis_1$row_3_details[
        match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
      ]
    )
    if (substr(
      Customised_Template$outcome_data_for_analysis_1$row_3_details[
        match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
      ],
      nchar(Customised_Template$outcome_data_for_analysis_1$row_3_details[
        match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
      ]),
      nchar(Customised_Template$outcome_data_for_analysis_1$row_3_details[
        match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
      ])
    ) == ";") {
      Customised_Template$outcome_data_for_analysis_1$row_3_details[
        match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
      ] <- 
        substr(
          Customised_Template$outcome_data_for_analysis_1$row_3_details[
            match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
          ],
          1,
          (nchar(Customised_Template$outcome_data_for_analysis_1$row_3_details[
            match("outcome_data_1_intervention_1",Customised_Template$outcome_data_for_analysis_1$short_name)
          ]) - 1)
        )
    }
    Revised_Template <- do.call("rbind", Customised_Template)
    DEF_Text <- t(Revised_Template[, c("row_1_section_name", "row_2_column_name", "row_3_details", "row_4_intervention")])
    # Load DEF_Template and create conditional formatting styles
    incProgress(amount = 0.09, detail = "Phase 1: preparing the data extraction form sheets")
    DEF <- wb_load("DEF_Template.xlsx")
    DEF$add_dxfs_style(
      name = "style_warning", 
      font_color = wb_color(hex = "#FF9C0006"), 
      bg_fill = wb_color(hex = "#FFFFC7CE")
    )
    DEF$add_dxfs_style(
      name = "style_no_warning", 
      font_color = wb_color(hex = "#FF006100"), 
      bg_fill = wb_color(hex = "#FFC6EFCE")
    )
    DEF$add_dxfs_style(
      name = "style_greyed_out", 
      font_color = wb_color(hex = "#FF808080"), 
      bg_fill = wb_color(hex = "#FFF2F2F2")
    )
    
    # Store loaded information
    DEF$add_worksheet(
      "DEF_Design", visible = "false"
    )
    DEF$add_data(
      sheet = "DEF_Design",
      x = DEF_Design,
      col_names = TRUE,
      dims = wb_dims(1, 1),
      na.strings = ""
    )
    DEF$add_worksheet(
      "Revised_Template", visible = "false"
    )
    DEF$add_data(
      sheet = "Revised_Template",
      x = Revised_Template,
      col_names = TRUE,
      dims = wb_dims(1, 1),
      na.strings = ""
    )
    DEF$add_worksheet(
      "Reference_flow", visible = "false"
    )
    # Reference_flow
    Reference_flow <- cbind.data.frame(
      parameter = c("Number of references from database searches",
                    "Number of deduplicated references",
                    "Number of duplicate references not identified by automated removal",
                    "Number of references from other sources",
                    "Number of references screened",
                    "Number of references for which full text was sought",
                    "Number of references included",
                    "Number of studies included",
                    "Number of references of ongoing studies meeting inclusion criteria",
                    "Number of references excluded"
      ),
      numbers = rep(NA,10)
    )
    if ((nrow(Import_summary) >0) & (!is.na(Import_summary[1,1]))) {
      Import_summary$references.each.database <-
        c(
          sapply(
            1:length(Import_summary$database[Import_summary$database !=""]),
            function (x)
              sum(Import_summary$references.imported[
                match(str_split(
                  Import_summary$file.names,
                  "\\|"
                )[[x]], Import_summary$file.name
                )
              ]
              )
          ),
          rep(NA, length(Import_summary$database[Import_summary$database ==""]))
        )
      Searches$reference <- 
        create_reference(
          data.frame(cbind(
            Searches$authors,
            Searches$article.title,
            Searches$journal.name,
            Searches$article.publication.year,
            Searches$article.volume,
            Searches$article.issue,
            Searches$article.pages,
            Searches$url
          ))
        )
      Searches$reference.id <- create_reference_id(Searches)
      Reference_flow$numbers[Reference_flow$parameter == "Number of references from database searches"] <- 
        sum(Import_summary$references.each.database, na.rm = TRUE)
      Reference_flow$numbers[Reference_flow$parameter == "Number of deduplicated references"] <- nrow(Searches)
    }
    DEF$add_data(
      sheet = "Reference_flow",
      x = Import_summary,
      col_names = TRUE,
      dims = wb_dims(1, 1),
      na.strings = ""
    )
    if (nrow(Import_summary) >0) {
      DEF$add_data(
        sheet = "Reference_flow",
        x = cbind.data.frame(
          1:nrow(Searches),
          Searches$reference.id,
          Searches$reference
        ),
        col_names = TRUE,
        dims = wb_dims(1, 10),
        na.strings = ""
      )
      DEF$add_data(
        sheet = "Reference_flow",
        x = Reference_flow,
        col_names = TRUE,
        dims = wb_dims(1, 13),
        na.strings = ""
      )
    }
    DEF$add_formula(
      sheet = "Reference_flow",
      x = c(
        'COUNTIF(Excluded!D:D,"Unidentified duplicate record")',
        'COUNTA(Screening_First!B:B)-1-N3',
        'N3-N4+N5',
        'N6-COUNTIF(Screening_Summary!L:L,"Excluded")',
        'COUNTIF(FullText_Summary!M:M,"Included")',
        '"To calculate on uploading the document"',
        'COUNTIF(Excluded!D:D,"Ongoing study without interim data")',
        'COUNTIF(FullText_Summary!M:M,"Excluded")-N4'
      ),
      dims = wb_dims(4, 14)
    )
    # Instructions
    instructions <- read_xlsx(DEF,"Instructions",start_row = 1, col_names = FALSE, cols = 1)
    DEF$add_data(
      sheet = "Instructions",
      x = paste0(
        (1:length(
          DEF_Design$additional_text[substr(DEF_Design$variable,1,8) ==
                                       'outcome_'
          ]
        ))+(as.numeric(substr(
          instructions[nrow(instructions)-1,],
          1,
          (str_locate(instructions[nrow(instructions)-1,], "\\.")[1]-1)  
        ))),
        '. ',
        DEF_Design$variable_value[substr(DEF_Design$variable,1,8) ==
                                    'outcome_'
        ],
        ': ',
        DEF_Design$additional_text[substr(DEF_Design$variable,1,8) ==
                                     'outcome_'
        ],
        '.'
      ),
      dims = wb_dims((nrow(instructions)+1), 1),
      na.strings = ""
    )
    DEF$add_fill(
      sheet = "Instructions",
      dims = wb_dims(
        2:(nrow(instructions)+length(
          DEF_Design$additional_text[substr(DEF_Design$variable,1,8) ==
                                       'outcome_'
          ]
        )),
        1),
      color =  wb_color(hex = "#FFEFF9EB")
    )
    DEF$add_fill(
      sheet = "Instructions",
      dims = wb_dims(
        1:(nrow(instructions)+length(
          DEF_Design$additional_text[substr(DEF_Design$variable,1,8) ==
                                       'outcome_'
          ]
        )),
        2),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$add_fill(
      sheet = "Instructions",
      dims = wb_dims(
        ((nrow(instructions)+length(
          DEF_Design$additional_text[substr(DEF_Design$variable,1,8) ==
                                       'outcome_'
          ]
        ))+1),
        1:2),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$freeze_pane(
      sheet = "Instructions",
      first_active_row = 2,
      first_active_col = 3
    )
    DEF$protect_worksheet(
      sheet = "Instructions",
      protect = TRUE
    )
    # Screening_First
    DEF$add_data(
      sheet = "Screening_First",
      x = 1:(nrow(Searches)+100),
      dims = wb_dims(2,1),
      na.strings = ""
    )
    DEF$add_data(
      sheet = "Screening_First",
      x = cbind.data.frame(
        Searches$reference.id,
        Searches$reference
      ),
      col_names = FALSE,
      dims = wb_dims(2,2),
      na.strings = ""
    )
    DEF$add_data_validation(
      sheet = "Screening_First",
      dims = wb_dims(2:(nrow(Searches)+101),4),
      type = "list",
      value = '"Included,Excluded"',
      error_title = "Error",
      error = "Select from one of 'Included' or 'Excluded'. If doubtful, select 'Included'"
    )
    DEF$add_fill(
      sheet = "Screening_First",
      dims = wb_dims(2:(nrow(Searches)+101),c(1:3)),
      color =  wb_color(hex = "#FFFFFFCC"),
      every_nth_row = 2
    )
    DEF$add_fill(
      sheet = "Screening_First",
      dims = wb_dims(2:(nrow(Searches)+101),4:5),
      color =  wb_color(hex = "#FFFFCCFF"),
      every_nth_row = 2
    )
    DEF$add_fill(
      sheet = "Screening_First",
      dims = wb_dims(1:(nrow(Searches)+102),6),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$add_fill(
      sheet = "Screening_First",
      dims = wb_dims((nrow(Searches)+102),1:5),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$freeze_pane(
      sheet = "Screening_First",
      first_active_row = 2,
      first_active_col = 4
    )
    DEF$protect_worksheet(
      sheet = "Screening_First",
      protect = TRUE
    )
    DEF$clone_worksheet(
      old = "Screening_First",
      new = "Screening_Second"
    )
    DEF$add_fill(
      sheet = "Screening_Second",
      dims = wb_dims(2:(nrow(Searches)+101),c(4:5)),
      color =  wb_color(hex = "#FFCAEDFB"),
      every_nth_row = 2
    )
    DEF$worksheets[[match("Screening_Second", DEF$get_sheet_names())]]$sheetPr <- 
      "<sheetPr><tabColor rgb=\"FF002060\"/></sheetPr>"
    # For adding references from other sources
    DEF$add_fill(
      sheet = "Screening_First",
      dims = wb_dims((nrow(Searches)+1):(nrow(Searches)+101),c(2:3)),
      color =  wb_color(hex = "#FFFFCCFF"),
      every_nth_row = 2
    )
    DEF$add_formula(
      sheet = "Screening_Second",
      x= paste0('IF(Screening_First!B', (nrow(Searches)+2):(nrow(Searches)+101),'="","",Screening_First!B', (nrow(Searches)+2):(nrow(Searches)+101),')'),
      dims = wb_dims((nrow(Searches)+2):(nrow(Searches)+101),2)
    )
    DEF$add_formula(
      sheet = "Screening_Second",
      x= paste0('IF(Screening_First!C', (nrow(Searches)+2):(nrow(Searches)+101),'="","",Screening_First!C', (nrow(Searches)+2):(nrow(Searches)+101),')'),
      dims = wb_dims((nrow(Searches)+2):(nrow(Searches)+101),3)
    )
    # Screening_Summary
    DEF$add_data(
      sheet = "Screening_Summary",
      x = 1:(nrow(Searches)+100),
      dims = wb_dims(2,1),
      na.strings = ""
    )
    DEF$add_data(
      sheet = "Screening_Summary",
      x = cbind.data.frame(
        Searches$reference.id,
        Searches$reference
      ),
      col_names = FALSE,
      dims = wb_dims(2,2),
      na.strings = ""
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x= paste0('IF(Screening_First!B', (nrow(Searches)+2):(nrow(Searches)+101),'="","",Screening_First!B', (nrow(Searches)+2):(nrow(Searches)+101),')'),
      dims = wb_dims((nrow(Searches)+2):(nrow(Searches)+101),2)
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x= paste0('IF(Screening_First!C', (nrow(Searches)+2):(nrow(Searches)+101),'="","",Screening_First!C', (nrow(Searches)+2):(nrow(Searches)+101),')'),
      dims = wb_dims((nrow(Searches)+2):(nrow(Searches)+101),3)
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x = paste0('IF(Screening_First!D', 2:(nrow(Searches)+101),'="","",Screening_First!D', 2:(nrow(Searches)+101),')'),
      dims = wb_dims(2:(nrow(Searches)+101),4)
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x = paste0('IF(Screening_Second!D', 2:(nrow(Searches)+101),'="","",Screening_Second!D', 2:(nrow(Searches)+101),')'),
      dims = wb_dims(2:(nrow(Searches)+101),5)
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x = paste0('IF(AND($D', 2:(nrow(Searches)+101),'="",$E', 2:(nrow(Searches)+101),'=""),"",
             IF(AND($D', 2:(nrow(Searches)+101),'="Included",$E', 2:(nrow(Searches)+101),'="Included"),
             "Yes","No"))'),
      dims = wb_dims(2:(nrow(Searches)+101),6)
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x = paste0('IF(AND($D', 2:(nrow(Searches)+101),'="",$E', 2:(nrow(Searches)+101),'=""),"",
             IF(AND($D', 2:(nrow(Searches)+101),'="Excluded",$E', 2:(nrow(Searches)+101),'="Excluded"),
             "Yes","No"))'),
      dims = wb_dims(2:(nrow(Searches)+101),7)
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x = paste0('IF(AND($D', 2:(nrow(Searches)+101),'="",$E', 2:(nrow(Searches)+101),'=""),"",
             IF(OR($F', 2:(nrow(Searches)+101),'="Yes",$G', 2:(nrow(Searches)+101),'="Yes"),"No",
             IF($D', 2:(nrow(Searches)+101),'="Included","Yes","No")))'),
      dims = wb_dims(2:(nrow(Searches)+101),8)
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x = paste0('IF(AND($D', 2:(nrow(Searches)+101),'="",$E', 2:(nrow(Searches)+101),'=""),"",
             IF(OR($F', 2:(nrow(Searches)+101),'="Yes",$G', 2:(nrow(Searches)+101),'="Yes"),"No",
             IF($E', 2:(nrow(Searches)+101),'="Included","Yes","No")))'),
      dims = wb_dims(2:(nrow(Searches)+101),9)
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x = paste0(
        'IF(AND(H', 2:(nrow(Searches)+101),'="", I', 2:(nrow(Searches)+101),'=""),
    "",
    IF(OR(H', 2:(nrow(Searches)+101),'="Yes", I', 2:(nrow(Searches)+101),'="Yes"),
    "Yes","No")
    )'
      ),
      dims = wb_dims(2:(nrow(Searches)+101),10)
    )
    DEF$add_formula(
      sheet = "Screening_Summary",
      x = paste0(
        'IF(F', 2:(nrow(Searches)+101),'="","",',
        '"Reviewer_1: " & ',
        'Screening_First!E', 2:(nrow(Searches)+101),' & char(10) & ',
        '"Reviewer_2: " & ',
        'Screening_Second!E', 2:(nrow(Searches)+101),
        ')'
      ),
      dims = wb_dims(2:(nrow(Searches)+101),11)
    )
    DEF$add_data_validation(
      sheet = "Screening_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),12),
      type = "list",
      value = '"Included,Excluded"',
      error_title = "Error",
      error = "Select from one of 'Included' or 'Excluded'. If doubtful, select 'Included'"
    )
    DEF$add_conditional_formatting(
      sheet = "Screening_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),10),
      rule = "Yes",
      type = "containsText",
      style = "style_warning"
    )
    DEF$add_conditional_formatting(
      sheet = "Screening_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),10),
      rule = "No",
      type = "containsText",
      style = "style_no_warning"
    )
    DEF$add_fill(
      sheet = "Screening_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),c(1:11)),
      color =  wb_color(hex = "#FFFFFFCC"),
      every_nth_row = 2
    )
    DEF$add_fill(
      sheet = "Screening_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),12),
      color =  wb_color(hex = "#FFFFCC66"),
      every_nth_row = 2
    )
    DEF$add_fill(
      sheet = "Screening_Summary",
      dims = wb_dims(1:(nrow(Searches)+102),13),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$add_fill(
      sheet = "Screening_Summary",
      dims = wb_dims((nrow(Searches)+102),1:12),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$freeze_pane(
      sheet = "Screening_Summary",
      first_active_row = 2,
      first_active_col = 3
    )
    DEF$protect_worksheet(
      sheet = "Screening_Summary",
      protect = TRUE
    )
    # FullText_First
    DEF$add_data(
      sheet = "FullText_First",
      x = 1:(nrow(Searches)+100),
      dims = wb_dims(2,1),
      na.strings = ""
    )
    DEF$add_data(
      sheet = "FullText_First",
      x = cbind.data.frame(
        Searches$reference.id,
        Searches$reference
      ),
      col_names = FALSE,
      dims = wb_dims(2,2),
      na.strings = ""
    )
    DEF$add_formula(
      sheet = "FullText_First",
      x= paste0('IF(Screening_First!B', (nrow(Searches)+2):(nrow(Searches)+101),'="","",Screening_First!B', (nrow(Searches)+2):(nrow(Searches)+101),')'),
      dims = wb_dims((nrow(Searches)+2):(nrow(Searches)+101),2)
    )
    DEF$add_formula(
      sheet = "FullText_First",
      x= paste0('IF(Screening_First!C', (nrow(Searches)+2):(nrow(Searches)+101),'="","",Screening_First!C', (nrow(Searches)+2):(nrow(Searches)+101),')'),
      dims = wb_dims((nrow(Searches)+2):(nrow(Searches)+101),3)
    )
    DEF$add_formula(
      sheet = "FullText_First",
      x = paste0('IF(Screening_First!D', 2:(nrow(Searches)+101),'="","",Screening_First!D', 2:(nrow(Searches)+101),')'),
      dims = wb_dims(2:(nrow(Searches)+101),4)
    )
    DEF$add_formula(
      sheet = "FullText_First",
      x = paste0('IF(AND(E', 2:(nrow(Searches)+101),'="",D', 2:(nrow(Searches)+101),'=""),"",IF(E', 2:(nrow(Searches)+101),'="",D', 2:(nrow(Searches)+101),',E', 2:(nrow(Searches)+101),'))'),
      dims = wb_dims(2:(nrow(Searches)+101),8)
    )
    DEF$add_data_validation(
      sheet = "FullText_First",
      dims = wb_dims(2:(nrow(Searches)+101),5),
      type = "list",
      value = '"Included,Excluded"',
      error_title = "Error",
      error = "Select from one of 'Included' or 'Excluded'. If doubtful, select 'Included'"
    )
    DEF$add_data_validation(
      sheet = "FullText_First",
      dims = wb_dims(2:(nrow(Searches)+101),6),
      type = "list",
      value = "Exclusion_List",
      error_title = "Error",
      error = "Select from one of the options from the drop-down menu. If the reason is not in the list, please select 'Other reasons' and provide additional details in the relevant column."
    )
    DEF$add_conditional_formatting(
      sheet = "FullText_First",
      dims = wb_dims(2:(nrow(Searches)+101),4),
      rule = "Excluded",
      type = "containsText",
      style = "style_greyed_out"
    )
    DEF$add_fill(
      sheet = "FullText_First",
      dims = wb_dims(2:(nrow(Searches)+101),c(1:8)),
      color =  wb_color(hex = "#FFFFFFCC"),
      every_nth_row = 2
    )
    DEF$add_fill(
      sheet = "FullText_First",
      dims = wb_dims(2:(nrow(Searches)+101),5:7),
      color =  wb_color(hex = "#FFFFCCFF"),
      every_nth_row = 2
    )
    DEF$add_fill(
      sheet = "FullText_First",
      dims = wb_dims(1:(nrow(Searches)+102),9),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$add_fill(
      sheet = "FullText_First",
      dims = wb_dims((nrow(Searches)+102),1:8),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$freeze_pane(
      sheet = "FullText_First",
      first_active_row = 2,
      first_active_col = 3
    )
    DEF$protect_worksheet(
      sheet = "FullText_First",
      protect = TRUE
    )
    DEF$clone_worksheet(
      old = "FullText_First",
      new = "FullText_Second"
    )
    DEF$add_formula(
      sheet = "FullText_Second",
      x = paste0('IF(Screening_Second!D', 2:(nrow(Searches)+101),'="","",Screening_Second!D', 2:(nrow(Searches)+101),')'),
      dims = wb_dims(2:(nrow(Searches)+101),4)
    )
    DEF$add_fill(
      sheet = "FullText_Second",
      dims = wb_dims(2:(nrow(Searches)+101),c(5:7)),
      color =  wb_color(hex = "#FFCAEDFB"),
      every_nth_row = 2
    )
    DEF$worksheets[[match("FullText_Second", DEF$get_sheet_names())]]$sheetPr <- 
      "<sheetPr><tabColor rgb=\"FF002060\"/></sheetPr>"
    # FullText_Summary
    DEF$add_data(
      sheet = "FullText_Summary",
      x = 1:(nrow(Searches)+100),
      dims = wb_dims(2,1),
      na.strings = ""
    )
    DEF$add_data(
      sheet = "FullText_Summary",
      x = cbind.data.frame(
        Searches$reference.id,
        Searches$reference
      ),
      col_names = FALSE,
      dims = wb_dims(2,2),
      na.strings = ""
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x= paste0('IF(Screening_First!B', (nrow(Searches)+2):(nrow(Searches)+101),'="","",Screening_First!B', (nrow(Searches)+2):(nrow(Searches)+101),')'),
      dims = wb_dims((nrow(Searches)+2):(nrow(Searches)+101),2)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x= paste0('IF(Screening_First!C', (nrow(Searches)+2):(nrow(Searches)+101),'="","",Screening_First!C', (nrow(Searches)+2):(nrow(Searches)+101),')'),
      dims = wb_dims((nrow(Searches)+2):(nrow(Searches)+101),3)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x = paste0('IF(FullText_First!D', 2:(nrow(Searches)+101),'="","",FullText_First!D', 2:(nrow(Searches)+101),')'),
      dims = wb_dims(2:(nrow(Searches)+101),4)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x = paste0('IF(FullText_Second!D', 2:(nrow(Searches)+101),'="","",FullText_Second!D', 2:(nrow(Searches)+101),')'),
      dims = wb_dims(2:(nrow(Searches)+101),5)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x = paste0('IF(AND($D', 2:(nrow(Searches)+101),'="",$E', 2:(nrow(Searches)+101),'=""),"",
             IF(AND($D', 2:(nrow(Searches)+101),'="Included",$E', 2:(nrow(Searches)+101),'="Included"),
             "Yes","No"))'),
      dims = wb_dims(2:(nrow(Searches)+101),6)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x = paste0('IF(AND($D', 2:(nrow(Searches)+101),'="",$E', 2:(nrow(Searches)+101),'=""),"",
             IF(AND($D', 2:(nrow(Searches)+101),'="Excluded",$E', 2:(nrow(Searches)+101),'="Excluded"),
             "Yes","No"))'),
      dims = wb_dims(2:(nrow(Searches)+101),7)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x = paste0('IF(AND($D', 2:(nrow(Searches)+101),'="",$E', 2:(nrow(Searches)+101),'=""),"",
             IF(OR($F', 2:(nrow(Searches)+101),'="Yes",$G', 2:(nrow(Searches)+101),'="Yes"),"No",
             IF($D', 2:(nrow(Searches)+101),'="Included","Yes","No")))'),
      dims = wb_dims(2:(nrow(Searches)+101),8)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x = paste0('IF(AND($D', 2:(nrow(Searches)+101),'="",$E', 2:(nrow(Searches)+101),'=""),"",
             IF(OR($F', 2:(nrow(Searches)+101),'="Yes",$G', 2:(nrow(Searches)+101),'="Yes"),"No",
             IF($E', 2:(nrow(Searches)+101),'="Included","Yes","No")))'),
      dims = wb_dims(2:(nrow(Searches)+101),9)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x = paste0(
        'IF(AND(H', 2:(nrow(Searches)+101),'="", I', 2:(nrow(Searches)+101),'=""),
    "",
    IF(OR(H', 2:(nrow(Searches)+101),'="Yes", I', 2:(nrow(Searches)+101),'="Yes"),
    "Yes","No")
    )'
      ),
      dims = wb_dims(2:(nrow(Searches)+101),10)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x = paste0('IF(J', 2:(nrow(Searches)+101),'="","",
             "Reviewer_1: " & IF(FullText_First!F', 2:(nrow(Searches)+101),'="","",FullText_First!F', 2:(nrow(Searches)+101),') & CHAR(10) & 
             "Reviewer_2: " & IF(FullText_Second!F', 2:(nrow(Searches)+101),'="","",FullText_Second!F', 2:(nrow(Searches)+101),'))'),
      dims = wb_dims(2:(nrow(Searches)+101),11)
    )
    DEF$add_formula(
      sheet = "FullText_Summary",
      x = paste0('IF(J', 2:(nrow(Searches)+101),'="","",
             "Reviewer_1: " & IF(FullText_First!G', 2:(nrow(Searches)+101),'="","",FullText_First!G', 2:(nrow(Searches)+101),') & CHAR(10) & 
             "Reviewer_2: " & IF(FullText_Second!G', 2:(nrow(Searches)+101),'="","",FullText_Second!G', 2:(nrow(Searches)+101),'))'),
      dims = wb_dims(2:(nrow(Searches)+101),12)
    )
    DEF$add_data_validation(
      sheet = "FullText_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),13),
      type = "list",
      value = '"Included,Excluded"',
      error_title = "Error",
      error = "Select from one of 'Included' or 'Excluded'. If doubtful, select 'Included'"
    )
    DEF$add_data_validation(
      sheet = "FullText_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),14),
      type = "list",
      value = "Exclusion_List",
      error_title = "Error",
      error = "Select from one of the options from the drop-down menu. If the reason is not in the list, please select 'Other reasons' and provide additional details in the relevant column."
    )
    DEF$add_fill(
      sheet = "FullText_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),c(1:12)),
      color =  wb_color(hex = "#FFFFFFCC"),
      every_nth_row = 2
    )
    DEF$add_conditional_formatting(
      sheet = "FullText_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),10),
      rule = "Yes",
      type = "containsText",
      style = "style_warning"
    )
    DEF$add_conditional_formatting(
      sheet = "FullText_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),10),
      rule = "No",
      type = "containsText",
      style = "style_no_warning"
    )
    DEF$add_fill(
      sheet = "FullText_Summary",
      dims = wb_dims(2:(nrow(Searches)+101),13:15),
      color =  wb_color(hex = "#FFFFCC66"),
      every_nth_row = 2
    )
    DEF$add_fill(
      sheet = "FullText_Summary",
      dims = wb_dims(1:(nrow(Searches)+102),16),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$add_fill(
      sheet = "FullText_Summary",
      dims = wb_dims((nrow(Searches)+102),1:15),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$freeze_pane(
      sheet = "FullText_Summary",
      first_active_row = 2,
      first_active_col = 3
    )
    DEF$protect_worksheet(
      sheet = "FullText_Summary",
      protect = TRUE
    )
    # Data_Extraction_First
    # Most formatting is done with open xlsx - so only the formula, validation and fills are added here
    DEF$add_data(
      sheet = "BehindScenes",
      x = DEF_Design[substr(DEF_Design$variable,1,8) ==
                       'outcome_', c(2,4:6)],
      col_names = FALSE,
      dims = wb_dims(2,4)
    )
    DEF$add_formula(
      sheet = "BehindScenes",
      x = paste0('IFERROR(INDEX($C$2:$C$5,MATCH(E', 2:(length(
        DEF_Design$variable_value[substr(DEF_Design$variable,1,8) ==
                                    'outcome_']
      )+1),',$B$2:$B$5,0)),"")'),
      dims = wb_dims(2,8)
    )
    DEF$add_formula(
      sheet = "BehindScenes",
      x = paste0('IF(FullText_First!H', 2:(nrow(Searches)+101),'="","",FullText_First!H', 2:(nrow(Searches)+101),')'),
      dims = wb_dims(2:(nrow(Searches)+101),9)
    )
    DEF$add_formula(
      sheet = "BehindScenes",
      x= paste0('IF(OR(I', 2:(nrow(Searches)+101),'="",I', 2:(nrow(Searches)+101),'="Excluded"),"",MAX(J$1:J', 1:(nrow(Searches)+100),')+1)'),
      dims = wb_dims(2:(nrow(Searches)+101),10)
    )
    DEF$add_formula(
      sheet = "BehindScenes",
      x = rep(
        'IF(ROW()-1 <= MAX($J:$J),
    INDEX(FullText_First!$A:$A, MATCH(ROW()-1, $J:$J,0)) & "." &  INDEX(FullText_First!$B:$B, MATCH(ROW()-1, $J:$J,0)),
    "")',
        nrow(Searches)+100
      ), 
      dims = wb_dims(2:(nrow(Searches)+101),11)
    )
    DEF$add_formula(
      sheet = "BehindScenes",
      x = paste0('IF(FullText_Second!H', 2:(nrow(Searches)+101),'="","",FullText_Second!H', 2:(nrow(Searches)+101),')'),
      dims = wb_dims(2:(nrow(Searches)+101),12)
    )
    DEF$add_formula(
      sheet = "BehindScenes",
      x= paste0('IF(OR(L', 2:(nrow(Searches)+101),'="",L', 2:(nrow(Searches)+101),'="Excluded"),"",MAX(M$1:M', 1:(nrow(Searches)+100),')+1)'),
      dims = wb_dims(2:(nrow(Searches)+101),13)
    )
    DEF$add_formula(
      sheet = "BehindScenes",
      x = rep(
        'IF(ROW()-1 <= MAX($M:$M),
    INDEX(FullText_Second!$A:$A, MATCH(ROW()-1, $M:$M,0)) & "." &  INDEX(FullText_Second!$B:$B, MATCH(ROW()-1, $M:$M,0)),
    "")',
        nrow(Searches)+100
      ), 
      dims = wb_dims(2:(nrow(Searches)+101),14)
    )
    DEF$add_formula(
      sheet = "BehindScenes",
      x = paste0('IF(FullText_Summary!M', 2:(nrow(Searches)+101),'="","",FullText_Summary!M', 2:(nrow(Searches)+101),')'),
      dims = wb_dims(2:(nrow(Searches)+101),15)
    )
    DEF$add_formula(
      sheet = "BehindScenes",
      x = paste0('IF(OR(O', 2:(nrow(Searches)+101),'="",O', 2:(nrow(Searches)+101),'="Included"),"",MAX(P$1:P', 1:(nrow(Searches)+100),')+1)'),
      dims = wb_dims(2:(nrow(Searches)+101),16)
    )
    column_name <- openxlsx2::int2col(match("outcome_name", Revised_Template$short_name))
    DEF$add_formula(
      sheet = "DataExtractionForm_First",
      x = paste0('IF($',column_name, 5:1004,'="","",INDEX(BehindScenes!$F$2:$F$101,MATCH($',column_name, 5:1004,',BehindScenes!$D$2:$D$101,0)))'),
      dims = wb_dims(5:1004,match("outcome_type_2", Revised_Template$short_name)),
    )
    DEF$add_formula(
      sheet = "DataExtractionForm_First",
      x = paste0('IF($',column_name, 5:1004,'="","",INDEX(BehindScenes!$E$2:$E$101,MATCH($',column_name, 5:1004,',BehindScenes!$D$2:$D$101,0)))'),
      dims = wb_dims(5:1004,match("outcome_type_1", Revised_Template$short_name)),
    )
    DEF$add_formula(
      sheet = "DataExtractionForm_First",
      x = paste0('IF($',column_name, 5:1004,'="","",INDEX(BehindScenes!$H$2:$H$101,MATCH($',column_name, 5:1004,',BehindScenes!$D$2:$D$101,0)))'),
      dims = wb_dims(5:1004,match("outcome_specific_instruction", Revised_Template$short_name)),
    )
    DEF$add_formula(
      sheet = "DataExtractionForm_First",
      x = paste0('IF(',column_name, 5:1004,'="","",',column_name, 5:1004,')'),
      dims = wb_dims(5:1004,match("outcome_name_display", Revised_Template$short_name)),
    )
    # Now for the rob_outcome_level_message: this refers to objective or subjective
    column_name <- openxlsx2::int2col(match("outcome_type_2", Revised_Template$short_name))
    DEF$add_formula(
      sheet = "DataExtractionForm_First",
      x = paste0('IF(',column_name, 5:1004,'="","",',column_name, 5:1004,')'),
      dims = wb_dims(5:1004,match("rob_outcome_level_message", Revised_Template$short_name)),
    )
    DEF$add_data_validation(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(5:1004,match("Name of the outcome", Revised_Template$row_2_column_name)),
      type = "list",
      value = 'Outcomes',
      error_title = "Error",
      error = "Select from one of the outcomes in the list."
    )
    DEF$add_data_validation(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(5:1004,match("effect_measure_name", Revised_Template$short_name)),
      type = "list",
      value = 'EffectMeasures_List',
      error_title = "Error",
      error = "Select from one of the effect measures in the list."
    )
    # Find the first locations of first row (to start merge)
    # First row
    FirstRow <- Revised_Template$row_1_section_name[!is.na(Revised_Template$row_1_section_name)]
    FirstRow <- data.frame(first_row_text = FirstRow[FirstRow != ""])
    FirstRow$start_column <- match(FirstRow$first_row_text,
                                   Revised_Template$row_1_section_name
    )
    FirstRow$end_column <- c(FirstRow$start_column[2:nrow(FirstRow)]-1, nrow(Revised_Template))
    # Second row
    SecondRow <- data.frame(Revised_Template[
      !is.na(Revised_Template$row_2_column_name) & 
        (Revised_Template$row_2_column_name != "") & 
        (
          !is.na(match(Revised_Template$section,
                       c("participant_characteristics_2", 
                         "rob2","rob2_cluster", "rob2_cross_over","robins_i",
                         "intervention" 
                       )
          )) |
            !is.na(match(Revised_Template$sub_section,
                         c("intervention_participant_flow_each_outcome",
                           "outcome_data_for_analysis_1", "outcome_data_for_analysis_additional_1"
                         )
            ))
        )
      , c("section", "sub_section", "row_2_column_name")])
    colnames(SecondRow) <- c("section", "sub_section", "second_row_text")
    SecondRow$start_column <- match(
      paste0(SecondRow$sub_section, "%_%", SecondRow$second_row_text),
      paste0(Revised_Template$sub_section, "%_%", Revised_Template$row_2_column_name)
    )
    SecondRow$end_column[
      !is.na(match(SecondRow$section,
                   c("rob2","rob2_cluster", "rob2_cross_over","robins_i")
      ))
    ] <- 
      SecondRow$start_column[
        !is.na(match(SecondRow$section,
                     c("rob2","rob2_cluster", "rob2_cross_over","robins_i")
        ))
      ] + 2
    SecondRow$end_column[
      is.na(SecondRow$end_column)
    ] <- SecondRow$start_column[
      is.na(SecondRow$end_column)
    ] + 1
    DEF$add_formula(
      sheet = "DataExtractionForm_First", 
      x = create_hyperlink(
        sheet = "DataExtractionForm_First",
        row = 1,
        col = FirstRow$start_column,
        text = FirstRow$first_row_text
      ), 
      dims = wb_dims(5,1)
    )
    DEF$add_conditional_formatting(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(5:1004,
                     match("outcome_type_2", Revised_Template$short_name)
      ),
      type = "notContainsBlanks",
      style = "style_greyed_out"
    )
    DEF$add_conditional_formatting(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(5:1004,
                     match("outcome_type_1", Revised_Template$short_name)
      ),
      type = "notContainsBlanks",
      style = "style_greyed_out"
    )
    DEF$add_conditional_formatting(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(5:1004,
                     match("outcome_specific_instruction", Revised_Template$short_name)
      ),
      type = "notContainsBlanks",
      style = "style_greyed_out"
    )
    DEF$add_conditional_formatting(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(5:1004,
                     match("rob_outcome_level_message", Revised_Template$short_name)
      ),
      type = "notContainsBlanks",
      style = "style_greyed_out"
    )
    DEF$add_conditional_formatting(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(5:1004,
                     match("outcome_name_display", Revised_Template$short_name)
      ),
      type = "notContainsBlanks",
      style = "style_greyed_out"
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_First", 
      dims = wb_dims(1,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FF51154A")
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_First", 
      dims = wb_dims(2,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FF782170")
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_First", 
      dims = wb_dims(3,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FFCC00CC")
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_First", 
      dims = wb_dims(4,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FFD86DCD")
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_First", 
      dims = wb_dims(5:1004,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FFFFCCFF"),
      every_nth_row = 2
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(1:1005,(FirstRow$end_column[nrow(FirstRow)]+1)),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(1005,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$set_col_widths(
      sheet = "DataExtractionForm_First", 
      cols = (FirstRow$end_column[nrow(FirstRow)]+1),
      widths = 30
    )
    DEF$freeze_pane(
      sheet = "DataExtractionForm_First",
      first_active_row = 5,
      first_active_col = 3
    )
    DEF$protect_worksheet(
      sheet = "DataExtractionForm_First",
      protect = TRUE
    )
    validation_list <- list()
    for (i in 1:nrow(Revised_Template)) {
      if (trimws(Revised_Template$validation[i]) != "") {
        if (
          (trimws(Revised_Template$validation[i]) == "decimal") |
          (trimws(Revised_Template$validation[i]) == "whole")
        ) {
          validation_list[[i]] <- trimws(Revised_Template$validation[i])
          DEF$add_data_validation(
            sheet = "DataExtractionForm_First",
            dims = wb_dims(5:1004,i),
            type = trimws(Revised_Template$validation[i]),
            operator = "between",
            value = c(-100000000000000,100000000000000),
            error_title = "Error",
            error = paste0("This fields allows only a ", trimws(Revised_Template$validation[i]), " number.") 
          )
        } else {
          validation_list[[i]] <- str_split(
            trimws(Revised_Template$validation[i]),
            "%_%"
          )[[1]]
          if (validation_list[[i]][1] == "list"){
            DEF$add_data_validation(
              sheet = "DataExtractionForm_First",
              dims = wb_dims(5:1004,i),
              type = "list",
              value = paste0('"',
                             str_replace_all(validation_list[[i]][2],", ",","),
                             '"'
              ),
              error_title = "Error",
              error = "Select from one of the options from the drop-down menu."
            )
          } else if (
            (validation_list[[i]][1] == "decimal") |
            (validation_list[[i]][1] == "whole")
          ) {
            if (length(validation_list[[i]]) == 3) {
              DEF$add_data_validation(
                sheet = "DataExtractionForm_First",
                dims = wb_dims(5:1004,i),
                type = validation_list[[i]][1],
                operator = validation_list[[i]][2],
                value = validation_list[[i]][3],
                error_title = "Error",
                error = paste0("This fields allows only a ", validation_list[[i]][1], " number ",
                               validation_list[[i]][2], " ", validation_list[[i]][3]
                ) 
              )
            } else if (length(validation_list[[i]]) == 4) {
              DEF$add_data_validation(
                sheet = "DataExtractionForm_First",
                dims = wb_dims(5:1004,i),
                type = validation_list[[i]][1],
                operator = validation_list[[i]][2],
                value = c(validation_list[[i]][3],validation_list[[i]][4]),
                error_title = "Error",
                error = paste0("This fields allows only a ", validation_list[[i]][1], " number ",
                               validation_list[[i]][2], " ", validation_list[[i]][3], " and ",
                               validation_list[[i]][4]
                ) 
              )
            }
          }
        }
      }
    }
    # DataExtractionForm_Second
    DEF$clone_worksheet(
      old = "DataExtractionForm_First",
      new = "DataExtractionForm_Second"
    )
    DEF$worksheets[[match("DataExtractionForm_Second", DEF$get_sheet_names())]]$sheetPr <- 
      "<sheetPr><tabColor rgb=\"FF002060\"/></sheetPr>"
    DEF$add_formula(
      sheet = "DataExtractionForm_Second", 
      x = create_hyperlink(
        sheet = "DataExtractionForm_Second",
        row = 1,
        col = FirstRow$start_column,
        text = FirstRow$first_row_text
      ), 
      dims = wb_dims(5,1)
    )
    DEF$add_data_validation(
      sheet = "DataExtractionForm_First",
      dims = wb_dims(5:1004,match("Record ID", Revised_Template$row_2_column_name)),
      type = "list",
      value = 'Included_First',
      error_title = "Error",
      error = "Select from one of the records in the list. Only records selected as 'Included' in FullText_First will be included in this list."
    )
    DEF$add_data_validation(
      sheet = "DataExtractionForm_Second",
      dims = wb_dims(5:1004,match("Record ID", Revised_Template$row_2_column_name)),
      type = "list",
      value = 'Included_Second',
      error_title = "Error",
      error = "Select from one of the records in the list. Only records selected as 'Included' in FullText_Second will be included in this list."
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_Second", 
      dims = wb_dims(1,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FF002060")
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_Second", 
      dims = wb_dims(2,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FF215C98")
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_Second", 
      dims = wb_dims(3,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FF4D93D9")
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_Second", 
      dims = wb_dims(4,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FF61CBF3")
    )
    DEF$add_fill(
      sheet = "DataExtractionForm_Second", 
      dims = wb_dims(5:1004,1:FirstRow$end_column[nrow(FirstRow)]),
      color =  wb_color(hex = "#FFCAEDFB"),
      every_nth_row = 2
    )
    
    # Excluded
    DEF$add_formula(
      sheet = "Excluded",
      x = rep(
        'IF(ROW()-1 <= MAX(BehindScenes!$P:$P),
             INDEX(FullText_Summary!A:A,
             MATCH(ROW()-1, BehindScenes!$P:$P,0)),"")',
        nrow(Searches)+100
      ), 
      dims = wb_dims(2:(nrow(Searches)+101),1)
    )
    DEF$add_formula(
      sheet = "Excluded",
      x = rep(
        'IF(ROW()-1 <= MAX(BehindScenes!$P:$P),
             INDEX(FullText_Summary!B:B,
             MATCH(ROW()-1, BehindScenes!$P:$P,0)),"")',
        nrow(Searches)+100
      ), 
      dims = wb_dims(2:(nrow(Searches)+101),2)
    )
    DEF$add_formula(
      sheet = "Excluded",
      x = rep(
        'IF(ROW()-1 <= MAX(BehindScenes!$P:$P),
             INDEX(FullText_Summary!C:C,
             MATCH(ROW()-1, BehindScenes!$P:$P,0)),"")',
        nrow(Searches)+100
      ),
      dims = wb_dims(2:(nrow(Searches)+101),3)
    )
    DEF$add_formula(
      sheet = "Excluded",
      x= paste0('IF($A', 2:(nrow(Searches)+101),'="","",
            IF(INDEX(FullText_Summary!N:N,
            MATCH($A', 2:(nrow(Searches)+101),',FullText_Summary!$A:$A,0))="","No reason provided",
            INDEX(FullText_Summary!N:N,
            MATCH($A', 2:(nrow(Searches)+101),',FullText_Summary!$A:$A,0))))'),
      dims = wb_dims(2:(nrow(Searches)+101),4)
    )
    DEF$add_formula(
      sheet = "Excluded",
      x= paste0('IF($A', 2:(nrow(Searches)+101),'="","",
            IF(INDEX(FullText_Summary!O:O,
            MATCH($A', 2:(nrow(Searches)+101),',FullText_Summary!$A:$A,0))="","",
            INDEX(FullText_Summary!O:O,
            MATCH($A', 2:(nrow(Searches)+101),',FullText_Summary!$A:$A,0))))'),
      dims = wb_dims(2:(nrow(Searches)+101),5)
    )
    DEF$add_fill(
      sheet = "Excluded",
      dims = wb_dims(2:(nrow(Searches)+101),1:5),
      color =  wb_color(hex = "#FFFFFFCC"),
      every_nth_row = 2
    )
    DEF$add_fill(
      sheet = "Excluded",
      dims = wb_dims(1:(nrow(Searches)+102),6),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$add_fill(
      sheet = "Excluded",
      dims = wb_dims((nrow(Searches)+102),1:5),
      color =  wb_color(hex = "#FFF2F2F2")
    )
    DEF$freeze_pane(
      sheet = "Excluded",
      first_active_row = 2,
      first_active_col = 3
    )
    DEF$protect_worksheet(
      sheet = "Excluded",
      protect = TRUE
    )
    # Hide Behind Scenes
    DEF$set_sheet_visibility(match("BehindScenes", DEF$get_sheet_names()), "hidden")  
    # Save workbook
    DEF$set_order(
      match(c("Instructions", 
              "Screening_First", "Screening_Second","Screening_Summary",
              "FullText_First", "FullText_Second", "FullText_Summary",
              "DataExtractionForm_First", "DataExtractionForm_Second",
              "Calculators", "Calculations_Co_reviewer",
              "Excluded",
              "BehindScenes", "DEF_Design", "Revised_Template", "Reference_flow"
      ), 
      DEF$get_sheet_names()
      )
    )
    DEF$save(file = paste0(StorageFolder,"/DataExtractionForm.xlsx"), overwrite = TRUE)
    incProgress(amount = 0.2, detail = "Phase 1 complete. Commencing Phase 2, formatting of form: this will take a while!")
    # Format for all sheets other than DataExtractionForm_First and DataExtractionForm_Second
    DEF_2 <- loadWorkbook(paste0(StorageFolder,"/DataExtractionForm.xlsx"))
    addStyle(
      wb = DEF_2,
      sheet = "Instructions",
      style = createStyle(
        wrapText = TRUE
      ),
      rows = 2:(nrow(instructions)+length(
        DEF_Design$additional_text[substr(DEF_Design$variable,1,8) ==
                                     'outcome_'
        ]
      )),
      cols = 1,
      gridExpand = TRUE,
      stack = TRUE
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "Instructions",
      rows =  ((nrow(instructions)+length(
        DEF_Design$additional_text[substr(DEF_Design$variable,1,8) ==
                                     'outcome_'
        ]
      ))+1),
      heights = 400
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_First",
      style = createStyle(
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 2:(nrow(Searches)+1),
      cols = c(2:3),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_First",
      style = createStyle(
        wrapText = TRUE,
        locked = FALSE,
        hidden = FALSE
      ),
      rows = (nrow(Searches)+2):(nrow(Searches)+101),
      cols = c(2:3),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_First",
      style = createStyle(
        locked = FALSE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(4:5),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_Second",
      style = createStyle(
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(2:3),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_Second",
      style = createStyle(
        locked = FALSE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(4:5),
      gridExpand = TRUE,
      stack = TRUE
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "Screening_First",
      rows =  (nrow(Searches)+102),
      heights = 400
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "Screening_Second",
      rows =  (nrow(Searches)+102),
      heights = 400
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_Summary",
      style = createStyle(
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = 1:11,
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_Summary",
      style = createStyle(
        locked = FALSE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = 12,
      gridExpand = TRUE,
      stack = TRUE
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "Screening_Summary",
      rows =  (nrow(Searches)+102),
      heights = 400
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_First",
      style = createStyle(
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(1:4,8),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_First",
      style = createStyle(
        wrapText = TRUE,
        locked = FALSE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(5:7),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_Second",
      style = createStyle(
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(1:4,8),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_Second",
      style = createStyle(
        wrapText = TRUE,
        locked = FALSE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(5:7),
      gridExpand = TRUE,
      stack = TRUE
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "FullText_First",
      rows =  (nrow(Searches)+102),
      heights = 400
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "FullText_Second",
      rows =  (nrow(Searches)+102),
      heights = 400
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_Summary",
      style = createStyle(
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(1:12),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_Summary",
      style = createStyle(
        wrapText = TRUE,
        locked = FALSE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(13:15),
      gridExpand = TRUE,
      stack = TRUE
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "FullText_Summary",
      rows = 2:(nrow(Searches)+101),
      heights = 57.6
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "FullText_Summary",
      rows =  (nrow(Searches)+102),
      heights = 400
    )
    addStyle(
      wb = DEF_2,
      sheet = "Excluded",
      style = createStyle(
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 2:(nrow(Searches)+101),
      cols = c(1:5),
      gridExpand = TRUE,
      stack = TRUE
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "Excluded",
      rows =  (nrow(Searches)+102),
      heights = 400
    )
    # Create borders
    incProgress(amount = 0.1, detail = "Phase 2: Creating borders")
    addStyle(
      wb = DEF_2,
      sheet = "Instructions",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,2,(nrow(instructions)+length(
        DEF_Design$additional_text[substr(DEF_Design$variable,1,8) ==
                                     'outcome_'
        ]
      )+1)),
      cols = c(1),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Instructions",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:(nrow(instructions)+length(
        DEF_Design$additional_text[substr(DEF_Design$variable,1,8) ==
                                     'outcome_'
        ]
      ))),
      cols = c(1:2),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_First",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,2,(nrow(Searches)+101+1)),
      cols = c(1:5),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_First",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:(nrow(Searches)+101)),
      cols = c(1,6),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_Second",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,2,(nrow(Searches)+101+1)),
      cols = c(1:5),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_Second",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:(nrow(Searches)+101)),
      cols = c(1,6),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_Summary",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,2,(nrow(Searches)+101+1)),
      cols = c(1:12),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Screening_Summary",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:(nrow(Searches)+101)),
      cols = c(1,13),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_First",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,2,(nrow(Searches)+101+1)),
      cols = c(1:8),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_First",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:(nrow(Searches)+101)),
      cols = c(1,9),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_Second",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,2,(nrow(Searches)+101+1)),
      cols = c(1:8),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_Second",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:(nrow(Searches)+101)),
      cols = c(1,9),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_Summary",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,2,(nrow(Searches)+101+1)),
      cols = c(1:15),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "FullText_Summary",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:(nrow(Searches)+101)),
      cols = c(1,16),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      style = createStyle(
        border = c("left"),
        borderStyle = "thin"
      ),
      rows = c(1:1004),
      c(SecondRow$start_column),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      style = createStyle(
        border = c("left"),
        borderStyle = "thin"
      ),
      rows = c(1:1004),
      c(SecondRow$start_column),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,5,(1004+1)),
      cols = c(1:FirstRow$end_column[nrow(FirstRow)]),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:1004),
      c(FirstRow$start_column, (FirstRow$end_column[nrow(FirstRow)]+1)),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,5,(1004+1)),
      cols = c(1:FirstRow$end_column[nrow(FirstRow)]),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:1004),
      c(FirstRow$start_column, (FirstRow$end_column[nrow(FirstRow)]+1)),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Excluded",
      style = createStyle(
        border = c("top"),
        borderStyle = "thick"
      ),
      rows = c(1,2,(nrow(Searches)+101+1)),
      cols = c(1:5),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "Excluded",
      style = createStyle(
        border = c("left"),
        borderStyle = "thick"
      ),
      rows = c(1:(nrow(Searches)+101)),
      cols = c(1,6),
      gridExpand = TRUE,
      stack = TRUE
    )
    # DataExtractionForm_First and DataExtractionForm_Second
    incProgress(amount = 0.2, detail = "Phase 2: Creating headings and merging cells: this will take a while!")
    writeData(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      x = DEF_Text,
      startCol = 1,
      startRow = 1,
      colNames = FALSE,
      rowNames = FALSE
    )
    writeData(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      x = DEF_Text,
      startCol = 1,
      startRow = 1,
      colNames = FALSE,
      rowNames = FALSE
    )
    for (i in 1:nrow(FirstRow)) {
      mergeCells(
        DEF_2,
        "DataExtractionForm_First",
        rows = 1:1,
        cols = c(FirstRow$start_column[i], FirstRow$end_column[i])
      )
      mergeCells(
        DEF_2,
        "DataExtractionForm_Second",
        rows = 1:1,
        cols = c(FirstRow$start_column[i], FirstRow$end_column[i])
      )
    }
    for (i in 1:nrow(SecondRow)) {
      mergeCells(
        DEF_2,
        "DataExtractionForm_First",
        rows = 2:2,
        cols = c(SecondRow$start_column[i], SecondRow$end_column[i])
      )
      mergeCells(
        DEF_2,
        "DataExtractionForm_First",
        rows = 3:3,
        cols = c(SecondRow$start_column[i], SecondRow$end_column[i])
      )
      mergeCells(
        DEF_2,
        "DataExtractionForm_Second",
        rows = 2:2,
        cols = c(SecondRow$start_column[i], SecondRow$end_column[i])
      )
      mergeCells(
        DEF_2,
        "DataExtractionForm_Second",
        rows = 3:3,
        cols = c(SecondRow$start_column[i], SecondRow$end_column[i])
      )
    }
    setColWidths(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      cols = c(1,2),
      widths = c(50,30),
      hidden = rep(FALSE, 2),
      ignoreMergedCells = FALSE
    )
    setColWidths(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      cols = c(1,2),
      widths = c(50,30),
      hidden = rep(FALSE, 2),
      ignoreMergedCells = FALSE
    )
    options("openxlsx.minWidth" = 14)
    options("openxlsx.maxWidth" = 70)
    setColWidths(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      cols = 3:FirstRow$end_column[nrow(FirstRow)],
      widths = "auto",
      hidden = rep(FALSE, length(3:FirstRow$end_column[nrow(FirstRow)])),
      ignoreMergedCells = FALSE
    )
    setColWidths(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      cols = 3:FirstRow$end_column[nrow(FirstRow)],
      widths = "auto",
      hidden = rep(FALSE, length(3:FirstRow$end_column[nrow(FirstRow)])),
      ignoreMergedCells = FALSE
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      rows = 1,
      heights = 20
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      rows = 2:3,
      heights = 50
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      rows = 1,
      heights = 20
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      rows = 2:3,
      heights = 50
    )
    rows3_4_merge = as.vector(1:nrow(Revised_Template))[Revised_Template$row_4_intervention == ""]
    for (i in 1:length(rows3_4_merge)){
      removeCellMerge(
        DEF_2,
        "DataExtractionForm_First",
        rows = 3:4,
        cols = rows3_4_merge[i]
      )
      mergeCells(
        DEF_2,
        "DataExtractionForm_First",
        rows = 3:4,
        cols = rows3_4_merge[i]
      )
      removeCellMerge(
        DEF_2,
        "DataExtractionForm_Second",
        rows = 3:4,
        cols = rows3_4_merge[i]
      )
      mergeCells(
        DEF_2,
        "DataExtractionForm_Second",
        rows = 3:4,
        cols = rows3_4_merge[i]
      )
    }
    rob_widths = as.vector(1:nrow(Revised_Template))[
      Revised_Template$row_4_intervention == "Classification"
    ]
    for (i in 1:length(rob_widths)){
      setColWidths(
        DEF_2,
        "DataExtractionForm_First",
        widths = 30,
        cols = c(rob_widths[i], rob_widths[i]+1,rob_widths[i]+2) 
      )
      setColWidths(
        DEF_2,
        "DataExtractionForm_Second",
        widths = 30,
        cols = c(rob_widths[i], rob_widths[i]+1,rob_widths[i]+2) 
      )
    }
    intervention_widths = as.vector(1:nrow(Revised_Template))[
      Revised_Template$row_4_intervention == DEF_Design$variable_value[match("intervention_1", DEF_Design$variable)]
    ]
    for (i in 1:length(intervention_widths)){
      setColWidths(
        DEF_2,
        "DataExtractionForm_First",
        widths = 50,
        cols = c(intervention_widths[i],intervention_widths[i]+1) 
      )
      setColWidths(
        DEF_2,
        "DataExtractionForm_Second",
        widths = 50,
        cols = c(intervention_widths[i],intervention_widths[i]+1) 
      )
    }
    removeCellMerge(
      DEF_2,
      "DataExtractionForm_First",
      rows = 1:4,
      cols = 1
    )
    mergeCells(
      DEF_2,
      "DataExtractionForm_First",
      rows = 1:4,
      cols = 1
    )
    removeCellMerge(
      DEF_2,
      "DataExtractionForm_First",
      rows = 1:4,
      cols = match("rob_outcome_level_message", Revised_Template$short_name)
    )
    mergeCells(
      DEF_2,
      "DataExtractionForm_First",
      rows = 2:4,
      cols = match("rob_outcome_level_message", Revised_Template$short_name)
    )
    removeCellMerge(
      DEF_2,
      "DataExtractionForm_Second",
      rows = 1:4,
      cols = 1
    )
    mergeCells(
      DEF_2,
      "DataExtractionForm_Second",
      rows = 1:4,
      cols = 1
    )
    removeCellMerge(
      DEF_2,
      "DataExtractionForm_Second",
      rows = 1:4,
      cols = match("rob_outcome_level_message", Revised_Template$short_name)
    )
    mergeCells(
      DEF_2,
      "DataExtractionForm_Second",
      rows = 2:4,
      cols = match("rob_outcome_level_message", Revised_Template$short_name)
    )
    setColWidths(
      DEF_2,
      "DataExtractionForm_First",
      widths = 30,
      cols = match("Record ID", Revised_Template$row_2_column_name) 
    )
    setColWidths(
      DEF_2,
      "DataExtractionForm_Second",
      widths = 30,
      cols = match("Record ID", Revised_Template$row_2_column_name) 
    )
    setColWidths(
      DEF_2,
      "DataExtractionForm_First",
      widths = 65,
      cols = match("outcome_specific_instruction", Revised_Template$short_name) 
    )
    setColWidths(
      DEF_2,
      "DataExtractionForm_Second",
      widths = 65,
      cols = match("outcome_specific_instruction", Revised_Template$short_name) 
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      style = createStyle(
        fontSize = 13,
        fontColour = "white",
        textDecoration = "bold",
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 1:2,
      cols = c(1:FirstRow$end_column[nrow(FirstRow)]),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      style = createStyle(
        fontSize = 12,
        fontColour = "white",
        textDecoration = "bold",
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 3,
      cols = c(1:FirstRow$end_column[nrow(FirstRow)]),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      style = createStyle(
        fontSize = 12,
        textDecoration = "bold",
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 4,
      cols = c(1:FirstRow$end_column[nrow(FirstRow)]),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      style = createStyle(
        fontSize = 13,
        fontColour = "white",
        textDecoration = "bold",
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 1:2,
      cols = c(1:FirstRow$end_column[nrow(FirstRow)]),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      style = createStyle(
        fontSize = 12,
        fontColour = "white",
        textDecoration = "bold",
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 3,
      cols = c(1:FirstRow$end_column[nrow(FirstRow)]),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      style = createStyle(
        fontSize = 12,
        textDecoration = "bold",
        wrapText = TRUE,
        hidden = TRUE
      ),
      rows = 4,
      cols = c(1:FirstRow$end_column[nrow(FirstRow)]),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      style = createStyle(
        wrapText = TRUE
      ),
      rows = 5:(4+nrow(FirstRow)),
      cols = 1,
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      style = createStyle(
        wrapText = TRUE
      ),
      rows = 5:(4+nrow(FirstRow)),
      cols = 1,
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      style = createStyle(
        locked = FALSE
      ),
      rows = 5:1004,
      cols = 2:FirstRow$end_column[nrow(FirstRow)],
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      style = createStyle(
        locked = FALSE
      ),
      rows = 5:1004,
      cols = 2:FirstRow$end_column[nrow(FirstRow)],
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      style = createStyle(
        locked = TRUE,
        hidden = TRUE
      ),
      rows = 5:1004,
      cols = match(c("outcome_type_2","outcome_type_1","outcome_specific_instruction","outcome_name_display", "rob_outcome_level_message"), Revised_Template$short_name),
      gridExpand = TRUE,
      stack = TRUE
    )
    addStyle(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      style = createStyle(
        locked = TRUE,
        hidden = TRUE
      ),
      rows = 5:1004,
      cols = match(c("outcome_type_2","outcome_type_1","outcome_specific_instruction"), Revised_Template$short_name),
      gridExpand = TRUE,
      stack = TRUE
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "DataExtractionForm_First",
      rows =  1005,
      heights = 400
    )
    setRowHeights(
      wb = DEF_2,
      sheet = "DataExtractionForm_Second",
      rows =  1005,
      heights = 400
    )
    # Save
    incProgress(amount = 0.2, detail = "Phase 2: Creating the file for download. This is the final step!")
    protectWorkbook(
      wb = DEF_2,
      protect = TRUE
    )
    saveWorkbook(
      wb = DEF_2,
      file = paste0(StorageFolder,"/DataExtractionForm.xlsx"),
      overwrite = TRUE,
      returnValue = FALSE
    )
    # Return output
    return(DEF_2)
  })
}
# Functions for extracting data from plots ####
# Calculation of lnHR and its SE from KM curve
# Tierney, J.F., Stewart, L.A., Ghersi, D. et al. Practical methods for incorporating summary time-to-event data into meta-analysis. Trials 8, 16 (2007). 
# https://doi.org/10.1186/1745-6215-8-16

create.numeric.inputs.groups <- function(x){
  y <- ""
  for (i in 1:x) {
    y <- paste0(y,
                ifelse(i >1, "; ", ""),
                'output$PlotExtract_KM_Group_Numbers_', i, '_UI<- renderUI(',
                'numericInput("PlotExtract_KM_Group_Numbers_',i,'","Enter the number of participants in group ', i, ': "',
                ', min = 2, value = NA',
                ')',
                ')'
    )
  }
  return(y)
}
remove.numeric.inputs.groups <- function(x){
  y <- ""
  for (i in 1:x) {
    y <- paste0(y,
                ifelse(i >1, "; ", ""),
                'output$PlotExtract_KM_Group_Numbers_', i, '_UI<- NULL'
    )
  }
  return(y)
}
cbind.missing <- function(x) {
  # upto 4 level of lists
  y1 <- list()
  column_names <- vector()
  for (i in 1:length(x)){
    if (is.list(x[[i]])){
      for (j in 1:length(x[[i]])){
        y1[[length(y1)+1]] <- x[[i]][[j]]
      }
      column_names <- c(column_names, names(x[[i]]))
    } else {
      y1[[length(y1)+1]] <- x[[i]]
      column_names <- c(column_names, names(x[i]))
    }
  }
  names(y1) <- column_names
  column_names <- vector()
  y2 <- list()
  for (i in 1:length(y1)){
    if (is.list(y1[[i]])){
      for (j in 1:length(y1[[i]])){
        y2[[length(y2)+1]] <- y1[[i]][[j]]
      }
      column_names <- c(column_names, names(y1[[i]]))
    } else {
      y2[[length(y2)+1]] <- y1[[i]]
      column_names <- c(column_names, names(y1[i]))
    }
  }
  names(y2) <- column_names
  column_names <- vector()
  y3 <- list()
  for (i in 1:length(y2)){
    if (is.list(y2[[i]])){
      for (j in 1:length(y2[[i]])){
        y3[[length(y3)+1]] <- y2[[i]][[j]]
      }
      column_names <- c(column_names, names(y2[[i]]))
    } else {
      y3[[length(y3)+1]] <- y2[[i]]
      column_names <- c(column_names, names(y2[i]))
    }
  }
  names(y3) <- column_names
  column_names <- vector()
  y4 <- list()
  for (i in 1:length(y3)){
    if (is.list(y3[[i]])){
      for (j in 1:length(y3[[i]])){
        y4[[length(y4)+1]] <- y3[[i]][[j]]
      }
      column_names <- c(column_names, names(y3[[i]]))
    } else {
      y4[[length(y4)+1]] <- y3[[i]]
      column_names <- c(column_names, names(y3[i]))
    }
  }
  z <- vector()
  for (i in 1:length(y4)){
    z <- c(z, length(y4[[i]]))
  }
  z <- max(z)
  for (i in 1:length(y4)){
    y4[[i]] <- c(y4[[i]], rep(NA, (z-length(y4[[i]]))))
  }
  y4 <- data.frame(y4)
  colnames(y4) <- column_names
  return(y4)
}
values.to.pixel <- function(
    x_value, 
    x_min_pixel, x_max_pixel,
    x_min_value, x_max_value)
{
  uniroot(function (
    pixel, 
    x_min_pixel, x_max_pixel,
    x_min_value, x_max_value,
    x_value
  ) 
  {(((pixel - x_min_pixel)/(x_max_pixel - x_min_pixel)) * (x_max_value - x_min_value) +
      + x_min_value) - x_value
  }, 
  c(x_min_pixel, x_max_pixel),
  x_value = x_value,
  x_min_pixel = x_min_pixel,
  x_max_pixel = x_max_pixel,
  x_min_value = x_min_value,
  x_max_value = x_max_value
  )$root
}
check.ascending.descending <- function(x) {
  y <- sort(x)
  z <- sort(x, decreasing = TRUE)
  if (identical(x, y)){
    "ascending"
  } else if (identical(x,z)) {
    "descending"
  } else {
    "no order"
  }
}
KM_min_max_analysis.date <- function(x, units) {
  analysis.date = as.Date(x[1])
  first.patient.recruitment = as.Date(x[2])
  last.patient.recruitment = as.Date(x[3])
  y = as.numeric(analysis.date - last.patient.recruitment)
  if (y < 0){
    y <- 0
  }
  z = as.numeric(analysis.date - first.patient.recruitment)
  if (z < 0){
    z <- 0
  }
  if (missing(units)){
    units <- "months"
  }
  if (units == "days") {
    min.follow_up <- y
    max.follow_up <- z
  } else if (units == "months") {
    min.follow_up <- y*12/365
    max.follow_up <- z*12/365
  } else if (units == "years") {
    min.follow_up <- y/365
    max.follow_up <- z/365
  }
  c(min.follow_up,max.follow_up)
}
KM_min_max_submission.date <- function(x, units) {
  submission.date = as.Date(x[1])
  analysis.date = submission.date - 365/2
  first.patient.recruitment = as.Date(x[2])
  last.patient.recruitment = as.Date(x[3])
  y = as.numeric(analysis.date - last.patient.recruitment)
  if (y < 0){
    y <- 0
  }
  z = as.numeric(analysis.date - first.patient.recruitment)
  if (missing(units)){
    units <- "months"
  }
  if (z < 0){
    z <- 0
  }
  if (units == "days") {
    min.follow_up <- y
    max.follow_up <- z
  } else if (units == "months") {
    min.follow_up <- y*12/365
    max.follow_up <- z*12/365
  } else if (units == "years") {
    min.follow_up <- y/365
    max.follow_up <- z/365
  }
  c(min.follow_up,max.follow_up)
}
KM_Table <- function(points_values, groups, KM_TimePoints, percent) {
  # First three rows relate to obtaining the values
  # The last two rows relate to minimum and maximum follow-up, but not if the values are skipped
  if (length(points_values) > (3 + (groups*length(KM_TimePoints)))){
    min.follow_up <- points_values[(length(points_values)-1)]
    max.follow_up <- points_values[length(points_values)]
  } else {
    min.follow_up <- 0
    max.follow_up <- max(KM_TimePoints)
  }
  points_values <- points_values[4:length(points_values)]
  points_values <- points_values[1:(groups*length(KM_TimePoints))]
  if (missing(percent)) {
    percent <- TRUE
  }
  if (percent == FALSE){
    points_values <- points_values * 100
  }
  x <- list()
  for (i in 1:groups) {
    x[[i]] <- points_values[(1:length(KM_TimePoints)) + (i-1)*length(KM_TimePoints)]
    if (check.ascending.descending(x[[i]]) == "ascending"){
      x[[i]] <- 100 - x[[i]]
    }
    x[[i]] <- c(100, x[[i]])
  }
  names(x) <- paste0("event.free.prop.group.",1:groups)
  y <- list(KM_DataTable = x,
            KM_TimePoints = c(0,KM_TimePoints),
            min.follow_up = min.follow_up,
            max.follow_up = max.follow_up)
}

KM_lnHR <- function(KM_DataTable, KM_TimePoints, min.follow_up, max.follow_up, n.participants) {
  KM_Calculations <- list()
  min.Survival_Proportions <- list()
  for (i in 1:(length(KM_DataTable)-1)) {
    KM_Calculations[[i]] <- cbind(
      time = KM_TimePoints, 
      prop.event_free_intervention = KM_DataTable[[i]],
      n.event_free_intervention = rep(NA, length(KM_DataTable[[i]])),
      n.at.risk_intervention = rep(NA, length(KM_DataTable[[i]])),
      n.events_intervention = rep(NA, length(KM_DataTable[[i]])),
      n.censored_intervention = rep(NA, length(KM_DataTable[[i]])),
      prop.event_free_control= KM_DataTable[[length(KM_DataTable)]],
      n.event_free_control = rep(NA, length(KM_DataTable[[length(KM_DataTable)]])),
      n.at.risk_control = rep(NA, length(KM_DataTable[[length(KM_DataTable)]])),
      n.events_control = rep(NA, length(KM_DataTable[[length(KM_DataTable)]])),
      n.censored_control = rep(NA, length(KM_DataTable[[length(KM_DataTable)]])),
      ln.hr.t= rep(NA, length(KM_DataTable[[length(KM_DataTable)]])),
      inverse.v.t = rep(NA, length(KM_DataTable[[length(KM_DataTable)]])),
      o_e.t = rep(NA, length(KM_DataTable[[length(KM_DataTable)]])),
      v.t = rep(NA, length(KM_DataTable[[length(KM_DataTable)]]))
    )
    if (
      (length(KM_TimePoints) == length(KM_DataTable[[i]])) &
      (length(KM_DataTable[[i]]) == length(KM_DataTable[[1]]))
    ){
      if ((check.ascending.descending(KM_Calculations[[i]][,1]) == "ascending") &
          (check.ascending.descending(KM_Calculations[[i]][,2]) == "descending") & 
          (check.ascending.descending(KM_Calculations[[i]][,7]) == "descending")
      ) {
        KM_File <- data.frame(KM_Calculations[[i]])
        min.Survival_Proportions[[i]] <- c(min(KM_DataTable[[i]]), min(KM_DataTable[[length(KM_DataTable)]]))
        for (j in 1:nrow(KM_File)) {
          if (j == 1) {
            KM_File$n.event_free_intervention[j] <- n.participants[i]
            KM_File$n.at.risk_intervention[j] <- KM_File$n.event_free_intervention[j]
            KM_File$n.events_intervention[j] <- ifelse(
              (
                (KM_File$prop.event_free_intervention[j] == KM_File$prop.event_free_intervention[(j+1)]) | 
                  (KM_File$prop.event_free_intervention[j] == min.Survival_Proportions[[i]][1])
              ), 0.000001, 
              KM_File$n.at.risk_intervention[j] * 
                ((KM_File$prop.event_free_intervention[j] - KM_File$prop.event_free_intervention[(j+1)])/KM_File$prop.event_free_intervention[j])
            )
            KM_File$n.censored_intervention[j] <- 0
            KM_File$n.event_free_control[j] <- n.participants[length(n.participants)]
            KM_File$n.at.risk_control[j] <- KM_File$n.event_free_control[j]
            KM_File$n.events_control[j] <- ifelse(
              (
                (KM_File$prop.event_free_control[j] == KM_File$prop.event_free_control[(j+1)]) | 
                  (KM_File$prop.event_free_control[j] == min.Survival_Proportions[[i]][2])
              ), 0.000001, 
              KM_File$n.at.risk_control[j] * 
                ((KM_File$prop.event_free_control[j] - KM_File$prop.event_free_control[(j+1)])/KM_File$prop.event_free_control[j])
            )
            KM_File$n.censored_control[j] <- 0
          } else if (j == nrow(KM_File)){
            KM_File$n.event_free_intervention[j] <- KM_File$n.event_free_intervention[(j-1)] - KM_File$n.events_intervention[(j-1)] - KM_File$n.censored_intervention[(j-1)]
            KM_File$n.at.risk_intervention[j] <- KM_File$n.event_free_intervention[j]
            KM_File$n.events_intervention[j] <- 0.000001
            KM_File$n.censored_intervention[j] <- 0
            KM_File$n.event_free_control[j] <- KM_File$n.event_free_control[(j-1)] - KM_File$n.events_control[(j-1)] - KM_File$n.censored_control[(j-1)]
            KM_File$n.at.risk_control[j] <- KM_File$n.event_free_control[j]
            KM_File$n.events_control[j] <- 0.000001
            KM_File$n.censored_control[j] <- 0
          } else {
            KM_File$n.event_free_intervention[j] <- KM_File$n.event_free_intervention[(j-1)] - KM_File$n.events_intervention[(j-1)] - KM_File$n.censored_intervention[(j-1)]
            KM_File$n.censored_intervention[j] <- ifelse(
              (
                ((KM_File$time[j] < min.follow_up) | (KM_File$time[j] >= max.follow_up)) |
                  ((KM_File$prop.event_free_intervention[j] == min.Survival_Proportions[[i]][1]) & (KM_File$prop.event_free_control[j] == min.Survival_Proportions[[i]][2]))  
              ), 
              0,
              KM_File$n.event_free_intervention[j] * 0.5 * (KM_File$time[j+1] - KM_File$time[j]) * 
                (1/(max.follow_up - KM_File$time[j]))
            )
            KM_File$n.at.risk_intervention[j] <- KM_File$n.event_free_intervention[j] - KM_File$n.censored_intervention[j]
            KM_File$n.events_intervention[j] <- ifelse(
              (
                (KM_File$prop.event_free_intervention[j] == KM_File$prop.event_free_intervention[(j+1)]) | 
                  (KM_File$prop.event_free_intervention[j] == min.Survival_Proportions[[i]][1])
              ), 0.000001, 
              KM_File$n.at.risk_intervention[j] * 
                ((KM_File$prop.event_free_intervention[j] - KM_File$prop.event_free_intervention[(j+1)])/KM_File$prop.event_free_intervention[j])
            )
            KM_File$n.event_free_control[j] <- KM_File$n.event_free_control[(j-1)] - KM_File$n.events_control[(j-1)] - KM_File$n.censored_control[(j-1)]
            KM_File$n.censored_control[j] <- ifelse(
              (
                ((KM_File$time[j] < min.follow_up) | (KM_File$time[j] >= max.follow_up)) |
                  ((KM_File$prop.event_free_intervention[j] == min.Survival_Proportions[[i]][1]) & (KM_File$prop.event_free_control[j] == min.Survival_Proportions[[i]][2]))  
              ), 
              0,
              KM_File$n.event_free_control[j] * 0.5 * (KM_File$time[j+1] - KM_File$time[j]) * 
                (1/(max.follow_up - KM_File$time[j]))
            )
            KM_File$n.at.risk_control[j] <- KM_File$n.event_free_control[j] - KM_File$n.censored_control[j]
            KM_File$n.events_control[j] <- ifelse(
              (
                (KM_File$prop.event_free_control[j] == KM_File$prop.event_free_control[(j+1)]) | 
                  (KM_File$prop.event_free_control[j] == min.Survival_Proportions[[i]][2])
              ), 0.000001, 
              KM_File$n.at.risk_control[j] * 
                ((KM_File$prop.event_free_control[j] - KM_File$prop.event_free_control[(j+1)])/KM_File$prop.event_free_control[j])
            )
          }
        }
        KM_File$ln.hr.t <- log((KM_File$n.events_intervention/KM_File$n.at.risk_intervention)/(KM_File$n.events_control/KM_File$n.at.risk_control))
        KM_File$inverse.v.t <- (1/KM_File$n.events_intervention) - (1/KM_File$n.at.risk_intervention) + (1/KM_File$n.events_control) - (1/KM_File$n.at.risk_control)
        KM_File$o_e.t <- KM_File$ln.hr.t/KM_File$inverse.v.t
        KM_File$v.t <- 1/KM_File$inverse.v.t
        ln.hr <- sum(KM_File$o_e.t)/sum(KM_File$v.t)
        se.ln.hr <- 1/(sum(KM_File$v.t)^0.5)
      } else {
        KM_File <- "Please check data: proportion event free cannot be more than the previous time point"
        ln.hr <- "Please check data: proportion event free cannot be more than the previous time point"
        se.ln.hr <- "Please chcek data: proportion event free cannot be more than the previous time point"
      }
    } else {
      KM_File <- "Please check data: the number of time points and number of values supplied for intervention and control do not match"
      ln.hr <- "Please check data: the number of time points and number of values supplied for intervention and control do not match"
      se.ln.hr <- "Please check data: the number of time points and number of values supplied for intervention and control do not match"
    }
    KM_Calculations[[i]] <- list(calculations = KM_File,
                                 ln.hr = ln.hr,
                                 se.ln.hr = se.ln.hr,
                                 KM_DataTable = KM_DataTable
    )
  }
  return(KM_Calculations)
}
# Imputation methods for standard deviation
# Reference: Weir CJ, Butcher I, Assi V, Lewis SC, Murray GD, Langhorne P, Brady MC. Dealing with missing standard deviation and mean values in meta-analysis of continuous outcomes: a systematic review. BMC Med Res Methodol. 2018 Mar 7;18(1):25. doi: 10.1186/s12874-018-0483-0. PMID: 29514597; PMCID: PMC5842611.
# Reference: Wiebe N, Vandermeer B, Platt RW, Klassen TP, Moher D, Barrowman NJ. A systematic review identifies a lack of standardization in methods for handling missing variance data. J Clin Epidemiol. 2006 Apr;59(4):342-53. doi: 10.1016/j.jclinepi.2005.08.017. PMID: 16549255.
# Higgins JPT, Li T, Deeks JJ (editors). Chapter 6: Choosing effect measures and computing estimates of effect. 
# In: Higgins JPT, Thomas J, Chandler J, Cumpston M, Li T, Page MJ, Welch VA (editors). 
# Cochrane Handbook for Systematic Reviews of Interventions version 6.4 (updated August 2023). Cochrane, 2023. 
# Available from www.training.cochrane.org/handbook. 

individual.group.se.to.sd <- function(se,n) {
  # Formula from Cochrane Handbook: SD = SE × √𝑁
  se*n^0.5
}
individual.group.ci.to.sd <- function(lower.ci, upper.ci, n, ci, normal.distribution) {
  # Formula and suggested algorithm from Cochrane Handbook: SD = √𝑁 × (upper limit − lower limit)⁄3.92
  # Instead of rounding, the qnorm function is used directly
  if (missing(normal.distribution)) {
    normal.distribution <- FALSE
  }
  if (missing(ci)) {
    ci <- 0.95
  }
  if (
    (n> 100) |
    ((n > 60) & (normal.distribution == TRUE))
  ){
    abs((upper.ci - lower.ci)/
          (qnorm((1-ci)/2)*2)
    )*
      n^0.5 
  } else {
    abs((upper.ci - lower.ci)/
          (qt((1-ci)/2,(n-1))*2)
    )*
      n^0.5
  }
} 

individual.group.quartiles.to.sd <- function(lower.quartile, upper.quartile,
                                             minimum, maximum, n) {
  # Formula from Cochrane: (upper.quartile-lower.quartile) * 1.35 (appropriate for large sample size and normal distribution)
  # Formula from Weir et al based on Wan X, Wang W, Liu J, Tong T. Estimating the sample mean and standard deviation from the sample size, median, range and/or interquartile range. BMC Med Res Methodol. 2014;14:135. doi: 10.1186/1471-2288-14-135. 
  # Formula with minimum and maximum
  # Formula: sd = ((maximum - minimum)/(4*qnorm((n-0.375)/(n+0.25)))) + ((upper.quartile - lower.quartile)/(4*qnorm((0.75*n-0.125)/(n+0.25))))
  # Formula without minimum and maximum
  # Formula: sd = (upper.quartile - lower.quartile)/(2*qnorm((0.75*n-0.125)/(n+0.25)))
  if ((missing(minimum)) | (missing(maximum))) {
    abs((upper.quartile - lower.quartile)/(2*qnorm((0.75*n-0.125)/(n+0.25))))
  } else {
    ((maximum - minimum)/(4*qnorm((n-0.375)/(n+0.25)))) + ((upper.quartile - lower.quartile)/(4*qnorm((0.75*n-0.125)/(n+0.25))))
  }
}
individual.group.range.to.sd <- function(minimum, maximum, n){
  # Formula from Weir et al based on Wan X, Wang W, Liu J, Tong T. Estimating the sample mean and standard deviation from the sample size, median, range and/or interquartile range. BMC Med Res Methodol. 2014;14:135. doi: 10.1186/1471-2288-14-135. 
  # Formula: sd = (maximum - minimum)/(2*qnorm((n-0.375)/(n+0.25)))
  abs((maximum - minimum)/(2*qnorm((n-0.375)/(n+0.25))))
}

# References for meta-analysis
# Package: Meta
# Balduzzi S, Rücker G, Schwarzer G. How to perform a meta-analysis with R: a practical tutorial. Evid Based Ment Health. 2019 Nov;22(4):153-160. doi: 10.1136/ebmental-2019-300117. Epub 2019 Sep 28. PMID: 31563865.

# Methods to convert SMD to odds ratio: https://academic.oup.com/ije/article/41/5/1445/711693
# Methods for imputation of SD
# Methods for calculation of hazard ratio: Parmar et al

# Meta-analysis of rare events
# Dungang Li. Meta-Analysis of Rare Events. 2019. Wiley StatsRef: Statistics Reference Online. DOI: 10.1002/9781118445112.stat08167
# GLMM for sparse events: Stijnen, T., Hamza, T.H. and Özdemir, P. (2010), Random effects meta-analysis of event outcome in the framework of the generalized linear mixed model with applications in sparse data. Statist. Med., 29: 3046-3067. https://doi.org/10.1002/sim.4040

# Funnel plot asymmetry
# Sterne et al. Recommendations for examining and interpreting funnel plot asymmetry in meta-analyses of randomised controlled trials. BMJ 2011; 343 doi: https://doi.org/10.1136/bmj.d4002
# Rücker G, Schwarzer G, Carpenter J. Arcsine test for publication bias in meta-analyses with binary outcomes. Stat Med. 2008 Feb 28;27(5):746-63. doi: 10.1002/sim.2971. PMID: 17592831.

# Metaregression
# Thompson SG, Higgins JP. How should meta-regression analyses be undertaken and interpreted? Stat Med. 2002 Jun 15;21(11):1559-73. doi: 10.1002/sim.1187. PMID: 12111920.

# Dealing with missing data
# Mavridis, D, White, IR. Dealing with missing outcome data in meta-analysis. Res Syn Meth. 2020; 11: 2– 13. https://doi.org/10.1002/jrsm.1349
# Higgins JP, White IR, Wood AM. Imputation methods for missing outcome data in meta‐analysis of clinical trials.Clin Trials.2008;5(3):225‐23. https://journals.sagepub.com/doi/10.1177/1740774508091600
# Mavridis D, White IR, Higgins JPT, Cipriani A, Salanti G. Allowing for uncertainty due to missing continuous outcome data in pairwise and network meta‐analysis. Stat Med 2015;34(5):721‐741. https://doi.org/10.1002/sim.6365

# Variances of product of two independent variables
# Leo A. Goodman (1960) On the Exact Variance of Products, Journal of the American Statistical Association, 55:292, 708-713, DOI: 10.1080/01621459.1960.10483369
# Variance: V(x,y) =  E(x)^2*V(y)+E(y)^2*V(x)+V(x)*V(y) 
# [Equation 2]
# Variances of product of two dependent variables
# https://rdrr.io/github/FabioLugar/mvEvol/src/R/varTransform.R
# Another formula is also available from Leo A.Goodman reference

# Variance of the sum of two random variables (X and Y) = Var(X)+Var(Y)+2*Cov(X,Y)
# Reference: H. Pishro-Nik, "Introduction to probability, statistics, and random processes", available at https://www.probabilitycourse.com, Kappa Research LLC, 2014.

# Defaults and optional
# Effect measures
# Odds ratio for 'binary'
# Rate ratio for 'count' 
# Mean difference for 'continuous' unless the scale indicates different measures
# Hazard ratio for 'time' outcomes
# Optional: risk ratio and risk difference for 'binary', mean difference (when different scales), standardised mean difference (otherwise), ratio of means for 'continuous' outcomes

# Model
# Random-effects model (normal distribution) and fixed-effect model (also presented)
# Hartung and Knapp adjusted analysis for random-effects model
# Prediction interval also presented
# Optional: without Hartung and Knapp adjusted analysis 

# Method
# For binary outcomes: Mantel Haenszel method, but if data = sparse (continuity correction applied), GLMM (exact likelihood) (Ref: Li 2019; Stijnen 2010) ==> if no convergence, GLMM (approximate likelihood)
# For continuous outcomes (SMD): Hedges' g, exact SMD
# For other outcomes: inverse variance method
# Optional: other methods

# Metabias
# Contour enhanced plots offered for any number of trials
# Tests for funnel plot asymmetry
# Minimum 10 studies (Sterne 2011)
# For binary with tau2<0.10, Harbord (Sterne 2011), otherwise Thompson test after arcsine transformation (as per Rucker 2008)
# For non-binary outcomes: Egger
# Optional: other methods

# Sensitivity analysis
# Binary outcomes: best-worst meta-analysis, IMOR (same for intervention and control): any missing or only for missing not at random: using control proportions
# Continuous outcomes: exclude studies in which SD was imputed

# Metaregression
# User selected variables

# Subgroup meta-analysis
# User selected variables
# Only for categorical variables
# Different variances across subgroups

# Future Improvements
# New meta-analysis methods
# Apply box cox transformation to continuous variables (dependent and metaregression)
# Random-effects (non-normal distribution)
# Meta-analysis of ordinal outcomes
# NMA
# Repeated measures
# Correlated outcomes
# Ordinal outcomes
# Allow user to specify whether the categorical variable in subgroup analysis is ordered
# DTAR
# Prognostic
# Meta-analysis of correlations

# More user choice
# Impute method for standard deviation for continuous outcomes
# ImputeMethodSD <- c("Method 1", "Method 2")
# ImputeMissingSD <- c("Maximum of other SD", "Median of other SD", "I will provide values")

# Systematic review related
# Screening trials
# Extracting data from text (after OCR)

# The future
# Link with COMET outputs and outcome taxonomy

# Make the code available
ProgrammeCode <- read.delim("ProgrammeCode.txt", header = FALSE, sep = "\t", dec = ".", quote="")

# Start recording the code (only for meta-analysis of intervention currently)
GenerateCode <- read.delim("Code_Intervention.txt", header = FALSE, sep = "\t", dec = ".", quote="")

# Choices ####
FirstSelection <- c(
  "View instructions",
  "View Main menu",
  "Instructions (Intervention review)",
  "Upload new data, view, modify, and run meta-analysis (Intervention review)",
  "View and download results (Intervention review)",
  "Combine database searches and highlight keywords",
  "Create data extraction form",
  "Perform optical character recognition (OCR)",
  "Data extraction from plots",
  "Process data (Intervention review)",
  "Interpret data (Intervention review)"
)
MainHeaderSelection <- c(
  '<h2 style = "color:maroon"><b>Instructions</b></h2>',
  '<h2 style = "color:maroon"><b>Main menu</b></h2>',
  '<h2 style = "color:maroon"><b>Meta-analysis in systematic reviews of intervention</b></h2>',
  '<h2 style = "color:maroon"><b>Meta-analysis in systematic reviews of intervention</b></h2>
  <h2 style = "color:darkgreen">Upload new data, view, modify, and run meta-analysis</b></h2>',
  '<h2 style = "color:maroon"><b>Meta-analysis in systematic reviews of intervention</b></h2>
  <h2 style = "color:darkgreen">View and download results</b></h2>',
  '<h2 style = "color:maroon"><b>Combine database searches and highlight keywords</b></h2>',
  '<h2 style = "color:maroon"><b>Create data extraction form</b></h2>',
  '<h2 style = "color:maroon"><b>Perform optical character recognition (OCR)</b></h2>',
  '<h2 style = "color:maroon"><b>Data extraction from plots</b></h2>',
  '<h2 style = "color:maroon"><b>Process data</b></h2>',
  '<h2 style = "color:maroon"><b>Interpret data</b></h2>'
)
DEF_Plan_IntChoice <- c(
  "I want to upload my own Data extraction form plan that I have prepared previously for intervention reviews",
  "I want to create a new Data extraction form plan for intervention reviews"
)
MetaAnalysisPlanChoice_Int <- c(
  "I want to use the default plan for meta-analysis of interventions (available below)",
  "I want to use the RevMan plan for meta-analysis of interventions (available below)",
  "I want to use my own meta-analysis plan that I have prepared previously for intervention reviews using this programme without any modifications",
  "I want to use my own meta-analysis plan that I have prepared previously for intervention reviews using this programme after modifying it",
  "I want to modify the default plan (available below for intervention reviews) and use the modified plan in the future if necessary",
  "I want to modify the RevMan plan (available below for intervention reviews) and use the modified plan in the future if necessary"
)
EffectMeasure_Binary_Choice <- c("Odds ratio", "Risk ratio", "Risk difference")
EffectMeasure_Binary_Choice_Converter <- c("OR", "RR", "RD")
EffectMeasure_Continuous_Choice <- c("Mean difference", "Standardised mean difference","Ratio of means")
EffectMeasure_Continuous_Choice_Converter <- c("MD","SMD","ROM")
EffectMeasure_Count_Choice <- c("Rate ratio")
EffectMeasure_Count_Choice_Converter <- c("RR")
EffectMeasure_Ratio_Choice <- c("Odds ratio", "Risk ratio", "Rate ratio", "Hazard ratio", "Ratio of means")
EffectMeasure_Ratio_Choice_Converter <- c("OR", "RR", "RR", "HR", "ROM")
EffectMeasure_Difference_Choice <- c("Mean difference", "Standardised mean difference","Risk difference")
EffectMeasure_Difference_Choice_Converter <- c("MD","SMD","RD")

RareEvents_Correction_Choice <- c("Continuity correction with 0.5 for events and no events", "Continuity correction with 0.5 for events only")
RareEvents_Method_Choice <- c("Generalised Linear Mixed Model (only for odds ratios)", "Peto odds ratio (odds ratio and fixed-effect model only)", "Perform the meta-analysis with continuity correction")
FixedEffect_Choice <- c("Yes","No")
PredictionInterval_Choice <- c("Yes","No")
HKAdjustment_Choice <- c("Yes","No")
MA_Method_Binary_Choice <- c("Mantel-Haenszel","Inverse variance") 
MA_Method_Binary_Choice_Converter <- c("MH","Inverse") 
MA_Method_SMD_Choice <- c("Hedges's g with exact SMD", "Hedges's g with approximate SMD","Cohen's d with exact SMD","Cohen's d with approximate SMD", "Glass' delta with control group standard deviation", "Glass' delta with intervention group standard deviation")
MA_Method_SMD_Choice_Converter <- c("Hedges_TRUE","Hedges_FALSE","Cohen_TRUE","Cohen_FALSE","Glass_sd.c","Glass_sd.e")
Metabias_Any_Choice <- c("Begg", "Egger", "Thompson", "Harbord")
Metabias_Heterogeneity_Choice <- c("Begg", "Egger", "Thompson", "Harbord", "Arcsine-Begg", "Arcsine-Egger", "Arcsine-Thompson")
Metabias_Heterogeneity_Choice_Converter <- c("None_Begg", "None_Egger", "None_Thompson", "None_Harbord", "ASD_Begg", "ASD_Egger", "ASD_Thompson")

# Storage folder
StorageFolder <- tempdir()

# Reference screener
database <- c(
  "PubMed", "MEDLINE", "EMBASE", "WOS", "Cochrane", "CTgov", "ICTRP"
)

# OCR languages
ocr.languages <- data.frame(cbind(
  c("Chinese", "Danish", "German", "English", "Persian", "French", "Italian", "Japanese", "Korean", "Dutch", "Norwegian", "Polish", "Portugese", "Russian", "Spanish", "Thai", "Ukraine"),
  c("chi_sim", "dan", "deu", "eng", "fas", "fra", "ita", "jpn", "kor", "nld", "nor", "pol", "por", "rus", "spa", "swe", "ukr")
))
colnames(ocr.languages) <- c("Language", "Engine")
ocr.languages <- ocr.languages[order(ocr.languages$Language),]

# Lists for extracting data from plots ####
PlotExtract_PlotTypes <- c(
  "Kaplan-Meier Plot in percentages", #1
  "Kaplan-Meier Plot in decimal fractions", #2
  "Box plot", #3
  "Bar plot without error bars", #4
  "Bar plot with error bars", #5
  "Line plot without error bars", #6
  "Line plot with error bars" #7
)
PlotExtract_y_min_y_max_builder_OutputType <- c(
  "sliderInput", #1
  "sliderInput", #2
  "numericInput", #3
  "numericInput", #4
  "numericInput", #5
  "numericInput", #6
  "numericInput" #7
)
PlotExtract_y_min_y_max_builder_min_max_value_min <- c(
  "min = 0, max = 100, value = 0", #1
  "min = 0, max = 1, value = 0", #2
  "value = NA", #3
  "value = NA", #4
  "value = NA", #5
  "value = NA", #6
  "value = NA" #7
)
PlotExtract_y_min_y_max_builder_min_max_value_max <- c(
  "min = 0, max = 100, value = 100", #1
  "min = 0, max = 1, value = 1", #2
  "value = NA", #3
  "value = NA", #4
  "value = NA", #5
  "value = NA", #6
  "value = NA" #7
)
PlotExtract_y_min_y_max_builder_min_max_value_min_change <- c(
  "min = 0, max = 100, value = input$PlotExtract_y_min", #1
  "min = 0, max = 1, value = input$PlotExtract_y_min", #2
  "value = input$PlotExtract_y_min", #3
  "value = input$PlotExtract_y_min", #4
  "value = input$PlotExtract_y_min", #5
  "value = input$PlotExtract_y_min", #6
  "value = input$PlotExtract_y_min" #7
)
PlotExtract_y_min_y_max_builder_min_max_value_max_change <- c(
  "min = 0, max = 100, value = input$PlotExtract_y_max", #1
  "min = 0, max = 1, value = input$PlotExtract_y_max", #2
  "value = input$PlotExtract_y_max", #3
  "value = input$PlotExtract_y_max", #4
  "value = input$PlotExtract_y_max", #5
  "value = input$PlotExtract_y_max", #6
  "value = input$PlotExtract_y_max" #7
)
PlotExtract_y_min_y_max <- paste0(
  'output$PlotExtract_y_min_UI <- renderUI(',
  PlotExtract_y_min_y_max_builder_OutputType,
  '("PlotExtract_y_min", "Choose the minimum y value in the plot",',
  PlotExtract_y_min_y_max_builder_min_max_value_min,
  ')); output$PlotExtract_y_max_UI <- renderUI(',
  PlotExtract_y_min_y_max_builder_OutputType,
  '("PlotExtract_y_max", "Choose the maximum y value in the plot",',
  PlotExtract_y_min_y_max_builder_min_max_value_max,
  '))'
)
PlotExtract_y_min_y_max[c(1:2)] <- paste0(
  'output$PlotExtract_x_min_UI <- renderUI(',
  'numericInput',
  '("PlotExtract_x_min", "Choose the minimum x value in the plot",',
  'min = 0, value = NA',
  ')); output$PlotExtract_x_max_UI <- renderUI(',
  'numericInput',
  '("PlotExtract_x_max", "Choose the maximum x value in the plot",',
  'min = 0, value = NA',
  '))',
  '; ',
  PlotExtract_y_min_y_max[c(1:2)]
) 
PlotExtract_y_min_y_max[c(6:7)] <- paste0(
  'output$PlotExtract_x_min_UI <- renderUI(',
  'numericInput',
  '("PlotExtract_x_min", "Choose the minimum x value in the plot",',
  'value = NA',
  ')); output$PlotExtract_x_max_UI <- renderUI(',
  'numericInput',
  '("PlotExtract_x_max", "Choose the maximum x value in the plot",',
  'value = NA',
  '))',
  '; ',
  PlotExtract_y_min_y_max[c(6:7)]
) 
PlotExtract_y_min_y_max_change <- paste0(
  'output$PlotExtract_y_min_UI <- renderUI(',
  PlotExtract_y_min_y_max_builder_OutputType,
  '("PlotExtract_y_min", "Choose the minimum y value in the plot",',
  PlotExtract_y_min_y_max_builder_min_max_value_min_change,
  ')); output$PlotExtract_y_max_UI <- renderUI(',
  PlotExtract_y_min_y_max_builder_OutputType,
  '("PlotExtract_y_max", "Choose the maximum y value in the plot",',
  PlotExtract_y_min_y_max_builder_min_max_value_max_change,
  '))'
)
# Add x_min and x-max for KM curves and line plots
PlotExtract_y_min_y_max_change[c(1:2)] <- paste0(
  'output$PlotExtract_x_min_UI <- renderUI(',
  'numericInput',
  '("PlotExtract_x_min", "Choose the minimum x value in the plot",',
  'min = 0, value = input$PlotExtract_x_min',
  ')); output$PlotExtract_x_max_UI <- renderUI(',
  'numericInput',
  '("PlotExtract_x_max", "Choose the maximum x value in the plot",',
  'min = 0, value = input$PlotExtract_x_max',
  '))',
  '; ',
  PlotExtract_y_min_y_max_change[c(1:2)]
) 
PlotExtract_y_min_y_max_change[c(6:7)] <- paste0(
  'output$PlotExtract_x_min_UI <- renderUI(',
  'numericInput',
  '("PlotExtract_x_min", "Choose the minimum x value in the plot",',
  'value = input$PlotExtract_x_min',
  ')); output$PlotExtract_x_max_UI <- renderUI(',
  'numericInput',
  '("PlotExtract_x_max", "Choose the maximum x value in the plot",',
  'value = input$PlotExtract_x_max',
  '))',
  '; ',
  PlotExtract_y_min_y_max_change[c(6:7)]
) 

PlotExtract_Points_EachGroup_EachTimePoint <- c(
  1, 1, 3, 1, 3, 1, 3
)
PlotExtract_Points_Names_EachGroup_EachTimePoint <- list(
  c("Proportion survived"),
  c("Proportion survived"),
  c("mean or median","lower quartile", "upper quartile"),
  c("mean"),
  c("mean", "lower limit","upper limit"),
  c("mean"),
  c("mean", "lower limit","upper limit")
)

PlotClick_Yes <- c(
  'output$PlotExtract_UploadedPlot_UI <- renderUI(
        plotOutput("PlotExtract_UploadedPlot", click = "Plot_Click"),
      )
  '  
)
PlotClick_No <- c(
  '    output$PlotExtract_UploadedPlot_UI <- renderUI(
        plotOutput("PlotExtract_UploadedPlot"),
      )
  '  
)
KM_Min_Max_Question_1_Choice <- c(
  "days",
  "months",
  "years"
)
KM_Min_Max_Question_2_Choice <- c(
  "Minimum and maximum follow-up directly reported in the trial",
  "Median follow-up and recruitment duration",
  "Date of analysis, date of first recruitment, and last recruitment",
  "Data of submission, date of first recruitment, and last recruitment",
  "I do not have any of the information above or ticks in the KM curve"
)
KM_Min_Max_Questions_3_5 <- c(
  'output$PlotExtract_KM_Min_Max_Question_3_UI <- renderUI(
      numericInput("PlotExtract_KM_Min_Max_Question_3",
                   "Enter the minimum follow-up",
                   min = 0,
                   value = NA)
    );
    output$PlotExtract_KM_Min_Max_Question_4_UI <- renderUI(
      numericInput("PlotExtract_KM_Min_Max_Question_4",
                   "Enter the maximum follow-up",
                   min = 0,
                   value = NA)
    );
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL', # Choice 1 of KM_Min_Max_Question_2_Choice
  'output$PlotExtract_KM_Min_Max_Question_3_UI <- renderUI(
      numericInput("PlotExtract_KM_Min_Max_Question_3",
                   "Enter the median follow-up",
                   min = 0,
                   value = NA)
    );
    output$PlotExtract_KM_Min_Max_Question_4_UI <- renderUI(
      numericInput("PlotExtract_KM_Min_Max_Question_4",
                   "Enter the recruitment duration",
                   min = 0,
                   value = NA)
    ); 
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL', # Choice 2 of KM_Min_Max_Question_2_Choice
  'output$PlotExtract_KM_Min_Max_Question_3_UI <- renderUI(
      dateInput("PlotExtract_KM_Min_Max_Question_3",
                   "Enter the date of analysis (if only the month and year are reported, choose 15 as the date)",
                   format = "yyyy-mm-dd",
                   startview = "month",
                   value = Sys.Date(),
                   max = Sys.Date())
    );
    output$PlotExtract_KM_Min_Max_Question_4_UI <- renderUI(
      dateInput("PlotExtract_KM_Min_Max_Question_4",
                   "Enter the date of first recruitment (if only the month and year are reported, choose 15 as the date)",
                   format = "yyyy-mm-dd",
                   startview = "month",
                   value = Sys.Date(),
                   max = Sys.Date())
    ); 
    output$PlotExtract_KM_Min_Max_Question_5_UI <- renderUI(
      dateInput("PlotExtract_KM_Min_Max_Question_5",
                   "Enter the date of last recruitment (if only the month and year are reported, choose 15 as the date)",
                   format = "yyyy-mm-dd",
                   startview = "month",
                   value = Sys.Date(),
                   max = Sys.Date())
    )', # Choice 3 of KM_Min_Max_Question_2_Choice
  'output$PlotExtract_KM_Min_Max_Question_3_UI <- renderUI(
      dateInput("PlotExtract_KM_Min_Max_Question_3",
                   "Enter the date of submission (if only the month and year are reported, choose 15 as the date)",
                   format = "yyyy-mm-dd",
                   startview = "month",
                   value = Sys.Date(),
                   max = Sys.Date())
    );
    output$PlotExtract_KM_Min_Max_Question_4_UI <- renderUI(
      dateInput("PlotExtract_KM_Min_Max_Question_4",
                   "Enter the date of first recruitment (if only the month and year are reported, choose 15 as the date)",
                   format = "yyyy-mm-dd",
                   startview = "month",
                   value = Sys.Date(),
                   max = Sys.Date())
    ); 
    output$PlotExtract_KM_Min_Max_Question_5_UI <- renderUI(
      dateInput("PlotExtract_KM_Min_Max_Question_5",
                   "Enter the date of last recruitment (if only the month and year are reported, choose 15 as the date)",
                   format = "yyyy-mm-dd",
                   startview = "month",
                   value = Sys.Date(),
                   max = Sys.Date())
    )', # Choice 4 of KM_Min_Max_Question_2_Choice
  'output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL; 
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL; 
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL'# Choice 5 of KM_Min_Max_Question_2_Choice
)

# Instructions ####
Instructions <- ('
<h3 style = "font-size:24px; color:purple;"><b>Instructions</b></h3>
<li>This programme performs the following functions: </li>
<ul>
<li><b>Perform meta-analysis in systematic reviews of interventions.</b></li>
<li><b>Combine search results from databases and highlight keywords.</b></li>
<li><b>Create a customised data extraction form.</b> <i>Because of memory constraints, this is possible only on a local version. 
You can download the program code to run a local version.</i></li>
<li><b>Optical character recognition (OCR) of English and non-English images and pdf files to allow online translation.</b></li>
<li><b>Extract data from plots.</b></li>
<li><b>Process data.</b> This includes conversion of data into a suitable format and converting signalling questions to risk of bias classifications.</li>
<li><b>Interpret data.</b> This includes obtaining information to help with GRADE classifications and interpretation in terms of clinical significance (rather than statistical significance)</li>
</ul>
<li>Click on <strong>"View Main Menu"</strong> on the left side panel to access the different functions of this application.</li>
<li>The instructions for each of these functions can be found under the relevant functions.</li>
')
Instructions_Int <- ('
                     <h3 style = "font-size:24px; color:purple;"><b>Instructions for performing meta-analysis in systematic review of inteventions</b></h3>
This version supports analysis of about 30 outcomes.
<h3><b><i>Preparation of data</i></b></h3>
<p>
<ul>
<p><b><i>Manual preparation of data</i></b></p>
<ul>
<li>The first 28 fields should be in the same order and should have the same field names as the template regardless of which outcomes you want to analyse or which data you have collected. 
For example, even if you do not use continuous outcomes, you should include the field names applicable only for continuous outcomes and in the same order. 
</li>
<li>For each outcome, please indicate the fields below. 
The mandatory fields are indicated as "[Mandatory]". If these fields are not provided in the correct format, the study will be excluded from the analysis. 
The optional fields are indicated as "[Optional]", but may be required for additonal analyses and presentation of information.</li>
<ul>
<li><b>Column 1</b>: Outcome name [Mandatory]: This is any name that you want to give to the outcome.</li>
<li><b>Column 2</b>: Type of outcome [Mandatory]: This should be one of the following six types: "Binary", "Continuous","Count","Time","Summary_Ratio","Summary_Difference". For which type of outcome you should choose, please see here.</li> 
<li><b>Column 3</b>: Are more events or higher value better or worse for participants? [Mandatory]: The choices are "Better", "Worse".</li> 
<li><i>The "Outcome name", "Type of outcome", and "Are more events or higher value better or worse for participants?" need to be specified only for the first row for each new outcome.</i></li>
<li><b>Column 4</b>: Study [Mandatory]: This can be the name of the study. This is usually the last name of the first author and followed by the year of publication indicated as YYYY. 
Year can be used for some aspects of meta-analysis.</li>
<li><b>Column 5</b>: Intervention (total number of participants) [Mandatory for "Binary" and "Continuous" outcomes and optional for remaining outcomes]: This is the total number of participants for the intervention group.</li> 
<li><b>Column 6</b>: Control (total number of participants) [Mandatory for "Binary" and "Continuous" outcomes and optional for remaining outcomes]: This is the total number of participants for the control group.</li>
<li><b>Column 7</b>: Parameter1 [Mandatory]: This varies according to outcomes.</li>
<ul>
<li>"Binary" outcomes: number of participants with outcome (event) in the intervention group</li>
<li>"Continuous" outcomes: Mean in intervention group</li>
<li>"Count" outcomes: Ln (natural logarithm) rate ratio</li>
<li>"Time" outcomes: Ln hazard ratio</li>
<li>"Summary_Ratio" outcomes: Ln odds ratio or Ln risk ratio</li>
<li>"Summary_Difference" outcomes: Mean difference, Standardised mean difference, or risk difference</li>
</ul>
<li><b>Column 8</b>: Parameter2 [Mandatory]: This varies according to outcomes.</li>
<ul>
<li>"Binary" outcomes: number of participants with outcome (event) in the control group</li>
<li>"Continuous" outcomes: Standard deviation in intervention group. 
If standard deviation is missing and cannot be imputed from any information in the trial, please leave this empty. 
If left empty, standard deviation in the study will be imputed as the maximum standard deviation in the remaining trials.</li>
<li>"Count" outcomes: Standard error of Ln rate ratio</li>
<li>"Time" outcomes: Standard error of Ln hazard ratio</li>
<li>"Summary_Ratio" outcomes: Standard error of effect measure used in column 8, i.e., Ln odds ratio or Ln risk ratio</li>
<li>"Summary_Difference" outcomes: Standard error of effect measure used in column 8, i.e., Mean difference, Standardised mean difference, or risk difference</li>
</ul>
<li><b>Column 9</b>: Parameter3 [Mandatory] for "Continuous" outcomes and not applicable for remaining outcome types: Mean in control group </li>
<li><b>Column 10</b>: Parameter4 [Mandatory] for "Continuous" outcomes and not applicable for remaining outcome types: Standard deviation in intervention group.
As for column 9, if standard deviation cannot be imputed and the field is left empty, standard deviation in the study will be imputed as the maximum standard deviation in the remaining trials.
</li>
<li><b>Column 11</b>: Units (Continuous outcomes) [Optional]: As the name indicates, this is applicable only for continuous outcomes. 
There are some continuous outcomes which do not have units.
This needs to be specified only for the first row of each continuous outcome.
</li> 
<li><b>Column 12</b>: Scale (Continuous outcomes) [Optional]: If the Continuous outcome is measured using different scales, then indicate the scale used in the study. 
If different scales are used, standardised mean difference will be calculated. If the same scale is used in all the studies or if left empty, mean difference will be calculated for continuous outcomes as default.
</li>
<li><b>Column 13</b>: Mean or standard deviation imputed (Continuous outcomes) [Optional]: If you have imputed the mean or standard deviation or both from other measures, 
you must perform a sensitivity analysis excluding such studies in which mean or standard deviation are imputed. Enter "1" in the study row if you have imputed the mean or standard deviation.
</li>
<li><b>Column 14</b>: Missing failure (Intervention)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in intervention group from analysis after randomisation because of reasons such as 
lack of therapeutic benefit, relapse, or worsening of symptoms which indicate failure of treatment.
</li>
<li><b>Column 15</b>: Missing success (Intervention)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in intervention group from analysis after randomisation because of reasons such as 
cure or positive response which indicate success of treatment. This is not an usual reason of exclusion from studies.
</li>
<li><b>Column 16</b>: Missing unrelated (Intervention)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in intervention group from analysis after randomisation because of reasons such as 
loss to follow-up or administrative error which are are unrelated to success or failure of treatment.
</li>
<li><b>Column 17</b>: Missing protocol violation (Intervention)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in intervention group from analysis after randomisation because of reasons such as 
protocol violation, non-compliance, adverse events where the excluded participants receive the control.
When the participants do not receive the control (mainly applicable in comparisons where the two groups have different active interventions), use Missing other to record the exclusions.
</li>
<li><b>Column 18</b>: Missing other (Intervention)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in intervention group from reasons not covered in the previous reasons for missing.
</li>
<li><b>Column 19</b>: Missing reasons not stated (Intervention)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
Record the missing data under this category when the reasons for missing in the intervention group are not reported.
</li>
<li><b>Column 20</b>: Missing not stated (Intervention)	[Mandatory]: This is applicable only for "Binary" and "Continuous" outcomes.
When it is not clear whether any participants in the intervention group were excluded from the analysis, indicate "Not stated". 
If it is clear that all participants were included in the analysis, you can enter "0". 
If you leave this column empty or enter any text, this will be treated as "Not stated". 
</li>
<li><b>Column 21</b>: Missing failure (Control)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in control group from analysis after randomisation because of reasons such as 
lack of therapeutic benefit, relapse, or worsening of symptoms which indicate failure of treatment.
</li>
<li><b>Column 22</b>: Missing success (Control)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in control group from analysis after randomisation because of reasons such as 
cure or positive response which indicate success of treatment. This is not an usual reason of exclusion from studies.
</li>
<li><b>Column 23</b>: Missing unrelated (Control)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in control group from analysis after randomisation because of reasons such as 
loss to follow-up or administrative error which are are unrelated to success or failure of treatment.
</li>
<li><b>Column 24</b>: Missing protocol violation (Control)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in intervention group from analysis after randomisation because of reasons such as 
protocol violation, non-compliance, adverse events where the excluded participants receive the intervention.
When the participants do not receive the intervention, use Missing other to record the exclusions.
</li>
<li><b>Column 25</b>: Missing other (Control)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
This indicates exclusion of participants in control group from reasons not covered in the previous reasons for missing.
</li>
<li><b>Column 26</b>: Missing reasons not stated (Control)	[Optional]: This is applicable only for "Binary" and "Continuous" outcomes.
Record the missing data under this category when the reasons for missing in the control group are not reported.
</li>
<li><b>Column 27</b>: Missing not stated (Control)	[Mandatory]: This is applicable only for "Binary" and "Continuous" outcomes.
When it is not clear whether any participants were excluded from the analysis, indicate "Not stated". 
If it is clear that all participants in the control group were included in the analysis, you can enter "0". 
If you leave this column empty or enter any text, this will be treated as "Not stated". 
</li>
<li><b>Column 28</b>: Intervention and control details for graphs [Optional]: Only the first 4 rows (after the heading) will be considered. Please insert the following.</li>
<ul>
<li>Row 1 after heading: Intervention full name</li>
<li>Row 2 after heading: Intervention short name</li>
<li>Row 3 after heading: Control full name</li>
<li>Row 4 after heading: Control short name</li>
</ul>
<li><b>Column 29 onwards</b> Effect modifiers (moderator) [Optional]: Any categorical variables (subgroups) or other quantitative variables (for example, mean age in trials) that you want to use for metaregression. 
Please note that any categorical variables should be entered as text and not as numbers, i.e., enter the subgroups without any coding for this to be treated as categorical variable. 
A maximum of 10 variables are supported.
</li>
</ul>
</ul>
</ul>
<ul>
<p><b><i>Export from data extraction form</i></b></p>
<ul>
<li>You can also export the data in a suitable format from the data extraction form from the sheet "Equal" by clicking on "Export data" and saving it in a suitable folder.</li>
<li>Please consider the following changes to the data that you saved.</li>
<ul>
<li>All the outcomes are labelled as "Worse" in the Column 3.
If higher value of an outcome is better for the participant, then change this to "Better"</li>
<li>If some participants have missing values, please revise columns 14 to 27 as appropriate.</li>
<li>In the meta-analysis plan, please alter the effect measures as appropriate.
Otherwise, default effect measures will be used regardless of what was used in the ReviewManager.</li>
</ul>
</ul>
<p><b><i>Export from Review Manager 5</i></b></p>
<ul>
<li>You can also convert Review Manager 5 (RevMan 5) data into a suitable format by performing the following steps.</li>
<li>First, add an empty outcome at the end of the last comparison. This is to work around a bug in RevMan which exports the last outcome as a subgroup even if there is no subgroup.</li>
<li>Next, from ReviewManager, choose File>Export>Data and analyses</li>
<li>In the resulting screen, ensure that "Data and analyses" box is selected and the "Risk of bias tables" is unselected.</li>
<li>Click Next.</li>
<li>In the resulting screen, select Comparison Number, Outcome Number, and Subgroup Number in addition to the default selection.</li>
<li>Click Next.</li>
<li>Retain the default selections and click "Finish".</li>
<li>In the resulting screen, choose the appropriate folder to save the file.</li>
<li>Now upload this file in the side panel where there is a place to upload the data exported from RevMan 5.</li>
<li>Please download the prepared data and consider the following changes.</li>
<ul>
<li>All the outcomes are labelled as "Worse" in the Column 3.
If higher value of an outcome is better for the participant, then change this to "Better"</li>
<li>If some participants have missing values, please revise columns 14 to 27 as appropriate.</li>
<li>In the meta-analysis plan, please alter the effect measures as appropriate.
Otherwise, default effect measures will be used regardless of what was used in the ReviewManager.</li>
</ul>
</ul>
</p>
<p><b><i>Export from RevMan Web</i></b></p>
<ul>
<li>You can also convert RevMan Web data into a suitable format by performing the following steps.</li>
<li>First, log in to RevMan Web and open the review.</li>
<li>Next, scroll down to "History" and select the version that you want to export data from.</li>
<li>Next, click on "Export" button (the button is just below "History" and becomes active once you select a version to export).</li>
<li>In the resulting screen, select "All analyses CSV" and click on "Generate export package".</li>
<li>If you have the right to download data, an export package is generated and is available under "Downloads".</li>
<li>Download the export package. This is usually available in the "Downloads" folder.</li>
<li>Unzip the export package.</li>
<li>The file that is to be used for import is "CD......-data-rows.csv" (the dots indicate the Cochrane CD number).</li>
<li>Since the export package file has another zip folder, the "CD......-data-rows.csv" file must be stored in a specific location before it can be used.
Therefore, copy the file to an appropriate location.</li>
<li>Now upload this file in the side panel where there is a place to upload the data exported from RevMan Web.</li>
<li>Please download the prepared data and consider the following changes.</li>
<ul>
<li>All the outcomes are labelled as "Worse" in the Column 3.
If higher value of an outcome is better for the participant, then change this to "Better"</li>
<li>If some participants have missing values, please revise columns 14 to 27 as appropriate.</li>
<li>In the meta-analysis plan, please alter the effect measures as appropriate.
Otherwise, default effect measures will be used regardless of what was used in the ReviewManager.</li>
</ul>
</ul>
</p>
<h3><b><i>Meta-analysis plan</i></b></h3>
<p>
<ul>
<li>You can either accept the <b>Default meta-analysis plan</b> (the rationale for this choice is provided here), the <b>RevMan meta-analysis plan</b>, 
or upload your own meta-analysis plan prepared with this program.
</li>
<li>If you change your outcome name, delete or add new outcomes to your data, you need to prepare a new meta-analysis plan</li>
<li>The default effect measures used are as follows: </li>
<ul>
<li>Binary: Odds Ratio</li>
<li>Continuous: Mean difference if single scale is used and standardised mean difference if multiple scales are used</li>
<li>Count: Rate ratio</li>
<li>Time: Hazard ratio</li>
</ul>
<li>The data synthesis methods used for the <b>Default plan</b> are as follows:
<ul>
<li><b>Model</b></li>
<ul>
<li>Random-effects model (normal distribution)</li>
<li>Hartung and Knapp adjusted analysis is used for random-effects model</li>
<li>Fixed-effect model (also called common effects model) is also presented</li>
<li>Prediction interval using Hartung and Knapp adjustment when possible is also presented</li>
</ul>
<li><b>Method</b></li>
<ul>
<li><i>Binary outcomes</i>: Mantel Haenszel method is used as default, 
but if data is sparse (zero event in one or more trials), Generalised Linear Mixed Model (GLMM) with exact likelihood is used.
If there is no convergence with GLMM with exact likelihood, GLMM with approximate likelihood is used.
</li>
<li><i>Continuous outcomes</i>: Inverse variance method is used. 
For standardised mean differences (SMD), Hedges g and exact methods are used for calculation of SMD and its confidence intervals.
</li>
</ul>
<li><b>Funnel plot asymmetry</b></li>
<ul>
<li>Contour enhanced funnel plots are generated for any number of trials.</li> 
<li>The following tests for funnel plot asymmetry are performed when there are 10 or more studies.</li>
<ul>
<i>Binary outcomes</i>: When the tau<sup>2</sup> is < 0.1, Harbord test is used; otherwise Thompson test after arcsine transformation is used.</li>
<li><i>All other outcomes</i>: Egger test is used.</li>
</ul>
</ul>
<li><b>Sensitivity analysis</b></li>
<ul>
<li><i>Binary outcomes</i>: Informative missingness Odds Ratio (IMOR) and best-worst analysis are performed.
The IMOR is calculated based on different reasons.
</li>
<ul>
<li>Missing because of failure: The event is considered not to have happened for a good outcome (more is better for patients)
and to have happened for a bad outcome (less is better for patients).
</li>
<li>Missing because of success: The event is considered to have happened for a good outcome and not happened for a bad outcome.</li>
<li>Missing because of unrelated reasons: The events are considered to happen at the same proportions as the respective groups to which the missing participants belonged.</li>
<li>Missing because of protocol violation (cross-over): The events are considered to happen at the proportions of the oppposite group,
i.e., for missing participants in the intervention group, the event is considered to happen at the same proportion as the control group,
and vice versa.
</li>
<li>Missing because of other reasons: The events are considered to happen at twice the proportions of the respective groups for bad outcomes
and half the proportions of the respective groups for good outcomes.
</li>
<li>Missing with no reasons stated: These are distributed in the same proportions of reasons as in the remaining studies.</li>
<li>Missing unknown: If it is not clear whether participants were excluded, the drop-out proportions in other studies are used to estimate this.</li>
</ul>
<li><i>Continuous outcomes</i>: Missing standard deviations are imputed as the highest standard deviations from the remaining studies. 
Senstivity analysis excluding any studies where mean or standard deviations were imputed from other measures is also performed.
</li>
</ul>
<li><b>Sensitivity analysis</b></li>
<ul>
<li>All moderator variables are included in the analysis.</li>
</ul>
<li><b>Subgroup analysis</b></li>
<ul>
<li>All categorical moderator variables are included in the analysis. 
Only the random-effects model is presented. The variances are allowed to vary by the subgroups.</li>
</ul>
</ul>
<li>The data synthesis methods used for the <b>Revman plan</b> are different from the default plan in the following ways.</li>
<ul>
<li>Dersimonian-Laird model is used for random-effects meta-analysis.</li>
<li>A continuity correction by adding 0.5 to the events and 1 to the number of participants in each group is used when the data is sparse.</li>
<li>For SMD, Hedges d with approximate methods are used for calculating the SMD and confidence intervals.</li>
<li>Prediction intervals are not reported.</li>
</ul>
</ul>
</p>
<h3><b><i>Analysis</i></b></h3>
<p>
<ul>
<li><b>Step 1</b>: Upload the data prepared in the correct format in one of the ways outline previously.</li>
<li><b>Step 2</b>: Use an analysis plan.</li>
<ul>
<li>You can use the <b>Default plan</b> or <b>RevMan plan</b> with or without any modifications 
by choosing the appropriate option once the data has been successfully uploaded.
</li>
<li>We expect majority of the users to use one of these two in-built plans.</li>
<li>Alternatively, you can upload your own plan that you prepared using this program and use it with or without modifications
by choosing the appropriate option once the data has been successfully uploaded.
</li>
<li>If you choose to modify any of these plans, the options for different aspects will appear depending upon the outcome that you choose.</li>
<li>You can modify only the specific outcome or all outcomes that are of the same type as the outcome that you are modifying by clicking on the correct option.</li>
<li>You might want to download the analysis plan, so that you do not need to modify this each time you want to analyse the data.</li>
<li>If you rename, add, or delete outcomes, you will need to create a new plan.</li>
<li>You can run the analysis or choose a different analysis plan at any time.
If you choose this option, any modifications to the plan will be lost.
</li>
</ul>
<li><b>Step 3</b>: Run the analysis.</li>
<ul>
<li>The results are available as results summary and plots which can be downloaded.</li>
</ul>
</ul>
</p>
<h3><b><i>Download the codes to run the analysis in R</i></b></h3>
<p>
<ul>
<li>You can download the codes to run the analysis in R. 
You might want to do this for various reasons, for example, you might want to use the validated R packages to report the analysis in a journal publication.
</li>
<li>You can download the codes at any time (from the left side panel), but only the codes after the analysis is complete will provide you with meaningful codes to run in R.</li>
<li>Once you have run the code in R, the results are organised in the following way.</li>
<ul>
<li>Names of outcomes: Any spaces and special characters such as "(", ")", "!" are replaced by ".". 
For example, if the outcome was "Kidney failure", the altered name will be "Kidney.failure". 
This is to ensure that the outcome names are in a format that makes them compatible with analysis with R software. 
Any reference to outcome name in this section refers to this altered name.
</li>
<li>Main meta-analysis: The main meta-analysis results are stored in a variable formed by combining the term "MetaAnalysis_" with the outcome name. 
For example, "MetaAnalysis_Kidney.failure".</li>
<li>Funnel plot asymmetry (main meta-analysis only): Statistical tests for funnel plot asymmetry are stored in a variable formed by combining the term "Funnel_" with the outcome name. 
For example, "Funnel_Kidney.failure".</li>
<li>Subgroup analysis: The subgroup analysis results are stored in a variable formed by combining the terms "Subgroup_", the moderator variable name (which is also altered in the same way and for the same reasons as for the name of the outcome), and the outcome name.  
For example, for a variable "Age in years" for the outcome kidney failure, 
the results are stored in "Subgroup_Age.in.years_Kidney.failure".</li>
<li>Metagression: The metaregression results are stored in a variable formed by combining the term "Metaregression_" with the outcome name. 
For example, "Metaregression_Kidney.failure".</li>
<li>Sensitivity analysis (binary outcomes): The sensitivity analysis results are stored in a variable formed by combining the terms "SensitivityAnalysis_", the method for imputing data ("IMOR_", "BestWorst_", "WorstBest_"), and the outcome name.
For example, "SensitivityAnalysis_IMOR_Kidney.failure". 
In addition, to allow people to use the validated "metasens" R-package to perform sensitivity analysis of missing data, additional sensitivity analysis results 
are stored in a variable formed by combining the terms "SensitivityAnalysis_MetaMiss", the method for imputing data ("BestWorst_", "WorstBest_"), and the outcome name. 
For example, "SensitivityAnalysis_MetaMiss_BestWorst_Kidney.failure".
</li>
<li>Sensitivity analysis (continuous outcomes): The sensitivity analysis results  (indicating the results after excluding studies in which standard deviations were imputed) are stored in a variable formed by combining the term "SensitivityAnalysis_" with the outcome name.
For example, for an outcome "Health related quality of life", it would be "SensitivityAnalysis_Health.related.quality.of.life".
</li>
<li>Plots: The plots are stored in variables which are formed by combining the prefix "Plot_" before the above the variables. 
For example, "Plot_MetaAnalysis_Kidney.failure".</li>
</ul>
</ul>
</p>
<h3><b><i> References</i></b></h3>
<p><b><i> Package: Meta</i></b></p>
<ul>
<li> Balduzzi S, Rücker G, Schwarzer G. How to perform a meta-analysis with R: a practical tutorial. Evid Based Ment Health. 2019 Nov;22(4):153-160.</li>
</ul>
<p><b><i> Meta-analysis of rare events</i></b></p>
<ul>
<li> Dungang Li. Meta-Analysis of Rare Events. 2019. Wiley StatsRef: Statistics Reference Online. DOI: 10.1002/9781118445112.stat08167</li>
<li>Stijnen, T., Hamza, T.H. and Özdemir, P. (2010), Random effects meta-analysis of event outcome in the framework of the generalized linear mixed model with applications in sparse data. Statist. Med., 29: 3046-3067.</li>
</ul>
<p><b><i> Funnel plot asymmetry</i></b></p>
<ul>
<li> Sterne et al. Recommendations for examining and interpreting funnel plot asymmetry in meta-analyses of randomised controlled trials. BMJ 2011; 343 doi: https://doi.org/10.1136/bmj.d4002</li>
<li> Rücker G, Schwarzer G, Carpenter J. Arcsine test for publication bias in meta-analyses with binary outcomes. Stat Med. 2008 Feb 28;27(5):746-63.</li>
</ul>
<p><b><i> Metaregression</i></b></p>
<ul>
<li> Thompson SG, Higgins JP. How should meta-regression analyses be undertaken and interpreted? Stat Med. 2002 Jun 15;21(11):1559-73.</li>
</ul>
<p><b><i> Dealing with missing data</i></b></p>
<ul>
<li> Mavridis, D, White, IR. Dealing with missing outcome data in meta-analysis. Res Syn Meth. 2020; 11: 2– 13.</li>
<li> Higgins JP, White IR, Wood AM. Imputation methods for missing outcome data in meta‐analysis of clinical trials.Clin Trials.2008;5(3):225‐23.</li>
</ul>
')
Instructions_OCR_1 <- ('
<h3 style = "font-size:24px; color:purple;"><b>Instructions for optical character recognition (OCR)</b></h3>
This function allows optical character recognition (OCR) of the following languages: Chinese, Danish, Dutch, English, French, German, Italian, Japanese, Korean, Norwegian, Persian, Polish, Portugese, Russian, Spanish, Thai, Ukraine.
This means that you can extract text characters of these languages from image files or pdf files and then use an online tool such as Google translate or Microsoft translator to translate the text.
<h3><b><i>Preparation of files</i></b></h3>
<ul>
<li>If you have a pdf article, you can upload the pdf as it is to see how the characters are extracted.</li>
<li>This programme only functions well with chunks of text and not tables. 
Therefore, if the OCR on the pdf does not work well, we recommend taking screenshots of chunks of texts and storing these as image files,
which can then be uploaded into the programme. It also works only with few pages of pdf. 
If you upload a pdf with lots of pages, this may result in error. 
In this situation, we recommend that you split the pdf into pdfs with fewer pages 
(you can simply "print to pdf" a few pages at a time). 
</li>
<li>You may need to use image editing software such as Photos (preinstalled in windows) or other programmes to crop out unnecessary parts of the image, 
tilt the images to make the text appear in straight lines, improve the contrast etc to allow better OCR.</li>
</ul>
<h3><b><i>Uploading the files</i></b></h3>
<ul>
<li>Please scroll below these instructions.</li>
<li>First select from one of the languages from the dropdown menu.</li>
<li>Then upload the pdf or image files.</li>
<li>When the OCR is complete, a download button appears below these instructions.
You can download the output as text file.
You can then copy the text, and use online translators to translate text.
</li>
</ul>
')
Instructions_OCR_2 <- ('
<h3><b><i>Perform OCR by selecting the language and starting the upload below</i></b></h3>
')
# Instructions
Instructions_references_1 <- ('
<h3 style = "font-size:24px; color:purple;"><b>Instructions for combining searches from databases</b></h3>
<p>This function allows you to combine and deduplicate references from the following databases: 
PubMed, Ovid MEDLINE, Ovid EMBASE, 
Web of Science (Conference Proceedings Citation Index), 
Cochrane Library, ClinicalTrials.gov, 
and WHO (World Health Organization) ICTRP (International Clinical Trials Registry Platform).
</p>
<h3><b><i>Formats for downloading the searches</i></b></h3>
<ul>
<li><i>PubMed</i>: "nbib" format</li>
<li><i>Ovid MEDLINE</i>: "Excel sheet" format and "Complete reference" for the fields. 
If there are more than 1000 references, download the files as 1000 references per file.
</li>
<li><i>Ovid EMBASE</i>: "Excel sheet" format and "complete reference" for the field choices. 
If there are more than 1000 references, download the files as 1000 references per file.
</li>
<li><i>Web of Science(Conference Proceedings Citation Index)</i>: "tab delimited" format and "Full record". 
If there are more than 500 or 1000 references (depending on the account), download the files as 500 or 1000 references per file.
</li>
<li><i>Cochrane Library</i>: "CSV (Excel)" format; ensure that "Include abstract" box is checked.</li>
<li><i>ClinicalTrials.gov</i>: "csv" format; select all data fields.</li>
<li><i>WHO ICTRP</i>: "XML" format; if there are more than 100 references, download the files as 100 references in each file.</li>
</ul>
<h3><b><i>Formats for uploading the searches</i></b></h3>
<ul>
<li><i>PubMed</i>: no change to format</li>
<li><i>Ovid MEDLINE</i>: save the "citations" sheet as "csv" format. 
You will receive warnings that csv does not support multiple sheets and certain data formats. 
You can ignore the warnings and save the file as "csv" since we are interested only in the "citations" sheet.
</li>
<li><i>Ovid EMBASE</i>: save the "citations" sheet as csv format as for Ovid MEDLINE ignoring warnings about multiple sheets and formats.</li>
<li><i>Web of Science(Conference Proceedings Citation Index)</i>: no change to format.</li>
<li><i>Cochrane Library</i>: no change to format.</li>
<li><i>ClinicalTrials.gov</i>: no change to format.</li>
<li><i>WHO ICTRP</i>: no change to format.</li>
</ul>
<h3><b><i>Preparing for uploads (store the files in a single folder)</i></b></h3>
<p>All the downloaded search files should be stored in a single folder. 
While you can call this folder by any name, we recommend calling this folder "DatabaseSearches" to allow you to identify the folder which contains the files to be uploaded.
</p>
<h3><b><i>Preparing the "Index file"</i></b></h3>
<ul>
<li><i>Index file format</i>: csv</li>
<li><i>Index file name</i>: Although there is no requirement for the index file to have a specific name, we recommend calling this file "Index" (with extension, it will be "Index.csv")
<li>The index file must have exactly two columns with specific column names. 
All column names are case sensitive and are should not have empty spaces before or after the names.</li>
<li><b>Column 1</b>: "file.name" (without the quotes): enter the file name with the extensions. 
The extension can be obtained by right-clicking the file and selecting the properties. 
If the correct formats were downloaded and then prepared for uploads, then the files extensions in different databases are as follows.</li>
<ul>
<li><i>PubMed</i>: ".nbib"</li>
<li><i>Ovid MEDLINE</i>: ".csv" (after changing format as above)</li>
<li><i>Ovid EMBASE</i>: ".csv" (after changing format as above)</li>
<li><i>Web of Science(Conference Proceedings Citation Index)</i>: ".txt"</li>
<li><i>Cochrane Library</i>: ".csv"</li>
<li><i>ClinicalTrials.gov</i>: ".csv"</li>
<li><i>WHO ICTRP</i>: ".xml"</li>
</ul>
<li>Although there is no requirement to change the names of downloaded searches, for easy management and avoiding errors, we recommend renaming the files to the databases from which they were downloaded. 
If multiple files were downloaded from the same database (for example, because of the maximum limit of the references in each file), you can add a suffix, for example, "_1","_2" and so on. 
For example, if you downloaded 3 files from MEDLINE, you can name these "MEDLINE_1", "MEDLINE_2", "MEDLINE_3" 
(with extensions, the names will be "MEDLINE_1.csv", "MEDLINE_2.csv", "MEDLINE_3.csv").</li>
<li><b>Column 2</b>: "database" (without the quotes): This column should indicate the database from which the file was downloaded. 
These can have one of the following values:
"Pubmed", "Medline", "Embase","WOS", "Cochrane","CTgov", and "ICTRP" corresponding to the seven databases mentioned above. </li>
Each file.name (column 1) should have a corresponding database.
</ul>
<h3><b><i>Preparing the "Keywords file"</i></b></h3>
<ul>
<li><i>Keywords file format</i>: csv</li>
<li><i>Keywords file name</i>: Although there is no requirement for the keywords file to have a specific name, we recommend calling this file "Keywords" (with extension, it will be "Keywords.csv").
<li>The keywords file must have exactly two columns with specific column names. 
All column names are case sensitive and are should not have empty spaces before or after the names.</li>
<li><b>Column 1</b>: "keywords" (without the quotes): enter the keywords.</li>
<li><b>Column 2</b>: "concept" (without the quotes): enter the concept relevant to the keywords. 
Each keyword should be linked to only one concept or sub-concept. 
For example, in an intervention review, the concepts for the search will be: study design, population, intervention, and control. 
Each of the above concepts can be split into sub-concepts as required, for example, intervention 1, intervention 2 etc.
</li>
<li>Note that each concept can have multiple keywords but each keyword should be linked to one concept. 
If there are multiple concepts or subconcepts to which a keyword can be linked, choose the most relevant concept. 
As a result, the number of unique concepts should be fewer or equal to the number of keywords. 
Any keywords not linked to a concept will not be highlighted.
</li>
</ul>
<h3><b><i>Sample files</i></b></h3>
Sample index file and keywords file are available from the left tab under the "Download Training resources". 
You can use this as a template for column headings and specifying the database correctly (for index file).
')
Instructions_references_2 <- ('
<h3><b><i>Combine the searches and highlight the keywords in the references by uploading the index file below</i></b></h3>
')
Instructions_DEF_Int_1 <- ('
<h3 style = "font-size:24px; color:purple;"><b><i>Instructions for creating data extraction form plan (DEF plan)</i></b></h3>
This function allows creation of data extraction.Instructions for data extraction are also provided below, but are also available in the data extraction form.
Because of space restrictions, this function is available only on local version of R or R studio installed on your computer. Additional packages are to be installed as necessary.
<h4 style="text-align:left;"><b><i>General</i></b></h4>
<ul>
<li>When creating the short names, use informative abbreviations. There should be no special characters other than "underscore" in the short names.</li>
<li>The abbreviations will be used in graphs and for automated processing.</li>
<li>An abbreviations list should be provided in the manuscript (and this can be found in the data extraction plan that you created with the software).</li>
<li>The data extraction form design should be saved in the csv format.</li>
</ul>
<h4 style="text-align:left;"><b><i>Customising inclusion and exclusion criteria in studies</i></b></h4>
<ul>
<li>For extracting information on the inclusion and exclusion criteria in the studies, 
the questions should be prepared in the following format.</li>
<ul>
<li><i>Criteria format</i>: csv</li>
<li><i>Criteria file name</i>: Although there is no requirement for the "Criteria" file to have a specific name, we recommend calling this file "Criteria" (with extension, it will be "Criteria.csv").
<li>The Criteria file must have exactly two columns with specific column names. 
All column names are case sensitive and are should not have empty spaces before or after the names.</li>
<li><b>Column 1</b>: "variable_value" (without the quotes): Enter the full question. The full question should be informative (i.e., self-explanatory).</li>
<li><b>Column 2</b>: "short_names" (without the quotes): This should follow the general rules for short names. To allow automated subgroup analysis based on a feature, please enter the feature followed by a underscore and the specific criterion. As an example, if you want to perform a subgroup analysis based on smoking status, you can include the short names of the first criterion to be "Smoking_Non-smoker", the second criterion to be "Smoking_Past smoker", the third criterion to be "Smoking_Current smoker", and the fourth criterion to be "Smoking _Unknown status". This will allow the program to automatically perform a subgroup analysis of studies based on smoking status.</li>
</ul>
<li>If no file is uploaded or the file uploaded is in the wrong format, the data extraction form will have two columns "Other inclusion criteria" and "Other exclusion criteria" to obtain details on the inclusion and exclusion criteria of participants in the study.</li>
</ul>
<h4 style="text-align:left;"><b><i>Customising characteristics</i></b></h4>
<ul>
<li>The data extraction form includes the PROGRESS-PLUS characteristics to capture the disadvantaged groups as default. 
The classifications used for different criteria are available in the references. 
Therefore, there is no need to add these in the "Other characteristics" file.
<li>For extracting information on other characteristics of participants or other characteristics of the study in the studies, 
the questions should be prepared in the following format.</li>
<ul>
<li><i>Other characteristics format</i>: csv</li>
<li><i>Other characteristics file name</i>: Although there is no requirement for the "Other characteristics" file to have a specific name, we recommend calling this file "Other characteristics" (with extension, it will be "Other characteristics.csv").
<li>The Other characteristics file must have exactly four columns with specific column names. 
All column names are case sensitive and are should not have empty spaces before or after the names.</li>
<li><b>Column 1</b>: "variable_value" (without the quotes): Enter the detail that you want to appear in the data extraction form. 
Depending on what you enter in column 3, the following text is added  before the details you enter.</li>
<ul>
<li>number: "Enter the number of "</li>
<li>score: "Enter the mean "</li>
<li>text: "Enter: "</li>
</ul> 
<li><b>Column 2</b>: "short_names" (without the quotes): This should follow the general rules for short names. To allow automated calculation of proportion of participants based on a categorical variable, please enter the categorical variable followed by a underscore and the category. As an example, if you want to calculate the proportion of participants with different smoking status, you can include the first characteristic to be "Smoking_Non-smoker", the second characteristic to be "Smoking_Past smoker", the third characteristic to be "Smoking_Current smoker", and the fourth characteristic to be "Smoking _Unknown status". This will allow the program to automatically calculate the proportion of people who belonged to each smoking category.</li>
<li><b>Column 3</b>: "type_1" (without the quotes): Enter the type of data that this characteristic should capture. The options are "number", "text", "score" without quotes. 
If you want to extract the number of participants with a certain characteristic, say, severe disease, indicate "number". 
If you want to extract the mean value of a certain characteristic, say, Body Mass Index (BMI) or symptom severity score, indicate "score". 
If you want to extract some details that cannot be captured by numbers, say the classification used to record symptom severity (if symptom severity can be measured in multiple ways), indicate "text".</li>
<li><b>Column 4</b>: "study_level_intervention_level" (without the quotes): Enter whether the detail should be captured at study-level or intervention-level. The options are "study_level" and "intervention_level". 
For example, BMI or symptom severity will be at intervention-level and should be recorded as "intervention_level"; 
on the other hand, the classification used to record symptom severity will be at the study-level and should be recorded as "study_level".</li>
</ul>
<li>If no file is uploaded or the file uploaded is in the wrong format, the data extraction form will have only the participant characteristics related to PROGRESS-PLUS.</li>
</ul>
<h4 style="text-align:left;"><b><i>Customising intervention names</i></b></h4>
<ul>
<li>For direct comparison reviews, we recommend using one data extraction form for each comparison. Name the intervention_1 and intervention_2 (and short names) according to the interventions for which the data extraction is required, for example, in a comparison involving aspirin versus "no treatment" for preventing heart attacks in healthy population, intervention_1 will be "aspirin" and intervention_2 will be "no treatment". 
The shortnames of intervention_1 and intervention_2 will be "Aspirin" and "No_treatment". 
If the comparison involves a broader comparison, say platelet inhibitors versus no treatment for preventing heart attacks in healthy population, intervention_1 will be "Platelet inhibitors" and intervention_2 will be "No treatment". 
The respective short names will be "Platelet_inhibitors" and "No_treatment". 
You can request the data extractors to extract the information about the name of the platelet inhibitor in the additional names column of data extraction. 
If you find a trial that compares aspirin versus clopidogrel versus no treatment in healthy population, you can extract information in another row with the exact study name as the previous row. 
In the first row for that study, you should extract information for aspirin versus "no treatment". In the second row for that study, you should extract information for "clopidogrel" only under intervention_1. 
In factorial trials with and without a co-intervention, for example, in a trial of aspirin versus "no treatment" with and without lifestyle advice, we recommend treating these as two different studies and extract information on aspirin versus "no treatment" in people who received lifestyle advice in one row and in people who did not receive lifestyle advice in another row.</li>
<li>For network meta-analysis, name the intervention_1 as intervention_1 and intervention_2 as intervention_2 (for both the full names and short names) to allow NMA (this function is not available currently but is part of planned development). Enter the name and short-name of the intervention_1 and intervention_2. You can obtain the details of the intervention in the additional name of the intervention. A short-name will also be required to allow the graphs to be displayed well. This should follow the general rules for short names.</li>
</ul>
<h4 style="text-align:left;"><b><i>Customising outcome names</i></b></h4>
<ul>
<li>For extracting information on outcomes, the questions should be prepared in the following format.</li>
<ul>
<li><i>Outcomes format</i>: csv</li>
<li><i>Outcomes file name</i>: Although there is no requirement for the "Outcomes" file to have a specific name, we recommend calling this file "Outcomes" (with extension, it will be "Outcomes.csv").
<li>The Outcomes file must have exactly five columns with specific column names. 
All column names are case sensitive and are should not have empty spaces before or after the names.</li>
<li><b>Column 1</b>: "variable_value" (without the quotes): While it is obvious that the outcome names should be informative of what we want to extract, it is useful to indicate the type of outcome. For example, serious adverse events can be both a binary and count outcomes, as the number of people who developed serious adverse events and the number of serious adverse events are both important from a patient and healthcare funder perspective. To avoid confusion as to whether one is looking for the number of people who developed serious adverse events or the number of serious adverse events, one can clearly indicate serious adverse events (proportion) and or even serious adverse events (proportion; binary outcome) and serious adverse events (number; count outcome). 
One can also specify the timing of outcome in the outcome name. For example, health-related quality of life (HRQoL) can be measured at different time points. You might want to collect the short-term HRQoL, say within 3 months of an intervention, medium-term HRQoL between 3 months and 12 months, extended medium-term HRQoL between 1 year and 5 years, and long-term HRQoL beyond 5 years. You might want to specify this in the outcome name. For example, HRQoL (less than 3 months), HRQoL (from 3 months to 12 months), HRQoL (from 1 year to 5 years), and HRQoL (beyond 5 years).</li>
<li><b>Column 2</b>: "short_names" (without the quotes): This should follow the general rules for short names. 
If you are planning advanced meta-analytical techniques, such as multivariate meta-analysis to analyse correlated outcomes (this function is not available but is part of planned development), to allow automated detection that you are looking for performing analysis of correlated outcomes, use a short name that starts with "Correlated_" followed by the correlated outcomes followed by an underscore. For example, if you consider that HRQoL (less than 3 months) and HRQoL (from 3 months to 1 year) are correlated, you can use the short names, "Correlated_HRQoL_less_than_3_months" and "Correlated_HRQoL_from_3_to_12_months" which will allow the data to be prepared and analysis using multivariate meta-analysis.</li>
<li><b>Column 3</b>: "type_1" (without the quotes): Enter the type of data. The options are "binary", "continuous", "count", and "time-to-event".</li>
<li><b>Column 4</b>: "outcome_objective_subjective" (without the quotes): Enter whether the outcome is objective or subjective. The options are "objective" and "subjective".</li>
<li><b>Column 5</b>: "additional_text" (without the quotes): Enter any additional instructions related to the outcome. For example, which definitions or scale of outcome are acceptable.</li>
</ul>
</ul>
<h4 style="text-align:left;"><b><i>Creating the data extraction form</i></b></h4>
<ul>
<li>Once you have designed the data extraction form as above, You can also save the data extraction form plan to avoid having to enter all the details in future.</li>
<li>You can also upload the "1_Import_Summary.csv" and "2_Deduplicated_References.csv" that you generated when the references from different databases were combined. 
If uploaded, the references will automatically be included in the different sheets. Otherwise, the references must be included manually in the "Screening_First" sheet.
The formatting and the automated formulae are completed only for 100 rows.</li>
<li>Once the information is entered, the data extraction form is generated and can be downloaded.</li>
<li>The sheets are protected to prevent any inadvertent changes. There is no password. 
Before you send this to the co-authors, you might want to protect the sheets with a suitable password to prevent inadvertent changes by the co-author. 
Please note that any edits to the headings will cause errors when you use the program to process the data extraction form. Therefore, ensure that you have the headings that match with the data extraction form plan that you created.</li>
</ul>
<h4><b><i>Sample files</i></b></h4>
Sample criteria file, other characteristics file, outcome file, and overall design file are available from the left tab under the "Download Training resources". 
You can use this as a template for column headings and specifying the information correctly.
<h4 style="text-align:left;"><b><i>References</i></b></h4>
<ul>
<li>PROGRESS-PLUS:ONeill J, Tabish H, Welch V, Petticrew M, Pottie K, Clarke M, Evans T, Pardo Pardo J, Waters E, White H, Tugwell P. Applying an equity lens to interventions: using PROGRESS ensures consideration of socially stratifying factors to illuminate inequities in health. Journal of Clinical Epidemiology. 2014, 67 (1), pg. 56-64. doi:10.1016/j.jclinepi.2013.08.005</li>
<li>Place of residence: Used by PROGRESS-Plus group</li>
<li>Race (Ethnicity) classification: Based on Office of National Statistics 2021 ethnic groups (https://www.ons.gov.uk/peoplepopulationandcommunity/culturalidentity/ethnicity/bulletins/ethnicgroupenglandandwales/census2021#ethnic-groups-in-england-and-wales) and US Census (https://www.census.gov/topics/population/race/about.html). </li>
<li>Occupation classification: Based on International Standard of Classification of Occupations (https://ilostat.ilo.org/resources/concepts-and-definitions/classification-occupation/)</li>
<li>Religion classification: Based on Office of National Statistics 2021 religion (https://www.ons.gov.uk/census/census2021dictionary/variablesbytopic/ethnicgroupnationalidentitylanguageandreligionvariablescensus2021/religion/classifications)</li>
<li>Education: Based on International Standard Classification of Education https://uis.unesco.org/sites/default/files/documents/international-standard-classification-of-education-isced-2011-en.pdf</li> 
<li>Socio-economic status: This is based on household wealth, but even census data bases socio-economic status based on occupational levels (https://www.ons.gov.uk/methodology/classificationsandstandards/otherclassifications/thenationalstatisticssocioeconomicclassificationnssecrebasedonsoc2010#continuity-with-social-class-and-socio-economic-group). Therefore, no separate category was used. </li>
<li>Social capital: This is based on the social network. It is difficult to measure and is largely a surrogate (https://www.socialcapitalresearch.com/social-capital-measurement/). Therefore, no separate category was used. </li>
<li>Intervention characteristics (TIDieR checklist): Hoffmann TC, Glasziou PP, Boutron I, Milne R, Perera R, Moher D, Altman DG, Barbour V, Macdonald H, Johnston M, Lamb SE, Dixon-Woods M, McCulloch P, Wyatt JC, Chan AW, Michie S. Better reporting of interventions: template for intervention description and replication (TIDieR) checklist and guide. BMJ. 2014 Mar 7;348:g1687. doi: 10.1136/bmj.g1687. PMID: 24609605. </li>
<li>Outcome characteristics (Outcome taxonomy): Dodd S, Clarke M, Becker L, Mavergames C, Fish R, Williamson PR. A taxonomy has been developed for outcomes in medical research to help improve knowledge discovery. J Clin Epidemiol. 2018;96:84-92</li>
</ul>
<h3 style = "font-size:24px; color:purple;"><b><i>Instructions for data extraction</i></b></h3>
<h4 style="text-align:left;"><b><i>General</i></b></h4>
<ul>
<li>Do not cut cells or override validation. This will lead to errors when you summarise the data or perform analysis.</li>
<li>For direct comparison reviews, we recommend using one data extraction for each comparison. For network meta-analysis, use the same data extraction for all comparisons.</li>
<li>Cells that are filled with pale yellow or grey are cells that you cannot change.</li>
<li>Alternate rows are filled to allow easy distinction between rows.</li>
<li>Cells in light pink (alternating with white) are cells to be completed by first reviewer and those in light blue (alternating with white) are to be completed by second reviewer. Cells in medium orange (alternating with white) must be completed after agreement between the two reviewers.</li>
<li>Cells with dropdown menus accept only one of the choices from the dropdown menu. Other cells may have restrictions such as whole numbers only or decimal places only.</li>
<li>When information is missing, do not enter 0. Please leave the cells empty.</li>
<li>Certain cells are locked and you will not be able to edit them.</li>
</ul>
<h4 style="text-align:left;"><b><i>Study details</i></b></h4>
<ul>
<li><i>Name of the study</i>: This can be the acronym for the trial, trial ID, or last name of the first author followed by year of publication. This should be a unique ID for each study, for example: Doe 2021. If there was another trial with same name, you can differentiate this by stating Doe 2021 (1), Doe 2021 (2), etc. An alternative is to use numbers for studies, for example, S001, S002, S003, etc. However, for easy identification, even if you use S001, S002, S003, etc, we recommend that you add the trial name, ID, or last name of first author followed by year of publication.</li>
<li>To allow automated comparison of data, we recommend that the first and second reviewers use the same study names/IDs to refer to a study.</li>
<li><i>Record ID</i>: These are automatically generated by the program.</li>
<li>If you find additional references which are not retrieved by searching databases, you can add them to end of the references in "Screening_First" sheet. You must give a record name, and record reference. You can add up to 100 references manually.</li>
</ul>
<h4 style="text-align:left;"><b><i>Inclusion or exclusion of a study</i></b></h4>
<ul>
<li>The first step is screening the titles and abstracts for potential inclusion. You can do this in the sheets "Screening_First" and "Screening_Second" ("First" or "Second" indicating the first or second reviewer). There is no need to provide detailed reasons for exclusion at the level of screening, but you might want to add some comments in the "optional_comment" column if there is a possibility for another reviewer to disagree with your exclusion.</li>
<li>The next step is selection at the level of full text.</li>
<li>You should include all records of a study regardless of whether you find any additional information in the record. For example, you may not include details from a record, say a conference abstract as all the information is available in a more detailed manner in a full journal report. You would still collate all the records of the study and consider this record as included.</li>
<li>You can override your selection in the "FullText_First" or "FullText_Second" sheets. If your choice at the "full text" stage remains the same as "screening" stage, there is no need to complete the "selection_fulltext" column . For example, you might have excluded a record at "screening" stage and the other reviewer may have also done the same: there is no need to complete the "selection_fulltext" column. Similarly, you might have included a record at the "screening" stage and your decision based on "full text" review remains the same: there is no need to complete the "selection_fulltext" column.</li>
<li>If you excluded a study at "full text" stage (and not "screening" stage), you must provide a reason for exclusion. If the reason for exclusion is not within the exclusion list, you can select "Other reasons" and enter the reason in the additional details for exclusion column. Even if you select one of the reasons in the exclusion list, you can optionally include additional details, for example, which record was this record a duplicate of.</li>
</ul>
<h4 style="text-align:left;"><b><i>Data extraction</i></b></h4>
<ul>
<li>Data extraction is performed in the "DataExtractionForm_First" or "DataExtractionForm_Second" sheets.</li>
<li>Only records that have been indicated as "Included" in the "selection_final" column in the" FullText_First" sheet which is based on the selection of the first reviewer at the "screening" stage and "full text" stage will be available for selection in the "Record ID" column in the "DataExtractionForm_First" sheet. Similarly, only records that have been indicated as "Included" in the "selection_final" column in the" FullText_Second" sheet which is based on the selection of the first reviewer at the "screening" stage and "full text" stage will be available for selection in the "Record ID" column in the "DataExtractionForm_Second" sheet.</li>
<li>Enter each outcome in a study in a new row. Please ensure that you complete the "Study name or ID" and the appropriate "Record ID" for the outcome.</li>
<li>Participant characteristics in the first row of a study are used for automated tabulation. Therefore, there is no need to copy these to each row.</li>
<li>Participant flow, follow-up, and risk of bias assessments from the first row of a study are used for automated tabulation. These need to be completed for each outcome only if they are different from the information in the first row. Please also see the instructions under the relevant sections.</li>
</ul>
<h4 style="text-align:left;"><b><i>Study author details</i></b></h4>
<ul>
<li>If corresponding author is not stated, please indicate the first author.</li>
<li>For contact details of corresponding author, enter the email if possible. If this is not possible, enter the institutional or departmental email. If this is not possible, then record the department or institution address and phone number if available.</li>
</ul>
<h4 style="text-align:left;"><b><i>Participant characteristics</i></b></h4>
<ul>
<li>If the participant characteristics are missing for each intervention, please enter the details for all intervention groups under the first intervention group.</li>
</ul>
<h4 style="text-align:left;"><b><i>Participant flow</i></b></h4>
<ul>
<li>Some aspects of participant flow such as number screened and included are at the study-level while other aspects such as number randomised or initially included and missing data numbers are collected at the intervention level.</li>
<li>In many studies, participant flow is similar for most outcomes. While it is possible to enter the information for each outcome, it is probably more efficient to enter this information for most outcomes and complete the information at the outcome level when it is different from the general assessment.</li>
<li>If an intention-to-treat analysis with an appropriate method of imputation (depending on the reason for missing data) was used for all participants initially included in the study was available, such participants should not be considered as missing outcome data.</li>
<li>If the number of participants with missing outcome data is not clear, do not enter "0". Leave this field empty.</li>
</ul>
<h4 style="text-align:left;"><b><i>Intervention</i></b></h4>
<ul>
<li>Additional names are required only when a network meta-analysis is performed or when a broad intervention is used. For example, in a comparison of platelet inhibitors versus no treatment for preventing heart attacks in healthy population, it is useful to know the platelet inhibitor (for example, aspirin or clopidogrel) used in the study. If you have added an additional name, the additional name and short names of the intervention should be harmonised (i.e., the two reviewers use the same additional names and short names) after the data extraction to allow automated comparison of data and analysis of data.</li>
<li>If you find studies which include more treatment arms than what you are comparing, you can include only the arms relevant for your review.</li>
<li>Sometimes, you may find that multiple arms are eligible for a single comparison in the review. For example, in a comparison of platelet inhibitors versus no treatment for preventing heart attacks in healthy population, you may find a trial that compares aspirin versus clopidogrel versus no treatment in healthy population. In this situation, you can extract information in another row with the exact study name as the previous row. In the first row for that study, you should extract information for "aspirin" versus "no treatment". You must add the additional names and short names to indicate that this row refers to "aspirin". In the second row for that study, you should extract information for "clopidogrel" only. You must add the additional names and short names to indicate that this row corresponds to "clopidogrel". You must also ensure that the additional names and short names are under the correct intervention, i.e., aspirin, clopidogrel, or other platelet inhibitors are under platelet inhibitors and not "no treatment". You can add as many interventions as you want for a study, provided that the additional names and short names are under the correct intervention. In network meta-analysis, there is no predefined intervention_1 and intervention_2. Therefore, you can add an intervention under intervention_1 or intervention_2.</li>
<li>Sometimes you may find factorial trials in which the intervention is compared with the comparator in the presence or absence of a co-intervention, for example, a trial of "aspirin" versus "no treatment" with and without lifestyle advice. In such situations, we recommend extracting data for the comparison of "aspirin" versus "no treatment" with lifestyle advice and the comparison of "aspirin" versus "no treatment" without lifestyle advice separately as two different studies (by adding a suffix) and extract information on "aspirin" versus "no treatment" in people who received lifestyle advice in one row and in people who did not receive lifestyle advice in another row.</li>
</ul>
<h4 style="text-align:left;"><b><i>Follow-up</i></b></h4>
<ul>
<li>In many studies, follow-up is similar for most outcomes. While it is possible to enter the information for each outcome, it is probably more efficient to enter this information for most outcomes and complete the information at the outcome level when it is different from the general assessment. Rarely, the follow-up is different for the different intervention and the comparator. In such a situation, you can enter this information separately for each group.</li>
</ul>
<h4 style="text-align:left;"><b><i>Risk of bias</i></b></h4>
<ul>
<li>As for follow-up, in many studies, risk of bias domains which are assessed at outcome level are similar for most outcomes. While it is possible to enter the information for each outcome, it is probably more efficient to enter this information for most outcomes and complete the information at the outcome level when it is different from the general assessment.</li>
<li>If you include randomised controlled trials and observational studies in your review, you need to complete the RoB 2.0 for randomised controlled trials and ROBINS-I for non-randomised studies for intervention. Therefore, you should completely one of them.</li>
<li>If you are including cluster randomised controlled trials or cross-over randomised controlled trials, you need to complete only RoB 2.0 (cluster RCTs) or RoB 2.0 (cross-over RCTs) tools. There is no need to complete the generic RoB 2.0 tool for the specific study.</li>
</ul>
<h4 style="text-align:left;"><b><i>Outcomes</i></b></h4>
<ul>
<li>Add one outcome in each row. Please ensure that you copy the study names and details for each row.</li>
<li>Additional names are required only when a broad outcome is used. For example, Patient Reported Outcome Measures may include a wide range of patient reported outcome measures but you want to analyse different patient reported outcome measures separately. In such a case add an additional name. If you have added an additional name, the additional name and short names of the outcome should be harmonised (i.e., the two reviewers use the same additional names and short names) after the data extraction to allow automated comparison of data and analysis of data.</li>
<li>In randomised controlled trials, the preferred data are as follows.</li>
<ul>
<li><i>Binary outcomes</i>: number of people with event and number included in analysis for each group.</li>
<li><i>Continuous outcomes</i>: mean, standard deviation, and number included in analysis for each group.</li>
<li><i>Count outcomes</i>: number of events and number included in analysis for each group.</li>
<li><i>Time-to-event outcomes</i>: hazard ratio and 95% confidence intervals.</li>
</ul>
</ul>
<ul>
<li>For observational studies (including cohort studies), the effect measure and its confidence interval may be the only information that is available in observational studies and it is useful to obtain the effect measure adjusted for confounders and unadjusted for confounders. Occasionally the effect measure and its standard error may be available, in which case, you can extract this information.</li>
<li>When some of the information is missing, it may be possible to calculate or impute this information from other information in the trials. This information is required only when the preferred information in the previous two points are not available.</li>
<li>Data can be extracted from graph. For guidance, please see guidance under "Data extraction from plots".</li>
<li>There are simple calculators that are available from the "Calculators" sheet. These can be used to show the co-reviewer how you arrived at some numbers and include simple addition, simple subtraction, calculation of months from days, weeks, and years, and calculation of hours from minutes. We have also added a generic calculator which converts multiple values using a conversion factor that you can specify. You can copy and paste pictures after entering the data into the "Calculations_Co_reviewer" sheet. This will avoid the need for discussions between the reviewers as to how some numbers were calculated.</li>
</ul>
')
Instructions_DEF_Int_2 <- ('
<h3><b><i>Create data extraction form by entering the details below</i></b></h3>
')
Instructions_PlotExtract_1 <- ('
<h3 style = "font-size:24px; color:purple;"><b>Instructions for extracting data from plots for inclusion in systematic review of inteventions</b></h3>
This version supports extraction of data from Kaplan-Meier plots, box plots, bar plots, and line plots.
<h3><b><i>Preparation of plots before uploading</i></b></h3>
<ul>
<li>We recommend reducing the size of the plots to less than 700 pixels in both height and width. This is possible in most photo edit software. If you use Windows operating system, MS Paint is pre-installed. You can use MS Paint to decrease the pixels. Uploading very large image files is not supported, but files with more than 700 pixels, it can take long time between selecting the data points.</li>
</ul>
<h3><b><i>General instructions</i></b></h3>
<ul>
<li>You need to enter the minimum and maximum values of y-axis (vertical axis) for all the plots and for the x-axis (horizontal axis) as well for Kaplan-Meier plots and line plots. 
These are for "calibration" purposes,i.e., to convert the pixels to absolute values. 
Therefore, we recommend that you select the points which have numbers next to them, so that it is easy to enter the numbers without any guesswork. 
This might mean that there are datapoints beyond the maximum value. However, there are no problems with that. The absolute values are calculated based on the "calibration".</li>
<li>At each step, the next data point to be selected is indicated in "Next step". Please follow these instructions carefully. Otherwise, this may result in wrong values; sometimes the app may stop working. If this is case, reload the app and select the correct data points as indicated in "Next step". If you are not seeing the "Next step" after entering the time points, please scroll screen to the top. You will be able to see the "Next step".</li>
<li>You are able to remove all the datapoints that you selected in the plot or you are able to remove only the last datapoint. These functions (particularly removing only the last data point) are useful if you notice that you have selected the datapoint(s) wrongly. If you are not seeing the buttons to remove the datapoints after entering the first data point, please scroll screen to the top. You will be able to see the buttons.</li>
<li>Once you have entered the minimum and maximum values in x axis, selected the time points, and selected the minimum and maximum data points for Kaplan-Meier plots and line plots, vertical dotted lines will appear at the specified time points. 
These can help you decide whether you have "calibrated" correctly and also is helpful to guide the selection of the data point corresponding to that time point. 
Once these "vertical guides" appear, you just need to focus on the y-axis. The data point will automatically "bind" to the vertical guide representing the time point indicated. This is difficult to explain by text, try this practically, you can easily see how this works. 
For the remaining plot types, when multiple data points in the same vertical line are required, for example, box plot which requires three data points in a straight line or bar plots with error bars which again require multiple data points in the same vertical line, a vertical dotted line will appear after the first data point is selected. For example, in a box plot if mean (or usually median) is clicked, a vertical line will appear and the lower and upper quartiles will "bind" automatically to this vertical line.</li>
<li>You can select up to 10 groups and 10 time points to extract the data.</li>
<li>You can save the plot with the data points and vertical lines included.</li>
<li>You can download the values corresponding to the data points.</li>
</ul>
<h3><b><i>Kaplan-Meier plots</i></b></h3>
<ul>
<li>At present, only Kaplan-Meier curves with descending curves are supported. If you find the occasional paper with ascending curves, use the "line plot" function to calculate the values at different time points and use the "Process data" function to convert the data to a format that can be used for meta-analysis.</li>
<li>In general, choose time points in such a way that less of 20% of population at risk have developed the event during the interval (i.e., start and end of the interval).</li>
<li>One should not choose time points beyond the maximum follow-up.</li>
<li>One can also choose fixed time points across studies, for example, 12 months, 36 months, 60 months, and so on.</li>
<li>If there are no events in either group during an interval, it does not contribute to the calculations. For example, if you plan to use fixed time intervals, say 12 months, 36 months, and 60 months, but there are no events between 12 months and 36 months, you can simply obtain the values at 12 months and 60 months.</li>
<li>The probability of no events at a time point cannot be higher than the probability of no events at an earlier time point. For example, the probability of no heart attacks at 60 months cannot be higher than the probability of survival at 12 months or 36 months.</li>
<li>If there are no events in one group during an interval, this contributes to the calculations. However, this can mean that when you select the data points for the intervention with no events, as you click the data points, you might have selected a data point which is a fraction higher than the previous data point inadvertently. This will result in non-conversion of the results to a format required for meta-analysis. One option is to click again without moving the pointer. Because of the "binding" function, both the data points will be calculated as having the same values. For example, if there are no events in one of the groups between 12 months and 36 months, you can move the pointer to a level that represents 12 months and click twice. This will calculate the same value for both 12 months and 36 months. Alternatively, you can obtain the datapoint values, make any corrections, and use the "Process data" function to convert the data to a format suitable for meta-analysis.</li>
<li>One needs to enter the minimum and maximum follow-up for the calculation of hazard ratio. This is the preferred option. If this is not available directly available from the report, you can obtain this information or estimate this information from other values. One way is to record the earliest "censoring", indicated usually by small vertical lines in the Kaplan-Meier curves (as in the sample Kaplan-Meier plot) or by crosses. One can click on the earliest "censoring" in any of the groups and the last "censoring" in any of the groups. If this is not available it can be estimated from other parameters such as "Median follow-up and recruitment duration", "Date of analysis, date of first recruitment, and last recruitment", or  "Data of submission, date of first recruitment, and last recruitment" in that order of preference.</li>
<li>One also needs the number of participants in each group for the calculations.</li>
<li>In a direct comparison review, which involves a broad comparison, say platelet inhibitors versus "no treatment", you might find trials which compare two different platelet inhibitors, say aspirin and clopidogrel versus placebo. In such a situation, one option might be to include comparisons of aspirin versus placebo and clopidogrel versus placebo in the same analysis. However, this might mean that the same participans from placebo are included twice in the analysis, which is incorrect. If you are extracting data from Kaplan-Meier plots, you can divide the number of participants in placebo group by the number of intervention groups (i.e., two in this case: aspirin and clopidogrel) while entering the information about the number of participants. For example, if the numbers of participants included in the aspirin, clopidogrel, and placebo groups were 100, 102, and 100, you would extract data points related to aspirin versus placebo first, and enter the number of participants as 100 and 50 (100 divided by 2) to calculate the data in a format suitable for meta-analysis for aspirin versus placebo. In the second extraction, you would extract data points related to clopidogrel versus placebo, and enter the number of participants as 102 and 50 (100 divided by 2)  to calculate the data in a format suitable for meta-analysis for clopidogrel versus placebo. For network meta-analysis, you can select 3 groups, extract the data for all three groups in a single data extraction, and not alter the number of participants.</li>
</ul>
<h3><b><i>References</i></b></h3>
<ul>
<li>Tierney, J.F., Stewart, L.A., Ghersi, D. et al. Practical methods for incorporating summary time-to-event data into meta-analysis. Trials 8, 16 (2007). 
https://doi.org/10.1186/1745-6215-8-16</li>
</ul>
')
Instructions_PlotExtract_2 <- ('
<h3><b><i>Start data extraction from plots by uploading a plot below</i></b></h3>
')
Instructions_Process_Int_1 <- ('
<h3><b><i>Instructions to appear soon</i></b></h3>
')
Instructions_Process_Int_2 <- ('
<h3><b><i>Start data processing by selecting one of the options below</i></b></h3>
')
Instructions_Interpret_Int_1 <- ('
<h3><b><i>Instructions to appear soon</i></b></h3>
')
Instructions_Interpret_Int_2 <- ('
<h3><b><i>Start data interpretation by selecting one of the options below</i></b></h3>
')

# User interface ####
ui <- fluidPage(
  # Change background colour and decide alignments spacing etc for headings
  tags$head(
    tags$style(HTML('
        body {background-color: aliceblue;color: black;}
        p {text-align: left; margin-top: 3px; margin-bottom: 2px;line-height: 1.6;font-family:Sans-Serif}
        h1 {text-align: center;font-family:arial bold;}
        h2 {text-align: center; margin-top: 6px;font-family:arial bold;}
        h3 {text-align: left; margin-top: 6px;font-family:arial bold;}
        h4 {text-align: center; margin-top: 3px;font-family:arial bold;}
        table, th, td, tbody {border-collapse: collapse}
        table, th, td {border: 1px solid black}
        th, td {padding-top: 5px;
                padding-bottom: 5px;
                padding-left: 10px;
                padding-right: 10px;}
        th {color: white; background: darkgreen; }
        table.center {margin-left: auto; margin-right: auto;}
        #MA_Int{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #skip_instructions_Int{background-color:maroon; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #DataUpload_instructions_page_Int{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #UploadData_Int{background-color:darkviolet; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Reset_MA{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Reset_MetaAnalysisPlan_Int{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Reset_MetaAnalysisPlan_Int_2{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Modify_MA_Row{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Modify_MA_RowsOfSimilarType{background-color:darkviolet; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #ModifyOneMoreMA_Row{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Run_MetaAnalysisPlan{background-color:darkblue; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #ReferenceScreener{background-color:darkblue; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #references_one_more{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #skip_instructions_references{background-color:maroon; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #DEF{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #skip_instructions_DEF_Int{background-color:maroon; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #DEF_Plan_Int_Change_Choice{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #DEF_Plan_Int_plan_submit{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #DEF_ImportSummary_Change_Choice{background-color:darkblue; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #DEF_Create_One_more{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #OCR{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #OCR_one_more{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #skip_instructions_OCR{background-color:maroon; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #PlotExtract{background-color:darkblue; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_UploadPlot{background-color:darkblue; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_UploadNewPlot{background-color:darkblue; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_PlotRotate{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_DownloadModifiedPlot{background-color:darkblue; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Confirm_DataPoints{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Skip_MinMax{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_KM_Submit_Group_Numbers{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_DownloadResults{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Confirm_PlotType{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Change_PlotType{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Confirm_y_min_y_max{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Change_y_min_y_max{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Confirm_Groups{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Change_Groups{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Confirm_TimePoints{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Change_TimePoints{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Confirm_KM_TimePoints{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Change_KM_TimePoints{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_KM_Min_Max_Reset_Questions{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_KM_Min_Max_Submit_Questions{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_ResetPlot{background-color:maroon; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
#PlotExtract_Remove_Last{background-color:maroon; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #skip_instructions_PlotExtract{background-color:maroon; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Process_Int{background-color:purple; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Process_Int_one_more{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #skip_instructions_Process_Int{background-color:maroon; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Interpret_Int{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #Interpret_Int_one_more{background-color:darkgreen; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
        #skip_instructions_Interpret_Int{background-color:maroon; text-align:center; font-size: 26px; font-family:arial bold; color: white;}
      '))
  ),
  # Title panel
  fluidRow(headerPanel(div(
    column(width = 1, HTML('<p><img src = "Logo.png" width="194.4" height="214.5" /></p>')), 
    column(width = 8, offset= 2, HTML('<h1 style = "color:white; background-color:darkblue; font-family:arial bold;"><b>Meta-analysis in systematic reviews of intervention</b></h1>')),
    column(width = 8, offset= 2, HTML('<h2 style = "color:#254636; font-family:arial bold;"><b>Evidence-Based Healthcare: Best Information for Best Practice</b></h2>')),
    column(width = 8, offset= 2, HTML('<h3 style = "color:#254636; font-family:arial bold;; text-align:center"><b>Developed by: </b><i>Professor Kurinchi Gurusamy, University College London</i></h3>')),
    column(width = 8, offset= 2, HTML('<h2 style = "color:#254636; font-family:arial bold;"><b>EQUity through biomedicAL research (EQUAL) group</b></h2>')),
  ))),
  
  # Split the user interface into two - the sidebar for input and main panel for output
  sidebarLayout(
    # Side panel
    sidebarPanel(
      width = 3,
      radioButtons("Activity", HTML('<p style = "font-size:18px"><b>I want to: </b></p>'), choices = FirstSelection[1:2], inline = FALSE, width = "100%"),
      HTML('<h3><b>Download Training resources</b></h3>'),
      downloadButton("SampleData_Int", HTML("Sample data (intervention review)")),
      HTML('<br><br>'),
      downloadButton("SampleMetaAnalysisPlan_Int", HTML("Sample Meta-analysis plan (interv. review)")),
      HTML('<br><br>'),
      downloadButton("SampleIndex_references", HTML("Sample Index file (references)")),
      HTML('<br><br>'),
      downloadButton("SampleKeywords_references", HTML("Sample Keywords file (references)")),
      HTML('<br><br>'),
      downloadButton("SampleCriteria_DEF", HTML("Sample Criteria file (Data extraction form)")),
      HTML('<br><br>'),
      downloadButton("SampleOther_characteristics_DEF", HTML("Sample Characteristics file (Data extraction form)")),
      HTML('<br><br>'),
      downloadButton("SampleOutcomes_DEF_Int", HTML("Sample Outcomes file (Data extraction form)")),
      HTML('<br><br>'),
      downloadButton("SampleDEF_Plan", HTML("Sample Data extraction plan file (Data extraction form)")),
      HTML('<br><br>'),
      downloadButton("SampleKM_Plot", HTML("Sample Kaplan-Meier plot file (Data extraction)")),
      HTML('<br><br>'),
      downloadButton("SampleBox_Plot", HTML("Sample Box plot file (Data extraction)")),
      HTML('<br><br>'),
      downloadButton("SampleBar_Plot", HTML("Sample Bar plot file (Data extraction)")),
      HTML('<br><br>'),
      downloadButton("SampleLine_Plot", HTML("Sample Line plot file (Data extraction)")),
      HTML('<h3><b>Convert Review Manager output into suitable format</b></h3>'),
      fileInput("Upload_RevMan5", "Please upload the RevMan 5 data (Accepted format: txt, csv)",
                multiple = FALSE,
                accept = c(".txt",".csv")
      ),
      fileInput("Upload_RevManWeb", "Please upload the RevMan Web data (Accepted format: txt, csv)",
                multiple = FALSE,
                accept = c(".txt",".csv")
      ),
      downloadButton("ProcessedRevManData_Int", HTML("Download processed RevMan data")),
      HTML('<h3><b>Code to run the analysis in R</b></h3>'),
      downloadButton("Code_Int", HTML("Download R Code to run the analysis")),
      HTML('<h3><b>Download the full programme code</b></h3>'),
      downloadButton("ProgrammeCode", HTML("Download Full programme code")),
    ),
    mainPanel(
      # Create input and output tabs
      fluidRow(
        htmlOutput("htmlTitle")
      ),
      fluidRow(
        column(width=12, 
               tabsetPanel(id = "ActivitySelector",
                           type = "hidden",
                           tabPanelBody("panel1",
                                        column(width = 12,
                                               htmlOutput("htmlInstructions")
                                        ),
                           ),
                           tabPanelBody("panel2",
                                        column(width=12,
                                               tags$div(id = "div_Menu", tags$style("#div_Menu div {margin-bottom: 10px}"),
                                                        fluidRow(
                                                          column(width = 6,
                                                                 actionButton("MA_Int","Perform meta-analysis in systematic reviews of intervention")
                                                          ),
                                                        ),
                                                        fluidRow(
                                                          column(width = 6, 
                                                                 actionButton("ReferenceScreener","Combine database searches and highlight key words")
                                                          ),
                                                        ),
                                                        fluidRow(
                                                          column(width = 6, 
                                                                 actionButton("DEF","Create data extraction form (this does not work online - download the programme code and run this from local computer.")
                                                          ),
                                                        ),
                                                        fluidRow(
                                                          column(width = 6, 
                                                                 actionButton("OCR","Optical character recognition to enable online translation")
                                                          ),
                                                        ),
                                                        fluidRow(
                                                          column(width = 6, 
                                                                 actionButton("PlotExtract","Extract data from plots")
                                                          ),
                                                        ),
                                                        fluidRow(
                                                          column(width = 6, 
                                                                 actionButton("Process_Int","Process data (Intervention review)")
                                                          ),
                                                        ),
                                                        fluidRow(
                                                          column(width = 6, 
                                                                 actionButton("Interpret_Int","Interpret data (Intervention review)")
                                                          ),
                                                        ),
                                               ),
                                        ),
                           ),
                           tabPanelBody("panel3",
                                        column(width = 12,
                                               uiOutput(outputId = "skip_instructions_Int_UI"),
                                               htmlOutput("htmlInstructions_Int"),
                                               actionButton("DataUpload_instructions_page_Int", "Start analysis by uploading data")
                                        ),
                           ),
                           tabPanelBody("panel4",
                                        column(width=12,
                                               tags$div(id = "div_MetaAnalysisPlan_Int", tags$style("#div_MetaAnalysisPlan_Int div {margin-bottom: 10px}"),
                                                        uiOutput(outputId = "UploadData_Int_UI"),
                                                        htmlOutput("htmlMsg1_Int"),
                                                        htmlOutput("htmlMsg2_Int"),
                                                        HTML("<br>"),
                                                        uiOutput(outputId = "Reset_MetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "Header_Upload_Data_Int_UI"),
                                                        uiOutput(outputId = "Upload_Data_Int_UI"),
                                                        uiOutput(outputId = "Header_MetaAnalysisPlan_Choice_Int_UI"),
                                                        uiOutput(outputId = "MetaAnalysisPlan_Choice_Int_UI"),
                                                        uiOutput(outputId = "Header_Upload_MetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "Upload_MetaAnalysisPlan_Int_UI"),
                                                        htmlOutput("htmlUpload_MetaAnalysisPlan_Int_Error_Warning"),
                                                        uiOutput(outputId = "MA_Outcome_UI"),
                                                        uiOutput(outputId = "MA_EffectMeasure_UI"),
                                                        uiOutput(outputId = "MA_ContinuityCorrection_UI"),
                                                        uiOutput(outputId = "MA_RareEventsMethod_UI"),
                                                        uiOutput(outputId = "MA_FixedEffect_UI"),
                                                        uiOutput(outputId = "MA_PredictionInterval_UI"),
                                                        uiOutput(outputId = "MA_HKAdjustment_UI"),
                                                        uiOutput(outputId = "MA_Method_UI"),
                                                        uiOutput(outputId = "MA_Summary_UI"),
                                                        uiOutput(outputId = "MA_Minimum_Studies_UI"),
                                                        uiOutput(outputId = "MA_Metabias_Any_UI"),
                                                        uiOutput(outputId = "MA_Metabias_Heterogeneity_UI"),
                                                        uiOutput(outputId = "MA_IMOR1_UI"),
                                                        uiOutput(outputId = "MA_IMOR2_UI"),
                                                        uiOutput(outputId = "MA_SubgroupSelection_UI"),
                                                        fluidRow(
                                                          column(width= 5, uiOutput(outputId = "Modify_MA_Row_UI"),
                                                          ),
                                                          column(width= 7, uiOutput(outputId = "Reset_MA_UI"),
                                                          ),
                                                        ),
                                                        fluidRow(
                                                          column(width = 8, uiOutput(outputId = "Modify_MA_RowsOfSimilarType_UI"),
                                                          ),
                                                        ),
                                                        htmlOutput("htmlMA_Modify_Msg"),
                                                        fluidRow(
                                                          column(width = 8, uiOutput(outputId = "ModifyOneMoreMA_Row_UI"),
                                                          ),
                                                        ),
                                                        fluidRow(
                                                          column(width = 8, uiOutput(outputId = "Run_MetaAnalysisPlan_UI"),
                                                          ),
                                                        ),
                                                        uiOutput(outputId = "Header_SelectedMetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "Download_SelectedMetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "SelectedMetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "Header_DefaultMetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "Download_DefaultMetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "DefaultMetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "Header_RevManMetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "Download_RevManMetaAnalysisPlan_Int_UI"),
                                                        uiOutput(outputId = "RevManMetaAnalysisPlan_Int_UI"),
                                               )
                                        ),
                           ),
                           tabPanelBody("panel5",
                                        column(width=12,
                                               tags$div(id = "div_Results_Int", tags$style("#div_Results_Int div {margin-bottom: 16px}"),
                                                        uiOutput(outputId = "Reset_MetaAnalysisPlan_Int_UI_2"),
                                                        uiOutput(outputId = "Header_ResultsTable_Int_UI"),
                                                        uiOutput(outputId = "ResultsTableDownload_Int_UI"),
                                                        uiOutput(outputId = "AllPlots_Download_Int_UI"),
                                                        uiOutput(outputId = "OutcomeSummary_Int_UI"),
                                                        uiOutput(outputId = "ResultsTable_Int_UI"),
                                               ),
                                        ),
                           ),
                           tabPanelBody("panel6",
                                        column(width=12,
                                               tags$div(id = "div_references", tags$style("#div_references div {margin-bottom: 16px}"),
                                                        uiOutput(outputId = "skip_instructions_references_UI"),
                                                        htmlOutput("htmlMsg1_references"),
                                                        uiOutput(outputId = "references_one_more_UI"),
                                                        htmlOutput("htmlInstructions1_references"),
                                                        uiOutput(outputId = "references_file1_UI"),
                                                        uiOutput(outputId = "references_file2_UI"),
                                                        uiOutput(outputId = "download_UI_1_references"),
                                                        uiOutput(outputId = "references_file3_UI"),
                                                        uiOutput(outputId = "download_UI_2_references"),
                                                        htmlOutput("htmlInstructions2_references"),
                                               ),
                                        ),
                           ),
                           tabPanelBody("panel7",
                                        column(width=12,
                                               tags$div(id = "div_DEF_Int", tags$style("#div_DEF_Int div {margin-bottom: 16px}"),
                                                        uiOutput(outputId = "skip_instructions_DEF_Int_UI"),
                                                        htmlOutput("htmlMsg1_DEF_Int"),
                                                        htmlOutput("htmlMsg2_DEF_Int"),
                                                        htmlOutput("htmlInstructions1_DEF_Int"),
                                                        htmlOutput("Header_DEF_Int"),
                                                        uiOutput(outputId = "DEF_Plan_Int_Choice_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_Change_Choice_UI"),
                                                        uiOutput(outputId = "DEF_ImportSummary_Change_Choice_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_NRS_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_cluster_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_cross_over_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_per_protocol_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_intervention_1_name_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_intervention_1_short_name_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_intervention_2_name_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_intervention_2_short_name_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_criteria_Upload_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_other_characteristics_Upload_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_outcomes_Upload_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_plan_submit_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Int_Upload_UI"),
                                                        uiOutput(outputId = "DEF_ImportSummary_Choice_UI"),
                                                        uiOutput(outputId = "DEF_ImportSummary_Upload_UI"),
                                                        uiOutput(outputId = "DEF_References_Upload_UI"),
                                                        uiOutput(outputId = "DEF_Plan_Download_UI"),
                                                        uiOutput(outputId = "DEF_Download_UI"),
                                                        htmlOutput("htmlInstructions2_DEF_Int"),
                                               ),
                                        ),
                           ),
                           tabPanelBody("panel8",
                                        column(width=12,
                                               tags$div(id = "div_ocr", tags$style("#div_ocr div {margin-bottom: 16px}"),
                                                        uiOutput(outputId = "skip_instructions_OCR_UI"),
                                                        htmlOutput("htmlMsg1_OCR"),
                                                        uiOutput(outputId = "OCR_one_more_UI"),
                                                        uiOutput(outputId = "OCR_text_Download_UI"),
                                                        htmlOutput("Header_OCR"),
                                                        uiOutput(outputId = "OCR_text_UI"),
                                                        htmlOutput("htmlInstructions1_OCR"),
                                                        uiOutput(outputId = "OCR_language_UI"),
                                                        uiOutput(outputId = "OCR_upload_UI"),
                                                        htmlOutput("htmlInstructions2_OCR"),
                                               ),
                                        ),
                           ),
                           # DE from plots Interface Working here ####
                           tabPanelBody("panel9",
                                        fluidRow(
                                        column(width=12,
                                               tags$div(id = "div_PlotExtract", tags$style("#div_PlotExtract div {margin-bottom: 16px}"),
                                                        uiOutput(outputId = "skip_instructions_PlotExtract_UI"),
                                                        htmlOutput("Header_PlotExtract"),
                                                        htmlOutput("htmlInstructions1_PlotExtract"),
                                                        column(width = 4,
                                                               uiOutput("PlotExtract_UploadPlot_UI"),
                                                               uiOutput("PlotExtract_UploadNewPlot_UI"),
                                                               uiOutput("PlotExtract_PlotRotate_UI"),
                                                               uiOutput("PlotExtract_DownloadModifiedPlot_UI"),
                                                               htmlOutput("PlotExtract_DisplayNextStep"),
                                                               uiOutput("PlotExtract_Confirm_DataPoints_UI"),
                                                               uiOutput("PlotExtract_Skip_MinMax_UI"),
                                                               uiOutput("PlotExtract_KM_Min_Max_Question_1_UI"),
                                                               uiOutput("PlotExtract_KM_Min_Max_Question_2_UI"),
                                                               uiOutput("PlotExtract_KM_Min_Max_Question_3_UI"),
                                                               uiOutput("PlotExtract_KM_Min_Max_Question_4_UI"),
                                                               uiOutput("PlotExtract_KM_Min_Max_Question_5_UI"),
                                                               uiOutput("PlotExtract_KM_Min_Max_Submit_Questions_UI"),
                                                               uiOutput("PlotExtract_KM_Min_Max_Reset_Questions_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_1_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_2_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_3_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_4_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_5_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_6_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_7_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_8_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_9_UI"),
                                                               uiOutput("PlotExtract_KM_Group_Numbers_10_UI"),
                                                               uiOutput("PlotExtract_KM_Submit_Group_Numbers_UI"),
                                                               uiOutput("PlotExtract_DownloadResults_UI"),
                                                               htmlOutput("PlotExtract_DisplaySelection"),
                                                               htmlOutput("PlotExtract_SelectionMessage"),
                                                               htmlOutput("htmlMsg1_PlotExtract"),
                                                               uiOutput("PlotExtract_PlotType_UI"),
                                                               uiOutput("PlotExtract_Confirm_PlotType_UI"),
                                                               uiOutput("PlotExtract_Change_PlotType_UI"),
                                                               uiOutput("PlotExtract_x_min_UI"),
                                                               uiOutput("PlotExtract_x_max_UI"),
                                                               uiOutput("PlotExtract_y_min_UI"),
                                                               uiOutput("PlotExtract_y_max_UI"),
                                                               uiOutput("PlotExtract_Confirm_y_min_y_max_UI"),
                                                               uiOutput("PlotExtract_Change_y_min_y_max_UI"),
                                                               uiOutput("PlotExtract_Groups_UI"),
                                                               uiOutput("PlotExtract_Confirm_Groups_UI"),
                                                               uiOutput("PlotExtract_Change_Groups_UI"),
                                                               uiOutput("PlotExtract_TimePoints_UI"),
                                                               uiOutput("PlotExtract_Confirm_TimePoints_UI"),
                                                               uiOutput("PlotExtract_Change_TimePoints_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_1_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_2_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_3_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_4_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_5_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_6_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_7_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_8_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_9_UI"),
                                                               uiOutput("PlotExtract_KM_TimePoints_10_UI"),
                                                               uiOutput("PlotExtract_Confirm_KM_TimePoints_UI"),
                                                               uiOutput("PlotExtract_Change_KM_TimePoints_UI"),
                                                        ),
                                                        column(width = 8,
                                                               fluidRow(
                                                                 column(width = 6,
                                                                        uiOutput("PlotExtract_ResetPlot_UI"),
                                                                 ),
                                                                 column(width = 6,
                                                                        uiOutput("PlotExtract_Remove_Last_UI"),
                                                                 ),
                                                               ),
                                                               fluidRow(
                                                                 uiOutput("PlotExtract_UploadedPlot_UI"),
                                                               ),
                                                        ),
                                               ),
                                        ),
                                        ),
                                          column(width = 4,
                                                 htmlOutput("htmlInstructions2_PlotExtract"),
                                          ),
                           ),
                           tabPanelBody("panel10",
                                        column(width=12,
                                               tags$div(id = "div_Process_Int", tags$style("#div_Process_Int div {margin-bottom: 16px}"),
                                                        uiOutput(outputId = "skip_instructions_Process_Int_UI"),
                                                        htmlOutput("htmlMsg1_Process_Int"),
                                                        uiOutput(outputId = "Process_Int_one_more_UI"),
                                                        uiOutput(outputId = "Process_Int_text_Download_UI"),
                                                        htmlOutput("Header_Process_Int"),
                                                        uiOutput(outputId = "Process_Int_text_UI"),
                                                        htmlOutput("htmlInstructions1_Process_Int"),
                                                        uiOutput(outputId = "Process_Int_language_UI"),
                                                        uiOutput(outputId = "Process_Int_upload_UI"),
                                                        htmlOutput("htmlInstructions2_Process_Int"),
                                               ),
                                        ),
                           ),
                           tabPanelBody("panel11",
                                        column(width=12,
                                               tags$div(id = "div_Interpret_Int", tags$style("#div_Interpret_Int div {margin-bottom: 16px}"),
                                                        uiOutput(outputId = "skip_instructions_Interpret_Int_UI"),
                                                        htmlOutput("htmlMsg1_Interpret_Int"),
                                                        uiOutput(outputId = "Interpret_Int_one_more_UI"),
                                                        uiOutput(outputId = "Interpret_Int_text_Download_UI"),
                                                        htmlOutput("Header_Interpret_Int"),
                                                        uiOutput(outputId = "Interpret_Int_text_UI"),
                                                        htmlOutput("htmlInstructions1_Interpret_Int"),
                                                        uiOutput(outputId = "Interpret_Int_language_UI"),
                                                        uiOutput(outputId = "Interpret_Int_upload_UI"),
                                                        htmlOutput("htmlInstructions2_Interpret_Int"),
                                               ),
                                        ),
                           ),
               ),
               # tabs end here  
        )          
      )),
  ),
)

# Processing ####
server <- function(input, output, session) {
  rv <- reactiveValues(
    InputData = NULL,
    outcome.summary_Int = NULL,
    df_Outcome = NULL,
    MA = NULL,
    MetaBias = NULL,
    SA = NULL,
    MetaReg = NULL,
    Subgroup_1 = NULL,
    Subgroup_2 = NULL,
    Subgroup_3 = NULL,
    Subgroup_4 = NULL,
    Subgroup_5 = NULL,
    Subgroup_6 = NULL,
    Subgroup_7 = NULL,
    Subgroup_8 = NULL,
    Subgroup_9 = NULL,
    Subgroup_10 = NULL,
    Metabias.Min = NULL,
    SelectedCovariates = NULL,
    SelectedCovariatesColumns = NULL,
    SelectedCovariatesColumnsSubgroup = NULL,
    MetaRegText = NULL,
    OldColumnNames = NULL,
    NewColumnNames = NULL,
    DefaultMetaAnalysisPlan = NULL,
    RevManMetaAnalysisPlan_Int = NULL,
    UploadedMetaAnalysisPlan_Int = NULL,
    EffectMeasure = NULL,
    Analysis = NULL,
    UploadPlanCheck = NULL,
    ResetData= NULL,
    ResetPlan = NULL,
    ModifyPlan = NULL,
    RunAnalysis = NULL,
    AcceptModification = NULL,
    RowsForModification = NULL,
    OutcomeRow = NULL,
    plot1 = NULL,
    plot2 = NULL,
    plot3 = NULL,
    plotSA1 = NULL,
    plotSA2 = NULL,
    plotSA3 = NULL,
    plotSubA1 = NULL,
    plotSubA2 = NULL,
    plotSubA3 = NULL,
    plotSubA4 = NULL,
    plotSubA5 = NULL,
    plotSubA6 = NULL,
    plotSubA7 = NULL,
    plotSubA8 = NULL,
    plotSubA9 = NULL,
    plotSubA10 = NULL,
    FinalPlot1 = NULL,
    FinalPlot2 = NULL,
    FinalPlot3 = NULL,
    FinalPlotSA1 = NULL,
    FinalPlotSA2 = NULL,
    FinalPlotSA3 = NULL,
    FinalPlotSubA1 = NULL,
    FinalPlotSubA2 = NULL,
    FinalPlotSubA3 = NULL,
    FinalPlotSubA4 = NULL,
    FinalPlotSubA5 = NULL,
    FinalPlotSubA6 = NULL,
    FinalPlotSubA7 = NULL,
    FinalPlotSubA8 = NULL,
    FinalPlotSubA9 = NULL,
    FinalPlotSubA10 = NULL,
    StorageFolder = StorageFolder,
    RevManData = NULL,
    RevManProcessed = NULL,
    Comparisons1 = NULL,
    Comparisons2 = NULL,
    Comparisons3 = NULL,
    GenerateCode = GenerateCode,
    ColumnNamesForCodes = NULL,
    OutcomeNamesForCodes = NULL,
    # Combine databases and highlight references
    index.file.full.name = NULL,
    reference.files.full.names = NULL,
    index.file.path = NULL, 
    index.file = NULL, 
    references.file = NULL,
    keywords.file.full.name = NULL,
    results = NULL,
    files.list.1 = NULL,
    files.list.2 = NULL,
    DEF_other_characteristics =  NULL,
    DEF_criteria =  NULL,
    DEF_outcomes =  NULL,
    x=NULL,
    y=NULL,
    UploadedPlot = NULL,
    x_pixels = NULL,
    y_pixels = NULL,
    plot_number = NULL,
    x_min = NULL,
    x_max = NULL,
    y_min = NULL,
    y_max = NULL,
    KM_TimePoints = NULL,
    points_max = NULL,
    points_names = NULL,
    points_times_groups = NULL,
    points_colours = NULL,
    points_colours_viridis = NULL,
    points_symbol = NULL,
    points_values = NULL,
    group_numbers = NULL,
    lines_required = NULL,
    KM_Calculations_Step1 = NULL,
    KM_Calculations_Step2 = NULL,
    PlotExtract_FinalResults = NULL
  )
  output$htmlInstructions <- renderUI(HTML(Instructions))
  output$htmlInstructions_Int <- renderUI(HTML(Instructions_Int))
  output$htmlInstructions1_references <- renderUI(HTML(paste0(
    Instructions_references_1,Instructions_references_2
  )))
  output$htmlInstructions1_DEF_Int <- renderUI(HTML(paste0(
    Instructions_DEF_Int_1, Instructions_DEF_Int_2
  )))
  output$htmlInstructions1_OCR <- renderUI(HTML(paste0(
    Instructions_OCR_1, Instructions_OCR_2
  )))
  output$htmlInstructions1_PlotExtract <- renderUI(HTML(paste0(
    Instructions_PlotExtract_1, Instructions_PlotExtract_2
  )))
  output$htmlInstructions1_Process_Int <- renderUI(HTML(paste0(
    Instructions_Process_Int_1, Instructions_Process_Int_2
  )))
  output$htmlInstructions1_Interpret_Int <- renderUI(HTML(paste0(
    Instructions_Interpret_Int_1, Instructions_Interpret_Int_2
  )))
  output$skip_instructions_Int_UI <- renderUI(
    actionButton("skip_instructions_Int", "Skip instructions")
  )
  output$skip_instructions_references_UI <- renderUI(
    actionButton("skip_instructions_references", "Skip instructions")
  )
  output$skip_instructions_DEF_Int_UI <- renderUI(
    actionButton("skip_instructions_DEF_Int", "Skip instructions")
  )
  output$skip_instructions_OCR_UI <- renderUI(
    actionButton("skip_instructions_OCR", "Skip instructions")
  )
  output$skip_instructions_PlotExtract_UI <- renderUI(
    actionButton("skip_instructions_PlotExtract", "Skip instructions")
  )
  output$skip_instructions_Process_Int_UI <- renderUI(
    actionButton("skip_instructions_Process_Int", "Skip instructions")
  )
  output$skip_instructions_Interpret_Int_UI <- renderUI(
    actionButton("skip_instructions_Interpret_Int", "Skip instructions")
  )
  
  rv$ResetData = "No"
  rv$ResetPlan <- NULL
  rv$ModifyPlan <- NULL
  rv$RunAnalysis <- NULL
  rv$AcceptModification <- NULL
  
  # Now for the observe events
  # If the main panel changes
  observeEvent(input$Activity, {
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[match(input$Activity,FirstSelection)]))
    panelchoice <- paste0("panel", match(input$Activity,FirstSelection))
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
  })
  
  # Reference screener events ####
  observeEvent(input$ReferenceScreener, {
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[6]))
    panelchoice <- "panel6"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[c(1:2,6)], 
                       selected = FirstSelection[6])
    output$htmlMsg1_references <- NULL
  })
  observeEvent(input$skip_instructions_references, {
    output$htmlInstructions1_references <- NULL
    output$htmlInstructions2_references <- renderUI(HTML(Instructions_references_1))
    output$skip_instructions_references_UI <- NULL
  })
  output$download_UI_1_references <- NULL
  output$download_UI_2_references <- NULL
  output$references_file1_UI <- renderUI(
    fileInput(
      inputId = "references_file1", 
      label = "Choose Index File", 
      multiple = FALSE,
      accept = c(".csv")
    )
  )
  output$references_file2_UI <- NULL
  output$references_file3_UI <- NULL
  output$references_one_more_UI <- NULL
  observeEvent(input$references_one_more, {
    output$htmlMsg1_references <- NULL
    output$download_UI_1_references <- NULL
    output$download_UI_2_references <- NULL
    output$references_file1_UI <- renderUI(
      fileInput(
        inputId = "references_file1", 
        label = "Choose Index File", 
        multiple = FALSE,
        accept = c(".csv")
      )
    )
    output$references_file2_UI <- NULL
    output$references_file3_UI <- NULL
    output$references_one_more_UI <- NULL
  })
  observeEvent(input$references_file1, {
    if (input$references_file1$datapath != "") {
      rv$index.file.full.name <- str_replace_all(input$references_file1$datapath,
                                                 fixed("\\"),
                                                 "/")
    }
    output$htmlInstructions1_references <- NULL
    output$htmlInstructions2_references <- renderUI(HTML(Instructions_references_1))
    rv$index.file <- read.csv(rv$index.file.full.name,header = TRUE)
    # Check column names
    if (FALSE %in% (colnames(rv$index.file) == c("file.name", "database"))){
      output$htmlMsg1_references <- renderUI(
        HTML('<h2 style="color:red; background-color:yellow"><b>
      The column names should be "file.name" and "database" (without the quotes). Please see sample download from left side panel for the correct column names.</b></h2>')  
      )
    } else if(nrow(rv$index.file) < 1) {
      output$htmlMsg1_references <- renderUI(
        HTML('<h2 style="color:red; background-color:yellow"><b>
      There is no data in this file. Please upload a file with data.</b></h2>')  
      )
    } else if (FALSE %in% !is.na(match(rv$index.file$database, database))) {
      output$htmlMsg1_references <- renderUI(
        HTML(paste0(
          '<h2 style="color:red; background-color:yellow"><b>
      There are unrecognised databases in the file. 
        The recognised databases are: ', 
          paste0(database, collapse = ", "),
          '. \nPlease ensure that there are no additional spaces. 
        Please note that the database names are case sensitive.
        </b></h2>'
        ))
      )
    } else {
      output$htmlMsg1_references <- renderUI(
        HTML('<h2 style="color:darkgreen; background-color:yellow">
           <b>Index file uploaded.</b><br>
           <i>Please upload the downloaded search results files...</i>
           </h2>')
      )
      output$references_file1_UI <- NULL
      output$references_file2_UI <- renderUI(
        fileInput(
          inputId = "references_file2", 
          label = "Choose downloaded search results files", 
          multiple = TRUE,
          accept = c(".csv", ".txt", ".xml", ".nbib")
        )
      )
    }
  })
  observeEvent(input$references_file2, {
    if (!is.null(rv$index.file.full.name)){
      if (input$references_file2$datapath[1] != ""){
        if (nrow(input$references_file2) <= nrow(rv$index.file)) {
          output$download_UI_1_references <- renderUI(
            HTML('<strong>Download button for csv files will appear once the processing is completed...</strong>')
          )
          references_file2.path <- str_replace_all(input$references_file2$datapath, fixed("\\"),"/")
          rv$reference.files.full.names <- paste0(
            substr(references_file2.path, 1,
                   str_locate_all(references_file2.path, "/")[[1]][nrow(str_locate_all(references_file2.path, "/")[[1]]),1]
            ),
            input$references_file2$name
          )
          file.rename(
            references_file2.path, 
            rv$reference.files.full.names
          )
          rv$index.file$full.file.name <- paste0(
            substr(references_file2.path, 1,
                   str_locate_all(references_file2.path[1], "/")[[1]][nrow(str_locate_all(references_file2.path[1], "/")[[1]]),1]
            ),
            rv$index.file$file.name
          )
          if (!TRUE %in% !is.na(match(rv$index.file$full.file.name, 
                                      rv$reference.files.full.names))){
            output$htmlMsg1_references <- renderUI(
              HTML('<h2 style="color:red; background-color:yellow"><b>
      None of the files indicated in the index file are present. 
                 Please check whether you have uploaded the correct index file 
                 and the database search results files.</b></h2>')
              
            )
            output$references_file2_UI <- NULL
            output$download_UI_1_references <- NULL
            output$references_file1_UI <- renderUI(
              fileInput(
                inputId = "references_file1", 
                label = "Choose Index File", 
                multiple = FALSE,
                accept = c(".csv")
              )
            )
          }else {
            rv$results <- import.references(rv$index.file.full.name, 
                                            rv$reference.files.full.names)
            # Get the file names
            rv$files.list.1 <- 
              dir(paste0(
                substr(rv$index.file.full.name,1,str_locate_all(rv$index.file.full.name, fixed("/"))[[1]][nrow(str_locate_all(rv$index.file.full.name, fixed("/"))[[1]]),1]),
                "FullDetails/"
              ), full.names = TRUE)
            output$references_file2_UI <- NULL
            output$htmlMsg1_references <- renderUI(
              HTML('<h2 style="color:darkgreen; background-color:yellow">
           <b>Searches combined and references deduplicated.</b><br>
           <i>Results are available below.</i><br>
           If you want keywords highligted, you can upload the keywords.<br>
           <i>If you want to combine another set of search results without highlighting keywords, click on <br>"Combine another set of search results"</i>.
           </h2>')
            )
            output$references_one_more_UI <- renderUI(
              actionButton("references_one_more", "Combine another set of search results")
            )
            output$download_UI_1_references <- renderUI(
              downloadButton("download.csv.references", 
                             HTML("Download the references in each database and deduplicated references")
              )
            )
            output$references_file3_UI <- renderUI(
              fileInput(
                inputId = "references_file3", 
                label = "Choose Keywords File", 
                multiple = FALSE,
                accept = c(".csv")
              )
            )
          }
        } else {
          output$htmlMsg1_references <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
      The number of files uploaded was more than the number indicated in the index file. 
                 Please check whether you have uploaded the correct index file 
                 and the database search results files.</b></h2>')
            
          )
          output$references_file2_UI <- NULL
          output$download_UI_1_references <- NULL
          output$references_file1_UI <- renderUI(
            fileInput(
              inputId = "references_file1", 
              label = "Choose Index File", 
              multiple = FALSE,
              accept = c(".csv")
            )
          )
        }
      }
    }
  })
  observeEvent(input$references_file3, {
    if (!is.null(rv$results)){
      if (input$references_file3$datapath[1] != "") {
        rv$keywords.file.full.name <- str_replace_all(input$references_file3$datapath, fixed("\\"),"/")
        rv$keywords.file <- read.csv(rv$keywords.file.full.name,header = TRUE)
        # Check column names
        if (ncol(rv$keywords.file) > 3) {
          output$htmlMsg1_references <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
            There has to be a maximum of three columns. The column names should be "keywords" and "concept" (without the quotes). You can also provide an optional "weight" column. Please see sample download from left side panel for the correct column names.</b></h2>')  
          )
        } else if (
          (ncol(rv$keywords.file) == 2) &
          (FALSE %in% (colnames(rv$keywords.file) == c("keywords", "concept")))
        ) {
          output$htmlMsg1_references <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
      The column names should be "keywords" and "concept" (without the quotes). You can also provide an optional "weight" column. Please see sample download from left side panel for the correct column names.</b></h2>')  
          )
        } else if (
          (ncol(rv$keywords.file) == 3) &
          (FALSE %in% (colnames(rv$keywords.file) == c("keywords", "concept", "weight")))
        ) {
          output$htmlMsg1_references <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
      The column names should be "keywords" and "concept" (without the quotes). You can also provide an optional "weight" column. Please see sample download from left side panel for the correct column names.</b></h2>')  
          )
        } else if(nrow(rv$keywords.file) < 1) {
          output$htmlMsg1_references <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
      There is no data in this file. Please upload a file with data.</b></h2>')  
          )
        } else {
          output$htmlMsg1_references <- NULL
          output$download_UI_2_references <- renderUI(
            HTML('<strong>Download button for highlighted files will appear once the processing is completed...</strong>')
          )
          output$references_file3_UI <- renderUI(
            HTML('<h2 style="color:darkgreen; background-color:yellow">
               Keywords file uploaded
               </h2>')
          )
          
          highlight.keywords(rv$results[[1]], rv$keywords.file.full.name, rv$results[[2]])
          # Get the file names
          rv$files.list.2 <- 
            dir(paste0(
              substr(rv$index.file.full.name,1,str_locate_all(rv$index.file.full.name, fixed("/"))[[1]][nrow(str_locate_all(rv$index.file.full.name, fixed("/"))[[1]]),1]),
              "References_to_Screen/"
            ), full.names = TRUE)
          output$download_UI_2_references <- renderUI(
            downloadButton("download.processed.references", 
                           HTML("Download the highlighted references")
            )
          )
          output$htmlMsg1_references <- renderUI(
            HTML('<h2 style="color:darkgreen; background-color:yellow">
               <b>References highlighted.</b><br>
               <i>You can download the results below.</i><br>
           If you want to combine another set of search results, click on <br>"Combine another set of search results".
           </h2>')
          )
          output$references_file3_UI <- NULL
        }
      }
    }
  })
  output$download.csv.references <- downloadHandler( 
    filename = "References_csv.zip", 
    content = function(file) {
      zip::zipr(zipfile = file, 
                files = rv$files.list.1)
    } 
  )
  output$download.processed.references <- downloadHandler( 
    filename = "Processed_references.zip", 
    content = function(file) {
      zip::zipr(zipfile = file, 
                files = rv$files.list.2)
    } 
  )
  # Create DEF events (Intervention review) ####
  observeEvent(input$DEF, {
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[7]))
    panelchoice <- "panel7"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[c(1:2,7)], 
                       selected = FirstSelection[7])
    output$htmlMsg1_DEF_Int <- NULL
    output$htmlMsg2_DEF_Int <- NULL
    output$Header_DEF_Int <- NULL
    if (file.exists(paste0(StorageFolder, "/DEF_Design.csv"))) {file.remove(paste0(StorageFolder, "/DEF_Design.csv"))}
    if (file.exists(paste0(StorageFolder, "/DEF_ImportSummary.csv"))) {file.remove(paste0(StorageFolder, "/DEF_ImportSummary.csv"))}
    if (file.exists(paste0(StorageFolder, "/DEF_References.csv"))) {file.remove(paste0(StorageFolder, "/DEF_References.csv"))}
    if (file.exists(paste0(StorageFolder, "/Data_extraction_form.xlsx.csv"))) {file.remove(paste0(StorageFolder, "/Data_extraction_form.xlsx.csv"))}
  })
  observeEvent(input$skip_instructions_DEF_Int, {
    output$htmlInstructions1_DEF_Int <- NULL
    output$htmlInstructions2_DEF_Int <- renderUI(HTML(Instructions_DEF_Int_1))
    output$skip_instructions_DEF_Int_UI <- NULL
  })
  observeEvent(input$DEF_Create_One_more, {
    output$skip_instructions_DEF_Int_UI <- NULL
    output$htmlMsg1_DEF_Int <- NULL
    output$htmlMsg2_DEF_Int <- NULL
    output$htmlInstructions1_DEF_Int <- NULL
    output$Header_DEF_Int <- NULL
    output$DEF_Plan_Int_Choice_UI <- renderUI(
      radioButtons("DEF_Plan_Int_Choice", 
                   "Please select from one of the following options.", 
                   choices = DEF_Plan_IntChoice,
                   width = "100%",
                   inline = FALSE,
                   selected = character(0)
      )  
    )
    output$DEF_Plan_Int_Change_Choice_UI <- NULL
    output$DEF_ImportSummary_Change_Choice_UI <- NULL
    output$DEF_Plan_Int_NRS_UI <- NULL
    output$DEF_Plan_Int_cluster_UI <- NULL
    output$DEF_Plan_Int_cross_over_UI <- NULL
    output$DEF_Plan_Int_per_protocol_UI <- NULL
    output$DEF_Plan_Int_intervention_1_name_UI <- NULL
    output$DEF_Plan_Int_intervention_1_short_name_UI <- NULL
    output$DEF_Plan_Int_intervention_2_name_UI <- NULL
    output$DEF_Plan_Int_intervention_2_short_name_UI <- NULL
    output$DEF_Plan_Int_criteria_Upload_UI <- NULL
    output$DEF_Plan_Int_other_characteristics_Upload_UI <- NULL
    output$DEF_Plan_Int_outcomes_Upload_UI <- NULL
    output$DEF_Plan_Int_plan_submit_UI <- NULL
    output$DEF_Plan_Int_Upload_UI <- NULL
    output$DEF_ImportSummary_Choice_UI <- NULL
    output$DEF_ImportSummary_Upload_UI <- NULL
    output$DEF_References_Upload_UI <- NULL
    output$DEF_Download_UI <- NULL
    output$DEF_Plan_Download_UI <- NULL
    output$htmlInstructions2_DEF_Int <- renderUI(HTML(Instructions_DEF_Int_1))
    if (file.exists(paste0(StorageFolder, "/DEF_Design.csv"))) {file.remove(paste0(StorageFolder, "/DEF_Design.csv"))}
    if (file.exists(paste0(StorageFolder, "/DEF_ImportSummary.csv"))) {file.remove(paste0(StorageFolder, "/DEF_ImportSummary.csv"))}
    if (file.exists(paste0(StorageFolder, "/DEF_References.csv"))) {file.remove(paste0(StorageFolder, "/DEF_References.csv"))}
    if (file.exists(paste0(StorageFolder, "/Data_extraction_form.xlsx.csv"))) {file.remove(paste0(StorageFolder, "/Data_extraction_form.xlsx.csv"))}
  })
  output$DEF_Plan_Int_Choice_UI <- renderUI(
    radioButtons("DEF_Plan_Int_Choice", 
                 "Please select from one of the following options.", 
                 choices = DEF_Plan_IntChoice,
                 width = "100%",
                 inline = FALSE,
                 selected = character(0)
    )  
  )
  observeEvent(input$DEF_Plan_Int_Choice, {
    if (input$DEF_Plan_Int_Choice == DEF_Plan_IntChoice[1]) {
      output$htmlMsg1_DEF_Int <- NULL
      output$htmlMsg2_DEF_Int <- NULL
      output$DEF_Plan_Int_Choice_UI<- NULL
      output$DEF_Plan_Int_Change_Choice_UI<- renderUI(
        actionButton("DEF_Plan_Int_Change_Choice", "Change Data extraction form Plan choice")
      )
      output$DEF_Plan_Int_NRS_UI<- NULL
      output$DEF_Plan_Int_cluster_UI<- NULL
      output$DEF_Plan_Int_cross_over_UI<- NULL
      output$DEF_Plan_Int_per_protocol_UI<- NULL
      output$DEF_Plan_Int_intervention_1_name_UI<- NULL
      output$DEF_Plan_Int_intervention_1_short_name_UI<- NULL
      output$DEF_Plan_Int_intervention_2_name_UI<- NULL
      output$DEF_Plan_Int_intervention_2_short_name_UI<- NULL
      output$DEF_Plan_Int_criteria_Upload_UI<- NULL
      output$DEF_Plan_Int_other_characteristics_Upload_UI<- NULL
      output$DEF_Plan_Int_outcomes_Upload_UI<- NULL
      output$DEF_Plan_Int_plan_submit_UI <- NULL
      output$DEF_Plan_Int_Upload_UI<- renderUI(
        fileInput("DEF_Plan_Int_Upload", "Please upload the data extraction form for intervention review prepared using this program previously",
                  multiple = FALSE,
                  accept = c(".csv")
        )
      )
      output$DEF_ImportSummary_Choice_UI<- NULL
      output$DEF_ImportSummary_Change_Choice_UI <- NULL
      output$DEF_ImportSummary_Upload_UI<- NULL
      output$DEF_References_Upload_UI<- NULL
      output$DEF_Download_UI <- NULL
      output$DEF_Plan_Download_UI <- NULL
    } else {
      output$htmlMsg1_DEF_Int <- NULL
      output$htmlMsg2_DEF_Int <- NULL
      output$DEF_Plan_Int_Choice_UI<- NULL
      output$DEF_Plan_Int_Change_Choice_UI<- renderUI(
        actionButton("DEF_Plan_Int_Change_Choice", "Change Data extraction form Plan choice")
      )
      output$DEF_Plan_Int_NRS_UI<- renderUI(
        radioButtons("DEF_Plan_Int_NRS", 
                     "Do you plan to include non-randomised studies of intervention?", 
                     choices = c("Yes", "No"),
                     width = "100%",
                     inline = FALSE
        )  
      )
      output$DEF_Plan_Int_cluster_UI<- renderUI(
        radioButtons("DEF_Plan_Int_cluster", 
                     "Do you plan to include cluster studies of intervention?", 
                     choices = c("Yes", "No"),
                     width = "100%",
                     inline = FALSE
        )  
      )
      output$DEF_Plan_Int_cross_over_UI<- renderUI(
        radioButtons("DEF_Plan_Int_cross_over",
                     "Do you plan to include cross-over studies of intervention?", 
                     choices = c("Yes", "No"),
                     width = "100%",
                     inline = FALSE
        )  
      )
      output$DEF_Plan_Int_per_protocol_UI<- renderUI(
        radioButtons("DEF_Plan_Int_per_protocol", 
                     "Do you plan to include per-protocol effect?", 
                     choices = c("Yes", "No"),
                     width = "100%",
                     inline = FALSE
        )  
      )
      output$DEF_Plan_Int_intervention_1_name_UI<- renderUI(
        textInput(
          "DEF_Plan_Int_intervention_1_name",
          label = "Please enter the name of the first intervention. If you are performing a network meta-analysis, please do not change the default name.",
          value = "intervention_1",
          placeholder = "intervention_1",
          width = "700px"
        )
      )
      output$DEF_Plan_Int_intervention_1_short_name_UI<- renderUI(
        textInput(
          "DEF_Plan_Int_intervention_1_short_name",
          label = "Please enter the short name of the first intervention. If you are performing a network meta-analysis, please do not change the default name.",
          value = "intervention_1",
          placeholder = "intervention_1",
          width = "700px"
        )
      )
      output$DEF_Plan_Int_intervention_2_name_UI<- renderUI(
        textInput(
          "DEF_Plan_Int_intervention_2_name",
          label = "Please enter the name of the second intervention (comparator). If you are performing a network meta-analysis, please do not change the default name.",
          value = "intervention_2",
          placeholder = "intervention_2",
          width = "700px"
        )
      )
      output$DEF_Plan_Int_intervention_2_short_name_UI<- renderUI(
        textInput(
          "DEF_Plan_Int_intervention_2_short_name",
          label = "Please enter the short name of the second intervention (comparator). If you are performing a network meta-analysis, please do not change the default name.",
          value = "intervention_2",
          placeholder = "intervention_2",
          width = "700px"
        )
      )
      output$DEF_Plan_Int_criteria_Upload_UI<- renderUI(
        fileInput("DEF_Plan_Int_criteria_Upload", "Please upload the fields for collecting the criteria for participant selection used by study authors",
                  multiple = FALSE,
                  accept = c(".csv"),
                  width = "700px"
        )
      )
      output$DEF_Plan_Int_other_characteristics_Upload_UI<- renderUI(
        fileInput("DEF_Plan_Int_other_characteristics_Upload", "Please upload the fields for collecting other characteristics",
                  multiple = FALSE,
                  accept = c(".csv"),
                  width = "700px"
        )
      )
      output$DEF_Plan_Int_outcomes_Upload_UI<- renderUI(
        fileInput("DEF_Plan_Int_outcomes_Upload", "Please upload the outcome details",
                  multiple = FALSE,
                  accept = c(".csv"),
                  width = "700px"
        )
      )
      output$DEF_Plan_Int_plan_submit_UI <- NULL
      output$DEF_Plan_Int_Upload_UI<- NULL
      output$DEF_ImportSummary_Choice_UI<- NULL
      output$DEF_ImportSummary_Change_Choice_UI <- NULL
      output$DEF_ImportSummary_Upload_UI<- NULL
      output$DEF_References_Upload_UI<- NULL
      output$DEF_Download_UI <- NULL
      output$DEF_Plan_Download_UI <- NULL
      output$htmlMsg1_DEF_Int <- renderUI(
        HTML(paste0(
          '<h2 style="color:darkblue; background-color:yellow">',
          '<b><i>Criteria file: </b></i>',
          if (is.null(input$DEF_Plan_Int_criteria_Upload)) {
            'No file uploaded'
          } else {
            'File validity is available at the time of upload'
          },
          '<br>',
          '<b><i>Other characteristics file: </b></i>',
          if (is.null(input$DEF_Plan_Int_other_characteristics_Upload)) {
            'No file uploaded'
          } else {
            'File validity is available at the time of upload'
          },
          '<br>',
          '<b><i>Outcomes file: </b></i>',
          if (is.null(input$DEF_Plan_Int_outcomes_Upload)) {
            'No file uploaded'
          } else {
            'File validity is available at the time of upload'
          }
        ))
      )
      output$htmlMsg2_DEF_Int <- NULL
    }    
  })
  observeEvent(input$DEF_Plan_Int_Change_Choice, {
    output$htmlMsg1_DEF_Int <- NULL
    output$htmlMsg2_DEF_Int <- NULL
    output$DEF_Plan_Int_Choice_UI <- renderUI(
      radioButtons("DEF_Plan_Int_Choice", 
                   "Please select from one of the following options.", 
                   choices = DEF_Plan_IntChoice,
                   width = "100%",
                   inline = FALSE,
                   selected = character(0)
      )  
    )
    output$DEF_Plan_Int_NRS_UI<- NULL
    output$DEF_Plan_Int_cluster_UI<- NULL
    output$DEF_Plan_Int_cross_over_UI<- NULL
    output$DEF_Plan_Int_per_protocol_UI<- NULL
    output$DEF_Plan_Int_intervention_1_name_UI<- NULL
    output$DEF_Plan_Int_intervention_1_short_name_UI<- NULL
    output$DEF_Plan_Int_intervention_2_name_UI<- NULL
    output$DEF_Plan_Int_intervention_2_short_name_UI<- NULL
    output$DEF_Plan_Int_criteria_Upload_UI<- NULL
    output$DEF_Plan_Int_other_characteristics_Upload_UI<- NULL
    output$DEF_Plan_Int_outcomes_Upload_UI<- NULL
    output$DEF_Plan_Int_plan_submit_UI <- NULL
    output$DEF_Plan_Int_Upload_UI<- NULL
    output$DEF_ImportSummary_Choice_UI<- NULL
    output$DEF_ImportSummary_Change_Choice_UI <- NULL
    output$DEF_ImportSummary_Upload_UI<- NULL
    output$DEF_References_Upload_UI<- NULL
    output$DEF_Download_UI <- NULL
    output$DEF_Plan_Download_UI <- NULL
    if (file.exists(paste0(StorageFolder, "/DEF_Design.csv"))) {file.remove(paste0(StorageFolder, "/DEF_Design.csv"))}
    if (file.exists(paste0(StorageFolder, "/DEF_ImportSummary.csv"))) {file.remove(paste0(StorageFolder, "/DEF_ImportSummary.csv"))}
    if (file.exists(paste0(StorageFolder, "/DEF_References.csv"))) {file.remove(paste0(StorageFolder, "/DEF_References.csv"))}
    if (file.exists(paste0(StorageFolder, "/Data_extraction_form.xlsx.csv"))) {file.remove(paste0(StorageFolder, "/Data_extraction_form.xlsx.csv"))}
  })
  observeEvent(input$DEF_Plan_Int_Upload, {
    if (input$DEF_Plan_Int_Upload$datapath != "") {
      DEF_Design <- read.csv(input$DEF_Plan_Int_Upload$datapath,header = TRUE)
      # Check column names
      if (ncol(DEF_Design) != 7) {
        output$htmlMsg1_DEF_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>
            The number of columns should be exactly 7. The column names should be "variable", "variable_value","short_names", "type_1",
             "outcome_objective_subjective", "additional_text", and "other_characteristics_study_level_intervention_level" (without the quotes). 
             Please see sample download from left side panel for the correct column names.</b></h2>')  
        )
      } else if (
        FALSE %in% (colnames(DEF_Design) == c("variable", "variable_value","short_names", "type_1",
                                              "outcome_objective_subjective", "additional_text", "other_characteristics_study_level_intervention_level"))
      ) {
        output$htmlMsg1_DEF_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>
      The column names should be "variable", "variable_value","short_names", "type_1",
             "outcome_objective_subjective", "additional_text", and "other_characteristics_study_level_intervention_level" (without the quotes). 
             Please see sample download from left side panel for the correct column names.</b></h2>')  
        )
      } else if(nrow(DEF_Design) < 1) {
        output$htmlMsg1_DEF_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>
      There is no data in this file. Please upload a file with data.</b></h2>')  
        )
      } else {
        output$htmlMsg1_DEF_Int <- renderUI(
          HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
      Data extraction form plan successfully uploaded.</b></h2>')  
        )
        write.csv(DEF_Design, paste0(StorageFolder, "/DEF_Design.csv"), row.names = FALSE, na="")
        output$DEF_ImportSummary_Choice_UI<- renderUI(
          radioButtons("DEF_ImportSummary_Choice", 
                       "Do you want to upload the 1_Import_Summary and 2_Deduplicated_References created using this programe?", 
                       choices = c("Yes", "No"),
                       width = "100%",
                       inline = FALSE,
                       selected = character(0)
          )  
        )
        output$DEF_Plan_Int_Upload_UI<- NULL
        output$DEF_Plan_Int_Change_Choice_UI <- NULL
      }
    }
  })
  observeEvent(input$DEF_Plan_Int_criteria_Upload, {
    if (! is.null(input$DEF_Plan_Int_criteria_Upload)) {
      DEF_criteria <- read.csv(input$DEF_Plan_Int_criteria_Upload$datapath, header = TRUE, 
                               na.strings = c("", " ", "  "))
      if (
        (ncol(DEF_criteria) == 2) & 
        (! FALSE %in% (colnames(DEF_criteria) == c("variable_value","short_names")))
      ) {
        DEF_criteria <- na.omit(DEF_criteria)
        if (nrow(DEF_criteria) >0) {
          output$htmlMsg2_DEF_Int <- renderUI(
            HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
            "Criteria" file uploaded and validated. This file had ', nrow(DEF_criteria),' rows with data. 
               Scroll down to upload other files, change uploads for this or other files, or change entries.</b></h2>')
          )
          DEF_criteria$short_names <- sapply(
            1:nrow(DEF_criteria),
            function (x) {
              str_replace_all(DEF_criteria$short_names[x], " ","_")
            }
          )
          DEF_criteria$variable <- paste0("criterion_", formatC(1:nrow(DEF_criteria), width = 3, format = "d", flag = "0"))
          DEF_criteria$type_1 <- NA
          DEF_criteria$outcome_objective_subjective <- NA
          DEF_criteria$additional_text <-NA
          DEF_criteria$other_characteristics_study_level_intervention_level <- NA
          rv$DEF_criteria <- DEF_criteria[,c(3,1:2,4:7)]
        } else {
          DEF_criteria <- NULL
          output$htmlMsg2_DEF_Int <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
            "Criteria" file did not have any data. 
               Please scroll down to re-upload. This is an optional file. 
                 Therefore, if you do not upload a new file, the data extraction form will have two columns "Other inclusion criteria" and "Other exclusion criteria" to obtain details on the inclusion and exclusion criteria of participants in the study.</b></h2>')  
          )
        }
      } else {
        DEF_criteria <- NULL
        output$htmlMsg2_DEF_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>
            "Criteria" file was not in the correct format. The column names should be exactly 
               "variable_value" and "short_names" (without quotes). 
               Please see sample download from left side panel for the correct column names. 
               Please scroll down to re-upload. This is an optional file. 
               Therefore, if you do not upload a new file, the data extraction form will have two columns "Other inclusion criteria" and "Other exclusion criteria" to obtain details on the inclusion and exclusion criteria of participants in the study.</b></h2>')  
        )
      }
    }
  })
  observeEvent(input$DEF_Plan_Int_other_characteristics_Upload, {
    if (! is.null(input$DEF_Plan_Int_other_characteristics_Upload)) {
      DEF_other_characteristics <- read.csv(input$DEF_Plan_Int_other_characteristics_Upload$datapath, header = TRUE, 
                                            na.strings = c("", " ", "  "))
      if (
        (ncol(DEF_other_characteristics) == 4) & 
        (! FALSE %in% (colnames(DEF_other_characteristics) == c("variable_value","short_names","type_1","study_level_intervention_level")))
      ) {
        DEF_other_characteristics <- na.omit(DEF_other_characteristics)
        if (nrow(DEF_other_characteristics) >0) {
          if (! FALSE %in% ! is.na(match(DEF_other_characteristics$type_1, c("number", "score", "text")))) {
            if (! FALSE %in% ! is.na(match(DEF_other_characteristics$study_level_intervention_level, c("study_level", "intervention_level")))) {
              output$htmlMsg2_DEF_Int <- renderUI(
                HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
            "Other characteristics" file uploaded and validated. This file had ', nrow(DEF_other_characteristics),' rows with data. 
               Scroll down to upload other files, change uploads for this or other files, or change entries.</b></h2>')
              )
              DEF_other_characteristics$short_names <- sapply(
                1:nrow(DEF_other_characteristics),
                function (x) {
                  str_replace_all(DEF_other_characteristics$short_names[x], " ","_")
                }
              )
              colnames(DEF_other_characteristics)[4] <- "other_characteristics_study_level_intervention_level"
              DEF_other_characteristics$variable <- paste0("other_characteristics_", formatC(1:nrow(DEF_other_characteristics), width = 3, format = "d", flag = "0"))
              DEF_other_characteristics$outcome_objective_subjective <- NA
              DEF_other_characteristics$additional_text <-NA
              rv$DEF_other_characteristics <- DEF_other_characteristics[,c(5,1:3,6:7,4)]
            } else {
              DEF_other_characteristics <- NULL
              output$htmlMsg2_DEF_Int <- renderUI(
                HTML('<h2 style="color:red; background-color:yellow"><b>
            "study_level_intervention_level" column has invalid entries.  
            "study_level_intervention_level" column should have the entries "study_level" or "intervention_level" (without the quotes). 
            Please scroll down to re-upload. This is an optional file. 
               Therefore, if you do not upload a new file, the data extraction form will have only the participant characteristics related to PROGRESS-PLUS.</b></h2>')  
              )  
            }
          } else {
            DEF_other_characteristics <- NULL
            output$htmlMsg2_DEF_Int <- renderUI(
              HTML('<h2 style="color:red; background-color:yellow"><b>
            "type_1 column" has invalid entries. 
            "type_1 column" should have the entries "number", "score", or "text" (without the quotes). 
            Please scroll down to re-upload. This is an optional file. 
               Therefore, if you do not upload a new file, the data extraction form will have only the participant characteristics related to PROGRESS-PLUS.</b></h2>')  
            )  
          }
        } else {
          DEF_other_characteristics <- NULL
          output$htmlMsg2_DEF_Int <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
            "Other characteristics" file did not have any data. 
               Please scroll down to re-upload. This is an optional file. 
               Therefore, if you do not upload a new file, the data extraction form will have only the participant characteristics related to PROGRESS-PLUS.</b></h2>')  
          )
        }
      } else {
        DEF_other_characteristics <- NULL
        output$htmlMsg2_DEF_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>
            "Other characteristics" file was not in the correct format. The column names should be exactly 
               "variable_value", "short_names", "type_1", and "study_level_intervention_level" (without quotes). 
               Please see sample download from left side panel for the correct column names. 
               Please scroll down to re-upload. This is an optional file. 
               Therefore, if you do not upload a new file, the data extraction form will have only the participant characteristics related to PROGRESS-PLUS.</b></h2>')  
        )
      }
    }
  })
  observeEvent(input$DEF_Plan_Int_outcomes_Upload, {
    if (! is.null(input$DEF_Plan_Int_outcomes_Upload)) {
      DEF_outcomes <- read.csv(input$DEF_Plan_Int_outcomes_Upload$datapath, header = TRUE, 
                               na.strings = c("", " ", "  "))
      if (
        (ncol(DEF_outcomes) == 5) & 
        (! FALSE %in% (colnames(DEF_outcomes) == c("variable_value","short_names","type_1","outcome_objective_subjective", "additional_text")))
      ) {
        DEF_outcomes <- DEF_outcomes[
          (
            (! is.na(DEF_outcomes$variable_value)) & 
              (! is.na(DEF_outcomes$short_names)) &
              (! is.na(DEF_outcomes$type_1)) &
              (! is.na(DEF_outcomes$outcome_objective_subjective))
          )
          ,]
        if (nrow(DEF_outcomes) >0) {
          if (! FALSE %in% ! is.na(match(DEF_outcomes$type_1, c("binary", "continuous", "count", "time-to-event")))) {
            if (! FALSE %in% ! is.na(match(DEF_outcomes$outcome_objective_subjective, c("objective", "subjective")))) {
              output$htmlMsg2_DEF_Int <- renderUI(
                HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
            "Outcomes" file uploaded and validated. This file had ', nrow(DEF_outcomes),' rows with data. 
               Scroll down to upload other files, change uploads for this or other files, change entries, or submit the proposed plan to create the data extraction form design.</b></h2>')  
              )
              DEF_outcomes$short_names <- sapply(
                1:nrow(DEF_outcomes),
                function (x) {
                  str_replace_all(DEF_outcomes$short_names[x], " ","_")
                }
              )
              DEF_outcomes$variable <- paste0("outcome_", formatC(1:nrow(DEF_outcomes), width = 3, format = "d", flag = "0"))
              DEF_outcomes$other_characteristics_study_level_intervention_level <-NA
              rv$DEF_outcomes <- DEF_outcomes[,c(6,1:5,7)]
              output$DEF_Plan_Int_plan_submit_UI <- renderUI(
                actionButton("DEF_Plan_Int_plan_submit", "Submit the proposed plan")
              )
            } else {
              DEF_outcomes <- NULL
              output$DEF_Plan_Int_plan_submit_UI <- NULL
              output$htmlMsg2_DEF_Int <- renderUI(
                HTML('<h2 style="color:red; background-color:yellow"><b>
            "outcome_objective_subjective" column has invalid entries.  
            "outcome_objective_subjective" column should have the entries "objective" or "subjective" (without the quotes). 
                           Please scroll down to re-upload. This is a mandatory file. Without correct upload, data extraction form will not be created.</b></h2>')  
              )  
            }
          } else {
            DEF_outcomes <- NULL
            output$DEF_Plan_Int_plan_submit_UI <- NULL
            output$htmlMsg2_DEF_Int <- renderUI(
              HTML('<h2 style="color:red; background-color:yellow"><b>
            "type_1" column has invalid entries.  
            "type_1" column should have the entries "binary", "continuous", "count", and "time-to-event" (without the quotes). 
               Please scroll down to re-upload. This is a mandatory file. Without correct upload, data extraction form will not be created.</b></h2>')  
            )  
          }
        } else {
          DEF_outcomes <- NULL
          output$DEF_Plan_Int_plan_submit_UI <- NULL
          output$htmlMsg2_DEF_Int <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
            "Outcomes" file did not have any data. 
               Please scroll down to re-upload. This is a mandatory file. Without correct upload, data extraction form will not be created.</b></h2>')  
          )
        }
      } else {
        DEF_outcomes <- NULL
        output$DEF_Plan_Int_plan_submit_UI <- NULL
        output$htmlMsg2_DEF_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>
            "Outcomes" file was not in the correct format. The column names should be exactly 
               "variable_value", "short_names", "type_1", "outcome_objective_subjective", and "additional_text" (without quotes). 
               Please see sample download from left side panel for the correct column names. 
               Please scroll down to re-upload. This is a mandatory file. Without correct upload, data extraction form will not be created.</b></h2>')  
        )
      }
    }
  })
  observeEvent(input$DEF_Plan_Int_plan_submit, {
    DEF_Design <- data.frame(matrix(nrow = 0, ncol = 7))
    DEF_Design <- rbind.data.frame(
      DEF_Design,
      c("non_randomised_studies_intervention", tolower(input$DEF_Plan_Int_NRS), rep(NA, 5)),
      c("cluster", tolower(input$DEF_Plan_Int_cluster), rep(NA, 5)),
      c("cross_over", tolower(input$DEF_Plan_Int_cross_over), rep(NA, 5)),
      c("per_protocol", tolower(input$DEF_Plan_Int_per_protocol), rep(NA, 5)),
      c("intervention_1", ifelse(input$DEF_Plan_Int_intervention_1_name == "", "intervention_1", input$DEF_Plan_Int_intervention_1_name),
        ifelse(input$DEF_Plan_Int_intervention_1_short_name == "", "intervention_1", input$DEF_Plan_Int_intervention_1_short_name),
        rep(NA, 4)),
      c("intervention_2", ifelse(input$DEF_Plan_Int_intervention_2_name == "", "intervention_2", input$DEF_Plan_Int_intervention_2_name), 
        ifelse(input$DEF_Plan_Int_intervention_2_short_name == "", "intervention_2", input$DEF_Plan_Int_intervention_2_short_name),
        rep(NA, 4))
    )
    colnames(DEF_Design) <- c("variable", "variable_value","short_names", "type_1",
                              "outcome_objective_subjective", "additional_text", "other_characteristics_study_level_intervention_level")
    DEF_Design <- rbind(
      DEF_Design,
      rv$DEF_outcomes
    )
    if (
      (! is.null(input$DEF_Plan_Int_criteria_Upload)) &
      (! is.null(rv$DEF_criteria))
    ) {
      DEF_Design <- rbind(
        DEF_Design,
        rv$DEF_criteria
      )
    }
    if (
      (! is.null(input$DEF_Plan_Int_criteria_Upload)) &
      (! is.null(rv$DEF_other_characteristics))
    ) {
      DEF_Design <- rbind(
        DEF_Design,
        rv$DEF_other_characteristics
      )
    }
    DEF_Design$variable <- as.character(DEF_Design$variable)
    DEF_Design$short_names <- as.character(DEF_Design$short_names)
    write.csv(DEF_Design, paste0(StorageFolder, "/DEF_Design.csv"), row.names = FALSE, na="")
    output$htmlMsg1_DEF_Int <- renderUI(
      HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
      Data extraction form plan successfully created.</b></h2>')
    )
    output$htmlMsg2_DEF_Int <- NULL 
    output$DEF_ImportSummary_Choice_UI<- renderUI(
      radioButtons("DEF_ImportSummary_Choice", 
                   "Do you want to upload the 1_Import_Summary and 2_Deduplicated_References created using this programe?", 
                   choices = c("Yes", "No"),
                   width = "100%",
                   inline = FALSE,
                   selected = character(0)
      )  
    )
    output$DEF_Plan_Int_Change_Choice_UI <- NULL
    output$DEF_Plan_Int_NRS_UI<- NULL
    output$DEF_Plan_Int_cluster_UI<- NULL
    output$DEF_Plan_Int_cross_over_UI<- NULL
    output$DEF_Plan_Int_per_protocol_UI<- NULL
    output$DEF_Plan_Int_intervention_1_name_UI<- NULL
    output$DEF_Plan_Int_intervention_1_short_name_UI<- NULL
    output$DEF_Plan_Int_intervention_2_name_UI<- NULL
    output$DEF_Plan_Int_intervention_2_short_name_UI<- NULL
    output$DEF_Plan_Int_criteria_Upload_UI<- NULL
    output$DEF_Plan_Int_other_characteristics_Upload_UI<- NULL
    output$DEF_Plan_Int_outcomes_Upload_UI<- NULL
    output$DEF_Plan_Int_plan_submit_UI <- NULL
    output$DEF_Download_UI <- NULL
    output$DEF_Plan_Download_UI <- NULL
  })
  observeEvent(input$DEF_ImportSummary_Choice, {
    if (input$DEF_ImportSummary_Choice == "Yes") {
      output$DEF_Plan_Int_Change_Choice_UI <- NULL
      output$DEF_ImportSummary_Choice_UI<- NULL
      output$DEF_ImportSummary_Change_Choice_UI <- renderUI(
        actionButton("DEF_ImportSummary_Change_Choice", "Change Import Summary choice")
      )
      output$DEF_ImportSummary_Upload_UI<- renderUI(
        fileInput("DEF_ImportSummary_Upload", "Please upload the import summary prepared using this program previously",
                  multiple = FALSE,
                  accept = c(".csv"),
                  width = "700px"
        )
      )
    } else if (input$DEF_ImportSummary_Choice == "No") {
      output$DEF_Plan_Int_Change_Choice_UI <- NULL
      output$DEF_ImportSummary_Choice_UI<- NULL
      output$DEF_ImportSummary_Change_Choice_UI <- NULL
      DEF_Design <- read.csv(
        paste0(StorageFolder, "/DEF_Design.csv"), header = TRUE
      )
      data_extraction_form <- create_dataextraction_form(DEF_Design = DEF_Design,
                                                         StorageFolder = StorageFolder)  
      output$DEF_Download_UI <- renderUI(
        downloadButton("DEF_Download", HTML('Download the data extraction form'))
      )
      output$DEF_Download <- downloadHandler( 
        filename = "Data_extraction_form.xlsx", 
        content = function(file) {
          file.copy(paste0(StorageFolder, "/DataExtractionForm.xlsx"), file)
        } 
      )
      output$DEF_Plan_Download_UI <- renderUI(
        downloadButton("DEF_Plan_Download", HTML('Download the data extraction form plan'))
      )
      output$DEF_Plan_Download <- downloadHandler( 
        filename = "DEF_Plan.csv", 
        content = function(file) {
          file.copy(paste0(StorageFolder, "/DEF_Design.csv"), file)
        } 
      )
      output$htmlMsg1_DEF_Int <- renderUI(
        HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
      Data extraction form successfully created and avaiable for download.</b></h2>')
      )
      output$htmlMsg2_DEF_Int <- renderUI(
        actionButton("DEF_Create_One_more", "Create one more form")
      )
    }
  })
  observeEvent(input$DEF_ImportSummary_Change_Choice, {
    output$DEF_ImportSummary_Choice_UI<- renderUI(
      radioButtons("DEF_ImportSummary_Choice", 
                   "Do you want to upload the 1_Import_Summary and 2_Deduplicated_References created using this programe?", 
                   choices = c("Yes", "No"),
                   width = "100%",
                   inline = FALSE,
                   selected = character(0)
      )  
    )
    if (file.exists(paste0(StorageFolder, "/DEF_ImportSummary.csv"))) {file.remove(paste0(StorageFolder, "/DEF_ImportSummary.csv"))}
    if (file.exists(paste0(StorageFolder, "/DEF_References.csv"))) {file.remove(paste0(StorageFolder, "/DEF_References.csv"))}
    if (file.exists(paste0(StorageFolder, "/Data_extraction_form.xlsx.csv"))) {file.remove(paste0(StorageFolder, "/Data_extraction_form.xlsx.csv"))}
    output$DEF_ImportSummary_Upload_UI <- NULL
    output$DEF_References_Upload_UI <- NULL
  })
  observeEvent(input$DEF_ImportSummary_Upload, {
    if (! is.null(input$DEF_ImportSummary_Upload)) {
      output$DEF_References_Upload_UI<- NULL
      DEF_ImportSummary <- read.csv(input$DEF_ImportSummary_Upload$datapath, header = TRUE, 
                                    na.strings = c("", " ", "  "))
      if (
        (ncol(DEF_ImportSummary) == 8) & 
        (! FALSE %in% (colnames(DEF_ImportSummary) == c("file.name", "import.status", "references.imported", "database", "file.names", 
                                                        "number.of.files", "file.exists", "file.exists.number")))
      ) {
        if (nrow(DEF_ImportSummary) >0) {
          write.csv(DEF_ImportSummary, paste0(StorageFolder, "/DEF_ImportSummary.csv"),
                    row.names = FALSE, na = "")
          output$DEF_References_Upload_UI<- renderUI(
            fileInput("DEF_References_Upload", "Please upload the references prepared using this program previously",
                      multiple = FALSE,
                      accept = c(".csv"),
                      width = "700px"
            )
          )
          output$htmlMsg1_DEF_Int <- renderUI(
            HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
            "Import summary" file successfully uploaded. 
                 Please upload the references.</b></h2>')  
          )
        } else {
          DEF_ImportSummary <- NULL
          output$htmlMsg1_DEF_Int <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
            "Import summary" file did not have any data. 
                 Please upload another file or change "Import Summary" choice.</b></h2>')  
          )
        }
      } else {
        DEF_ImportSummary <- NULL
        output$htmlMsg1_DEF_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>
            "Import summary" file was not in the correct format. 
               Please upload a file prepared using this program or change "Import Summary" choice.</b></h2>')  
        )
      }
    }
  })
  observeEvent(input$DEF_References_Upload, {
    if (! is.null(input$DEF_References_Upload)) {
      DEF_References <- read.csv(input$DEF_References_Upload$datapath, header = TRUE, 
                                 na.strings = c("", " ", "  "))
      if (
        (ncol(DEF_References) == 19) & 
        (! FALSE %in% (colnames(DEF_References) == c("database", "unique.identifier", "pmid", "embase.id", 
                                                     "ctgov.id", "ictrp.id", "other.trial.identifier", "url", 
                                                     "authors", "authors.contact", "article.title", "article.abstract", 
                                                     "journal.name", "article.publication.year", "article.volume", "article.issue", 
                                                     "article.pages", "keywords", "article.reference"
        )))
      ) {
        if (nrow(DEF_References) >0) {
          output$DEF_ImportSummary_Upload_UI <- NULL
          output$DEF_References_Upload_UI<- NULL
          write.csv(DEF_References, paste0(StorageFolder, "/DEF_References.csv"),
                    row.names = FALSE, na = "")
          output$htmlMsg2_DEF_Int <- renderUI(
            HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
            "Deduplicated references" file successfully uploaded.</b></h2>')  
          )
          output$DEF_Plan_Int_Change_Choice_UI <- NULL
          output$DEF_ImportSummary_Choice_UI<- NULL
          output$DEF_ImportSummary_Change_Choice_UI <- NULL
          DEF_Design <- read.csv(
            paste0(StorageFolder, "/DEF_Design.csv"), header = TRUE
          )
          DEF_ImportSummary <- read.csv(
            paste0(StorageFolder, "/DEF_ImportSummary.csv"), header = TRUE
          )
          data_extraction_form <- create_dataextraction_form(DEF_Design = DEF_Design,
                                                             StorageFolder = StorageFolder,
                                                             Import_summary = DEF_ImportSummary,
                                                             Searches = DEF_References
          )  
          output$DEF_Download_UI <- renderUI(
            downloadButton("DEF_Download", HTML('Download the data extraction form'))
          )
          output$DEF_Download <- downloadHandler( 
            filename = "Data_extraction_form.xlsx", 
            content = function(file) {
              file.copy(paste0(StorageFolder, "/DataExtractionForm.xlsx"), file)
            } 
          )
          output$DEF_Plan_Download_UI <- renderUI(
            downloadButton("DEF_Plan_Download", HTML('Download the data extraction form plan'))
          )
          output$DEF_Plan_Download <- downloadHandler( 
            filename = "DEF_Plan.csv", 
            content = function(file) {
              file.copy(paste0(StorageFolder, "/DEF_Design.csv"), file)
            } 
          )
          output$htmlMsg1_DEF_Int <- renderUI(
            HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
      Data extraction form successfully created and avaiable for download.</b></h2>')
          )
          output$htmlMsg2_DEF_Int <- renderUI(
            actionButton("DEF_Create_One_more", "Create one more form")
          )
        } else {
          DEF_References <- NULL
          output$htmlMsg1_DEF_Int <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>
            "Deduplicated references" file did not have any data. 
                 Please upload another file or change "Import Summary" choice.</b></h2>')  
          )
        }
      } else {
        DEF_References <- NULL
        output$htmlMsg1_DEF_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>
            "Deduplicated references" file was not in the correct format. 
               Please upload a file prepared using this program or change "Import Summary" choice.</b></h2>')  
        )
      }
    }
  })
  # OCR events ####
  observeEvent(input$OCR, {
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[8]))
    panelchoice <- "panel8"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[c(1:2,8)], 
                       selected = FirstSelection[8])
    output$htmlMsg1_OCR <- NULL
    output$Header_OCR <- NULL
  })
  observeEvent(input$skip_instructions_OCR, {
    output$htmlInstructions1_OCR <- NULL
    output$htmlInstructions2_OCR <- renderUI(HTML(Instructions_OCR_1))
    output$skip_instructions_OCR_UI <- NULL
  })
  output$OCR_language_UI <- renderUI(
    selectInput("OCR_language", "Select the language:", choices = ocr.languages$Language, selectize = FALSE)
  )
  output$OCR_upload_UI <- renderUI(
    fileInput("OCR_upload", "Please upload an image (jpeg, png, or another image format) or pdf file",
              multiple = FALSE,
              accept = c("image/*", ".pdf")
    )
  )
  output$OCR_text_UI <- NULL
  output$OCR_one_more_UI <- NULL
  output$OCR_text_Download_UI <- NULL
  observeEvent(input$OCR_one_more, {
    output$htmlMsg1_OCR <- NULL
    output$OCR_language_UI <- renderUI(
      selectInput("OCR_language", "Select the language:", choices = ocr.languages$Language, selectize = FALSE)
    )
    output$OCR_upload_UI <- renderUI(
      fileInput("OCR_upload", "Please upload an image (jpeg, png, or another image format) or pdf file",
                multiple = FALSE,
                accept = c("image/*", ".pdf")
      )
    )
    output$OCR_text_UI <- NULL
    output$OCR_one_more_UI <- NULL
    output$OCR_text_Download_UI <- NULL
    output$Header_OCR <- NULL
  })
  observeEvent(input$OCR_upload, {
    output$OCR_text_UI <- renderUI(
      HTML("Please wait: optical character recognition is being performed...")
    )
    if (tools::file_ext(input$OCR_upload$datapath) == "pdf") {
      withProgress(message = 'Converting pdf to images', value = 0, {
        z=""
        x <- list()
        y <- paste0(substr(input$OCR_upload$datapath,1,(nchar(input$OCR_upload$datapath)-4)), "_",1:pdftools:: pdf_info(input$OCR_upload$datapath)$pages,".tiff")
        try(pdftools::pdf_convert(input$OCR_upload$datapath, format='tiff',
                                  filenames = y,
                                  dpi = 72)
        )
      })
      withProgress(message = 'OCR of images', value = 0, {
        for (i in 1:pdftools:: pdf_info(input$OCR_upload$datapath)$pages) {
          x[[i]] <- try(
            tesseract::ocr(image_read(y[i]), 
                           engine = tesseract(ocr.languages[match(input$OCR_language,ocr.languages$Language),2],
                                              datapath = paste0(getwd(),"/TesseractTrainingData") 
                           )
            )
          )
          incProgress(1/(pdftools:: pdf_info(input$OCR_upload$datapath)$pages), 
                      detail = paste0('Reading data ', i, " of ", (pdftools:: pdf_info(input$OCR_upload$datapath)$pages)))
        }
        for (i in 1:pdftools:: pdf_info(input$OCR_upload$datapath)$pages) {
          z <- try(paste(z, "\n",
                         "-------------Page ", i, "-------------\n", 
                         x[[i]]))
        }
        incProgress(1/(pdftools:: pdf_info(input$OCR_upload$datapath)$pages), 
                    detail = paste0('Combining data ', i, " of ", (pdftools:: pdf_info(input$OCR_upload$datapath)$pages)))
        
      })
    } else {
      withProgress(message = 'OCR of images', value = 0, {
        z <- try(tesseract::ocr(image_read(input$OCR_upload$datapath), 
                                engine = tesseract(ocr.languages[match(input$OCR_language,ocr.languages$Language),2],
                                                   datapath = paste0(getwd(),"/TesseractTrainingData")
                                )
        )
        )
      })
    }
    output$OCR_text_UI <- renderUI(
      HTML(str_replace_all(z, "\n", "<br>"))
    )
    output$OCR_text_Download_UI <- renderUI(
      downloadButton("OCR_text_Download", HTML('Download the OCR text'))
    )
    output$htmlInstructions1_OCR <- NULL
    output$htmlInstructions2_OCR <- renderUI(HTML(Instructions_OCR_1))
    output$OCR_text_Download <- downloadHandler( 
      filename = "OCR.txt", 
      content = function(file) {
        write.table(z, file, 
                    row.names = FALSE, col.names = FALSE,
                    quote = FALSE
        )
      } 
    )
    output$htmlMsg1_OCR <- renderUI(
      HTML('<h2 style="color:darkgreen; background-color:yellow"><b>
      OCR successfully completed! Please see the results below.</b></h2>')  
    )
    output$Header_OCR <- renderUI(
      HTML('<h3 style = "font-size:24px; color:purple;"><b>OCR text</b></h3>')
    )
    output$OCR_one_more_UI <- renderUI(
      actionButton("OCR_one_more", HTML('Perform one more OCR'))
    )
    output$OCR_language_UI <- NULL
    output$OCR_upload_UI <- NULL
  })
  
  # Data extraction from plots events ####
  observeEvent(input$PlotExtract, {
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[8]))
    panelchoice <- "panel9"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[c(1:2,9)], 
                       selected = FirstSelection[9])
    output$htmlMsg1_PlotExtract <- NULL
    output$Header_PlotExtract <- NULL
  })
  observeEvent(input$skip_instructions_PlotExtract, {
    output$htmlInstructions1_PlotExtract <- NULL
    output$htmlInstructions2_PlotExtract <- renderUI(HTML(Instructions_PlotExtract_1))
    output$skip_instructions_PlotExtract_UI <- NULL
  })
  output$PlotExtract_UploadPlot_UI <- renderUI(
    fileInput("PlotExtract_UploadPlot", "Please upload an image file to begin",
              accept = "image/*")
  )
  output$PlotExtract_UploadedPlot_UI <- NULL
  output$PlotExtract_PlotType_UI <- NULL
  output$PlotExtract_Confirm_PlotType_UI <- NULL
  output$PlotExtract_Change_PlotType_UI <- NULL
  output$PlotExtract_DisplaySelection <- NULL
  output$PlotExtract_SelectionMessage <- NULL
  output$PlotExtract_ResetPlot_UI <- NULL
  output$PlotExtract_Remove_Last_UI <- NULL
  output$PlotExtract_UploadNewPlot_UI <- NULL
  output$PlotExtract_PlotRotate_UI <- NULL
  output$PlotExtract_DownloadModifiedPlot_UI <- NULL
  output$PlotExtract_x_min_UI <- NULL
  output$PlotExtract_x_max_UI <- NULL
  output$PlotExtract_y_min_UI <- NULL
  output$PlotExtract_y_max_UI <- NULL
  output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
  output$PlotExtract_Change_y_min_y_max_UI <- NULL
  output$PlotExtract_Groups_UI <- NULL
  output$PlotExtract_Confirm_Groups_UI <- NULL
  output$PlotExtract_Change_Groups_UI <- NULL
  output$PlotExtract_TimePoints_UI <- NULL
  output$PlotExtract_Confirm_TimePoints_UI <- NULL
  output$PlotExtract_Change_TimePoints_UI <- NULL
  output$PlotExtract_KM_TimePoints_1_UI <- NULL
  output$PlotExtract_KM_TimePoints_2_UI <- NULL
  output$PlotExtract_KM_TimePoints_3_UI <- NULL
  output$PlotExtract_KM_TimePoints_4_UI <- NULL
  output$PlotExtract_KM_TimePoints_5_UI <- NULL
  output$PlotExtract_KM_TimePoints_6_UI <- NULL
  output$PlotExtract_KM_TimePoints_7_UI <- NULL
  output$PlotExtract_KM_TimePoints_8_UI <- NULL
  output$PlotExtract_KM_TimePoints_9_UI <- NULL
  output$PlotExtract_KM_TimePoints_10_UI <- NULL
  output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
  output$PlotExtract_Change_KM_TimePoints_UI <- NULL
  output$htmlMsg1_PlotExtract <- NULL
  output$PlotExtract_DisplayNextStep <- NULL
  output$PlotExtract_Confirm_DataPoints_UI <- NULL
  output$PlotExtract_Skip_MinMax_UI<- NULL
  output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
  output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
  output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
  output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
  output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
  output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
  output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
  output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
  output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
  output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
  output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
  output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
  output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
  output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
  output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
  output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
  output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
  output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
  output$PlotExtract_DownloadResults_UI <- NULL
  rv$x <- NULL
  rv$y <- NULL
  rv$KM_Calculations_Step1 <- NULL
  rv$KM_Calculations_Step2 <- NULL
  rv$PlotExtract_FinalResults <- NULL
  rv$points_values <- NULL
  rv$group_numbers <- NULL
  # Upload plot
  observeEvent(input$PlotExtract_UploadPlot,{
    rv$UploadedPlot <- image_border(
      image_trim(
        image_read(
          input$PlotExtract_UploadPlot$datapath
        )
      ), color = "darkblue",geometry = "1x1"
    )
    rv$x_pixels <- rv$UploadedPlot[[1]][[2]]
    rv$y_pixels <- rv$UploadedPlot[[1]][[3]]
    eval(parse(text= PlotClick_No))
    output$PlotExtract_UploadedPlot <- renderPlot({
      plot({
        par(mar=c(0, 0, 0, 0))
        xlim = c(0, rv$x_pixels)
        ylim = c(0, rv$y_pixels)
        rv$UploadedPlot
      })
    }, width = 750,
    height = 750)
    output$PlotExtract_UploadPlot_UI <- NULL
    output$PlotExtract_UploadNewPlot_UI <- renderUI(
      actionButton("PlotExtract_UploadNewPlot", "Upload new Plot")
    ) 
    output$PlotExtract_PlotType_UI <- renderUI(
      radioButtons("PlotExtract_PlotType",
                   "Enter the plot type", 
                   choices = PlotExtract_PlotTypes,
                   inline = FALSE,
                   selected = PlotExtract_PlotTypes[1])
    )
    output$PlotExtract_Confirm_PlotType_UI <- renderUI(
      actionButton("PlotExtract_Confirm_PlotType", "Confirm: plot type")
    )
    output$PlotExtract_PlotRotate_UI <- renderUI(
      actionButton("PlotExtract_PlotRotate", "Rotate the plot anti-clockwise")
    )
  })
  # Upload New Plot
  observeEvent(input$PlotExtract_UploadNewPlot,{
    output$PlotExtract_UploadPlot_UI <- renderUI(
      fileInput("PlotExtract_UploadPlot", "Please upload an image file to begin",
                accept = "image/*")
    )
    output$PlotExtract_UploadedPlot_UI <- NULL
    output$PlotExtract_PlotType_UI <- NULL
    output$PlotExtract_Confirm_PlotType_UI <- NULL
    output$PlotExtract_Change_PlotType_UI <- NULL
    output$PlotExtract_DisplaySelection <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_ResetPlot_UI <- NULL
    output$PlotExtract_Remove_Last_UI <- NULL
    output$PlotExtract_UploadNewPlot_UI <- NULL
    output$PlotExtract_PlotRotate_UI <- NULL
    output$PlotExtract_DownloadModifiedPlot_UI <- NULL
    output$PlotExtract_x_min_UI <- NULL
    output$PlotExtract_x_max_UI <- NULL
    output$PlotExtract_y_min_UI <- NULL
    output$PlotExtract_y_max_UI <- NULL
    output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
    output$PlotExtract_Change_y_min_y_max_UI <- NULL
    output$PlotExtract_Groups_UI <- NULL
    output$PlotExtract_Confirm_Groups_UI <- NULL
    output$PlotExtract_Change_Groups_UI <- NULL
    output$PlotExtract_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_TimePoints_UI <- NULL
    output$PlotExtract_Change_TimePoints_UI <- NULL
    output$PlotExtract_KM_TimePoints_1_UI <- NULL
    output$PlotExtract_KM_TimePoints_2_UI <- NULL
    output$PlotExtract_KM_TimePoints_3_UI <- NULL
    output$PlotExtract_KM_TimePoints_4_UI <- NULL
    output$PlotExtract_KM_TimePoints_5_UI <- NULL
    output$PlotExtract_KM_TimePoints_6_UI <- NULL
    output$PlotExtract_KM_TimePoints_7_UI <- NULL
    output$PlotExtract_KM_TimePoints_8_UI <- NULL
    output$PlotExtract_KM_TimePoints_9_UI <- NULL
    output$PlotExtract_KM_TimePoints_10_UI <- NULL
    output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
    output$PlotExtract_Change_KM_TimePoints_UI <- NULL
    output$htmlMsg1_PlotExtract <- NULL
    output$PlotExtract_DisplayNextStep <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$x_min <- NULL
    rv$x_max <- NULL
    rv$y_min <- NULL
    rv$y_max <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
  })
  # Confirm plot type
  observeEvent(input$PlotExtract_Confirm_PlotType,{
    eval(parse(text= PlotClick_No))
    output$PlotExtract_PlotType_UI <- NULL
    rv$plot_number <- match(input$PlotExtract_PlotType,
                            PlotExtract_PlotTypes)
    eval(parse(text =
                 PlotExtract_y_min_y_max[rv$plot_number]
    ))
    if ((rv$plot_number >=3) & (rv$plot_number <=5)) {
      output$PlotExtract_Confirm_y_min_y_max_UI <- renderUI(
        actionButton("PlotExtract_Confirm_y_min_y_max", "Confirm: min/max y values")
      )
    } else {
      output$PlotExtract_Confirm_y_min_y_max_UI <- renderUI(
        actionButton("PlotExtract_Confirm_y_min_y_max", "Confirm: min/max x, y values")
      )
    }
    output$PlotExtract_Change_PlotType_UI <- renderUI(
      actionButton("PlotExtract_Change_PlotType", "Change: plot type")
    )
    output$PlotExtract_DisplaySelection <- renderUI(
      HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
           '<b>Plot type:</b> ', input$PlotExtract_PlotType)
    )
    output$PlotExtract_PlotType_UI <- NULL
    output$PlotExtract_Confirm_PlotType_UI <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_ResetPlot_UI <- NULL
    output$PlotExtract_Remove_Last_UI <- NULL
    output$PlotExtract_DownloadModifiedPlot_UI <- NULL
    output$PlotExtract_Change_y_min_y_max_UI <- NULL
    output$PlotExtract_Groups_UI <- NULL
    output$PlotExtract_Confirm_Groups_UI <- NULL
    output$PlotExtract_Change_Groups_UI <- NULL
    output$PlotExtract_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_TimePoints_UI <- NULL
    output$PlotExtract_Change_TimePoints_UI <- NULL
    output$PlotExtract_KM_TimePoints_1_UI <- NULL
    output$PlotExtract_KM_TimePoints_2_UI <- NULL
    output$PlotExtract_KM_TimePoints_3_UI <- NULL
    output$PlotExtract_KM_TimePoints_4_UI <- NULL
    output$PlotExtract_KM_TimePoints_5_UI <- NULL
    output$PlotExtract_KM_TimePoints_6_UI <- NULL
    output$PlotExtract_KM_TimePoints_7_UI <- NULL
    output$PlotExtract_KM_TimePoints_8_UI <- NULL
    output$PlotExtract_KM_TimePoints_9_UI <- NULL
    output$PlotExtract_KM_TimePoints_10_UI <- NULL
    output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
    output$PlotExtract_Change_KM_TimePoints_UI <- NULL
    output$htmlMsg1_PlotExtract <- NULL
    output$PlotExtract_DisplayNextStep <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$x_min <- NULL
    rv$x_max <- NULL
    rv$y_min <- NULL
    rv$y_max <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
  })
  # Change plot type
  observeEvent(input$PlotExtract_Change_PlotType,{
    eval(parse(text= PlotClick_No))
    output$PlotExtract_PlotType_UI <- renderUI(
      radioButtons("PlotExtract_PlotType",
                   "Enter the plot type", 
                   choices = PlotExtract_PlotTypes,
                   inline = FALSE,
                   selected = input$PlotExtract_PlotType)
    )
    output$PlotExtract_Confirm_PlotType_UI <- renderUI(
      actionButton("PlotExtract_Confirm_PlotType", "Confirm plot type")
    )
    output$PlotExtract_Change_PlotType_UI <- NULL
    output$PlotExtract_DisplaySelection <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_ResetPlot_UI <- NULL
    output$PlotExtract_Remove_Last_UI <- NULL
    output$PlotExtract_DownloadModifiedPlot_UI <- NULL
    output$PlotExtract_x_min_UI <- NULL
    output$PlotExtract_x_max_UI <- NULL
    output$PlotExtract_y_min_UI <- NULL
    output$PlotExtract_y_max_UI <- NULL
    output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
    output$PlotExtract_Change_y_min_y_max_UI <- NULL
    output$PlotExtract_Groups_UI <- NULL
    output$PlotExtract_Confirm_Groups_UI <- NULL
    output$PlotExtract_Change_Groups_UI <- NULL
    output$PlotExtract_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_TimePoints_UI <- NULL
    output$PlotExtract_Change_TimePoints_UI <- NULL
    output$PlotExtract_KM_TimePoints_1_UI <- NULL
    output$PlotExtract_KM_TimePoints_2_UI <- NULL
    output$PlotExtract_KM_TimePoints_3_UI <- NULL
    output$PlotExtract_KM_TimePoints_4_UI <- NULL
    output$PlotExtract_KM_TimePoints_5_UI <- NULL
    output$PlotExtract_KM_TimePoints_6_UI <- NULL
    output$PlotExtract_KM_TimePoints_7_UI <- NULL
    output$PlotExtract_KM_TimePoints_8_UI <- NULL
    output$PlotExtract_KM_TimePoints_9_UI <- NULL
    output$PlotExtract_KM_TimePoints_10_UI <- NULL
    output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
    output$PlotExtract_Change_KM_TimePoints_UI <- NULL
    output$htmlMsg1_PlotExtract <- NULL
    output$PlotExtract_DisplayNextStep <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$x_min <- NULL
    rv$x_max <- NULL
    rv$y_min <- NULL
    rv$y_max <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
  })
  # Confirm y_min and y_max####
  observeEvent(input$PlotExtract_Confirm_y_min_y_max, {
    if (
      (((rv$plot_number >=3) & (rv$plot_number <=5)) & 
       (input$PlotExtract_y_min < input$PlotExtract_y_max))
    ) {
      eval(parse(text= PlotClick_No))
      output$PlotExtract_Change_y_min_y_max_UI <- renderUI(
        actionButton("PlotExtract_Change_y_min_y_max", "Change: min/max y values")
      )
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max)
      )
      output$PlotExtract_Groups_UI <- renderUI(
        sliderInput("PlotExtract_Groups",
                    "Enter the number of groups",
                    min = 1,
                    max = 10,
                    value = 2
        )
      )
      output$PlotExtract_Confirm_Groups_UI <- renderUI(
        actionButton("PlotExtract_Confirm_Groups", "Confirm the number of groups")
      )
      rv$y_min <- input$PlotExtract_y_min
      rv$y_max <- input$PlotExtract_y_max
      output$PlotExtract_PlotType_UI <- NULL
      output$PlotExtract_Confirm_PlotType_UI <- NULL
      output$PlotExtract_SelectionMessage <- NULL
      output$PlotExtract_ResetPlot_UI <- NULL
      output$PlotExtract_Remove_Last_UI <- NULL
      output$PlotExtract_DownloadModifiedPlot_UI <- NULL
      output$PlotExtract_x_min_UI <- NULL
      output$PlotExtract_x_max_UI <- NULL
      output$PlotExtract_y_min_UI <- NULL
      output$PlotExtract_y_max_UI <- NULL
      output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
      output$PlotExtract_Change_Groups_UI <- NULL
      output$PlotExtract_TimePoints_UI <- NULL
      output$PlotExtract_Confirm_TimePoints_UI <- NULL
      output$PlotExtract_Change_TimePoints_UI <- NULL
      output$PlotExtract_KM_TimePoints_1_UI <- NULL
      output$PlotExtract_KM_TimePoints_2_UI <- NULL
      output$PlotExtract_KM_TimePoints_3_UI <- NULL
      output$PlotExtract_KM_TimePoints_4_UI <- NULL
      output$PlotExtract_KM_TimePoints_5_UI <- NULL
      output$PlotExtract_KM_TimePoints_6_UI <- NULL
      output$PlotExtract_KM_TimePoints_7_UI <- NULL
      output$PlotExtract_KM_TimePoints_8_UI <- NULL
      output$PlotExtract_KM_TimePoints_9_UI <- NULL
      output$PlotExtract_KM_TimePoints_10_UI <- NULL
      output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
      output$PlotExtract_Change_KM_TimePoints_UI <- NULL
      output$PlotExtract_DisplayNextStep <- NULL
      output$PlotExtract_Confirm_DataPoints_UI <- NULL
      output$PlotExtract_Skip_MinMax_UI<- NULL
      output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
      output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
      output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
      output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
      output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
      output$PlotExtract_DownloadResults_UI <- NULL
      rv$x <- NULL
      rv$y <- NULL
      rv$KM_Calculations_Step1 <- NULL
      rv$KM_Calculations_Step2 <- NULL
      rv$PlotExtract_FinalResults <- NULL
      rv$points_values <- NULL
      rv$group_numbers <- NULL
    } else if (
      (((rv$plot_number <=2) | (rv$plot_number >=6))) & 
      ((!is.na(input$PlotExtract_x_min)) & (!is.na(input$PlotExtract_x_max))) &
      ((length(input$PlotExtract_x_min) > 0) & (length(input$PlotExtract_x_max) > 0)) &
      ((input$PlotExtract_x_min < input$PlotExtract_x_max) & (input$PlotExtract_y_min < input$PlotExtract_y_max))
    ) {
      eval(parse(text= PlotClick_No))
      output$PlotExtract_Change_y_min_y_max_UI <- renderUI(
        actionButton("PlotExtract_Change_y_min_y_max", "Change: min/max x, y values")
      )
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum x value:</b> ', input$PlotExtract_x_min, '<br>',
             '<b>Maximum x value:</b> ', input$PlotExtract_x_max, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max)
      )
      output$PlotExtract_Groups_UI <- renderUI(
        sliderInput("PlotExtract_Groups",
                    "Enter the number of groups",
                    min = 1,
                    max = 10,
                    value = 2
        )
      )
      output$PlotExtract_Confirm_Groups_UI <- renderUI(
        actionButton("PlotExtract_Confirm_Groups", "Confirm the number of groups")
      )
      rv$x_min <- input$PlotExtract_x_min
      rv$x_max <- input$PlotExtract_x_max
      rv$y_min <- input$PlotExtract_y_min
      rv$y_max <- input$PlotExtract_y_max
      output$PlotExtract_PlotType_UI <- NULL
      output$PlotExtract_Confirm_PlotType_UI <- NULL
      output$PlotExtract_SelectionMessage <- NULL
      output$PlotExtract_ResetPlot_UI <- NULL
      output$PlotExtract_Remove_Last_UI <- NULL
      output$PlotExtract_DownloadModifiedPlot_UI <- NULL
      output$PlotExtract_x_min_UI <- NULL
      output$PlotExtract_x_max_UI <- NULL
      output$PlotExtract_y_min_UI <- NULL
      output$PlotExtract_y_max_UI <- NULL
      output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
      output$PlotExtract_Change_Groups_UI <- NULL
      output$PlotExtract_TimePoints_UI <- NULL
      output$PlotExtract_Confirm_TimePoints_UI <- NULL
      output$PlotExtract_Change_TimePoints_UI <- NULL
      output$PlotExtract_KM_TimePoints_1_UI <- NULL
      output$PlotExtract_KM_TimePoints_2_UI <- NULL
      output$PlotExtract_KM_TimePoints_3_UI <- NULL
      output$PlotExtract_KM_TimePoints_4_UI <- NULL
      output$PlotExtract_KM_TimePoints_5_UI <- NULL
      output$PlotExtract_KM_TimePoints_6_UI <- NULL
      output$PlotExtract_KM_TimePoints_7_UI <- NULL
      output$PlotExtract_KM_TimePoints_8_UI <- NULL
      output$PlotExtract_KM_TimePoints_9_UI <- NULL
      output$PlotExtract_KM_TimePoints_10_UI <- NULL
      output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
      output$PlotExtract_Change_KM_TimePoints_UI <- NULL
      output$PlotExtract_DisplayNextStep <- NULL
      output$PlotExtract_Confirm_DataPoints_UI <- NULL
      output$PlotExtract_Skip_MinMax_UI<- NULL
      output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
      output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
      output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
      output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
      output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
      output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
      output$PlotExtract_DownloadResults_UI <- NULL
      rv$x <- NULL
      rv$y <- NULL
      rv$KM_Calculations_Step1 <- NULL
      rv$KM_Calculations_Step2 <- NULL
      rv$PlotExtract_FinalResults <- NULL
      rv$points_values <- NULL
      rv$group_numbers <- NULL
    } else {
      if ((rv$plot_number <=2) | (rv$plot_number >=6)) {
        output$PlotExtract_SelectionMessage <- renderUI(
          HTML('<h3 style = "color:red;background-color:yellow">
              Minimum x and y values should be less than maximum x and y values. 
              x values should not be left empty.
              Please enter new values and try again.
               </h3>'
          )
        )
      } else {
        output$PlotExtract_SelectionMessage <- renderUI(
          HTML('<h3 style = "color:red;background-color:yellow">
              Minimum y values should be less than maximum y values. 
              Please enter new values and try again.
               </h3>'
          )
        )
      }
    }
  })
  # Change y_min and y_max
  observeEvent(input$PlotExtract_Change_y_min_y_max, {
    eval(parse(text= PlotClick_No))
    eval(parse(text =
                 PlotExtract_y_min_y_max_change[rv$plot_number]
    ))
    output$PlotExtract_Confirm_y_min_y_max_UI <- renderUI(
      actionButton("PlotExtract_Confirm_y_min_y_max", "Confirm: min/max y values")
    )
    output$PlotExtract_DisplaySelection <- renderUI(
      HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
           '<b>Plot type:</b> ', input$PlotExtract_PlotType)
    )
    output$PlotExtract_PlotType_UI <- NULL
    output$PlotExtract_Confirm_PlotType_UI <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_ResetPlot_UI <- NULL
    output$PlotExtract_Remove_Last_UI <- NULL
    output$PlotExtract_DownloadModifiedPlot_UI <- NULL
    output$PlotExtract_Change_y_min_y_max_UI <- NULL
    output$PlotExtract_Groups_UI <- NULL
    output$PlotExtract_Confirm_Groups_UI <- NULL
    output$PlotExtract_Change_Groups_UI <- NULL
    output$PlotExtract_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_TimePoints_UI <- NULL
    output$PlotExtract_Change_TimePoints_UI <- NULL
    output$PlotExtract_KM_TimePoints_1_UI <- NULL
    output$PlotExtract_KM_TimePoints_2_UI <- NULL
    output$PlotExtract_KM_TimePoints_3_UI <- NULL
    output$PlotExtract_KM_TimePoints_4_UI <- NULL
    output$PlotExtract_KM_TimePoints_5_UI <- NULL
    output$PlotExtract_KM_TimePoints_6_UI <- NULL
    output$PlotExtract_KM_TimePoints_7_UI <- NULL
    output$PlotExtract_KM_TimePoints_8_UI <- NULL
    output$PlotExtract_KM_TimePoints_9_UI <- NULL
    output$PlotExtract_KM_TimePoints_10_UI <- NULL
    output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
    output$PlotExtract_Change_KM_TimePoints_UI <- NULL
    output$htmlMsg1_PlotExtract <- NULL
    output$PlotExtract_DisplayNextStep <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$x_min <- NULL
    rv$x_max <- NULL
    rv$y_min <- NULL
    rv$y_max <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
  })
  # Confirm groups
  observeEvent(input$PlotExtract_Confirm_Groups, {
    eval(parse(text= PlotClick_No))
    output$PlotExtract_Change_Groups_UI <- renderUI(
      actionButton("PlotExtract_Change_Groups", "Change: number of groups")
    )
    if ((rv$plot_number <=2) | (rv$plot_number >=6)){
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum x value:</b> ', input$PlotExtract_x_min, '<br>',
             '<b>Maximum x value:</b> ', input$PlotExtract_x_max, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups)
      )
    } else {
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups)
      )
    } 
    output$PlotExtract_TimePoints_UI <- renderUI(
      sliderInput("PlotExtract_TimePoints",
                  "Enter the number of time points",
                  min = 1,
                  max = 10,
                  value = 2
      )
    )
    output$PlotExtract_Confirm_TimePoints_UI <- renderUI(
      actionButton("PlotExtract_Confirm_TimePoints", "Confirm: number of time points")
    )
    output$PlotExtract_PlotType_UI <- NULL
    output$PlotExtract_Confirm_PlotType_UI <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_ResetPlot_UI <- NULL
    output$PlotExtract_Remove_Last_UI <- NULL
    output$PlotExtract_DownloadModifiedPlot_UI <- NULL
    output$PlotExtract_x_min_UI <- NULL
    output$PlotExtract_x_max_UI <- NULL
    output$PlotExtract_y_min_UI <- NULL
    output$PlotExtract_y_max_UI <- NULL
    output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
    output$PlotExtract_Groups_UI <- NULL
    output$PlotExtract_Confirm_Groups_UI <- NULL
    output$PlotExtract_Change_TimePoints_UI <- NULL
    output$PlotExtract_KM_TimePoints_1_UI <- NULL
    output$PlotExtract_KM_TimePoints_2_UI <- NULL
    output$PlotExtract_KM_TimePoints_3_UI <- NULL
    output$PlotExtract_KM_TimePoints_4_UI <- NULL
    output$PlotExtract_KM_TimePoints_5_UI <- NULL
    output$PlotExtract_KM_TimePoints_6_UI <- NULL
    output$PlotExtract_KM_TimePoints_7_UI <- NULL
    output$PlotExtract_KM_TimePoints_8_UI <- NULL
    output$PlotExtract_KM_TimePoints_9_UI <- NULL
    output$PlotExtract_KM_TimePoints_10_UI <- NULL
    output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
    output$PlotExtract_Change_KM_TimePoints_UI <- NULL
    output$htmlMsg1_PlotExtract <- NULL
    output$PlotExtract_DisplayNextStep <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
  })
  # Change number of groups
  observeEvent(input$PlotExtract_Change_Groups, {
    eval(parse(text= PlotClick_No))
    if ((rv$plot_number <=2) | (rv$plot_number >=6)){
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum x value:</b> ', input$PlotExtract_x_min, '<br>',
             '<b>Maximum x value:</b> ', input$PlotExtract_x_max, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max)
      )
    } else {
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>')
      )
    }
    output$PlotExtract_Groups_UI <- renderUI(
      sliderInput("PlotExtract_Groups",
                  "Enter the number of groups",
                  min = 1,
                  max = 10,
                  value = input$PlotExtract_Groups
      )
    )
    output$PlotExtract_Confirm_Groups_UI <- renderUI(
      actionButton("PlotExtract_Confirm_Groups", "Confirm: number of groups")
    )
    output$PlotExtract_PlotType_UI <- NULL
    output$PlotExtract_Confirm_PlotType_UI <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_ResetPlot_UI <- NULL
    output$PlotExtract_Remove_Last_UI <- NULL
    output$PlotExtract_DownloadModifiedPlot_UI <- NULL
    output$PlotExtract_x_min_UI <- NULL
    output$PlotExtract_x_max_UI <- NULL
    output$PlotExtract_y_min_UI <- NULL
    output$PlotExtract_y_max_UI <- NULL
    output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
    output$PlotExtract_Change_Groups_UI <- NULL
    output$PlotExtract_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_TimePoints_UI <- NULL
    output$PlotExtract_Change_TimePoints_UI <- NULL
    output$PlotExtract_KM_TimePoints_1_UI <- NULL
    output$PlotExtract_KM_TimePoints_2_UI <- NULL
    output$PlotExtract_KM_TimePoints_3_UI <- NULL
    output$PlotExtract_KM_TimePoints_4_UI <- NULL
    output$PlotExtract_KM_TimePoints_5_UI <- NULL
    output$PlotExtract_KM_TimePoints_6_UI <- NULL
    output$PlotExtract_KM_TimePoints_7_UI <- NULL
    output$PlotExtract_KM_TimePoints_8_UI <- NULL
    output$PlotExtract_KM_TimePoints_9_UI <- NULL
    output$PlotExtract_KM_TimePoints_10_UI <- NULL
    output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
    output$PlotExtract_Change_KM_TimePoints_UI <- NULL
    output$htmlMsg1_PlotExtract <- NULL
    output$PlotExtract_DisplayNextStep <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
  })
  # Confirm time points
  observeEvent(input$PlotExtract_Confirm_TimePoints, {
    rv$points_max <- 
      2 + PlotExtract_Points_EachGroup_EachTimePoint[rv$plot_number] * input$PlotExtract_Groups * input$PlotExtract_TimePoints
    # 3 additional point for KM curve and 2 additional points for line plots
    if (rv$plot_number <=2){
      rv$points_max <- rv$points_max + 3
      rv$points_names <- c(
        "Point which indicates the junction of minimums of x axis and y axis", 
        "Maximum x in plot",
        "Maximum y in plot"
      )
      rv$points_times_groups <- rep("Not applicable",3)
    } else if (rv$plot_number >=6){
      rv$points_max <- rv$points_max + 2
      rv$points_names <- c(
        "Minimum x in plot", "Maximum x in plot",
        "Minimum y in plot", "Maximum y in plot"
      )
      rv$points_times_groups <- rep("Not applicable",4)
    } else {
      rv$points_names <- c(
        "Minimum y in plot", "Maximum y in plot"
      )
      rv$points_times_groups <- rep("Not applicable",2)
    }
    for (i in 1:input$PlotExtract_Groups){
      for (j in 1:input$PlotExtract_TimePoints){
        rv$points_names <- c(rv$points_names, paste0(
          PlotExtract_Points_Names_EachGroup_EachTimePoint[[rv$plot_number]]
          [1:length(PlotExtract_Points_Names_EachGroup_EachTimePoint[[rv$plot_number]])], 
          ' (Group ', i , '): time ',j
        )
        )
        if ((rv$plot_number >=3) & (rv$plot_number <=5)){
          rv$points_times_groups <- c(rv$points_times_groups, 
                                      rep(paste0(j,"_",i),length(PlotExtract_Points_Names_EachGroup_EachTimePoint[[rv$plot_number]])))
        } else {
          rv$points_times_groups <- c(rv$points_times_groups, 
                                      rep(j,length(PlotExtract_Points_Names_EachGroup_EachTimePoint[[rv$plot_number]])))
        }
      }
    }
    if (rv$plot_number <=2){
      rv$points_names <- c(rv$points_names, 
                           'First censored patient (first tick): <br>
                             <i>If minimum and maximum follow-up are directly reported click on "Skip: min/max follow-up".<br>
                             If minimum and maximum follow-up are not reported, click on first tick if available. Otherwise, click on "Skip: min/max follow-up"</i>', 
                           'Last censored patient (last tick): <br>
                             <i>If minimum and maximum follow-up are directly reported click on "Skip: min/max follow-up".<br>
                             If minimum and maximum follow-up are not reported, click on first tick if available. Otherwise, click on "Skip: min/max follow-up"</i>'
      )
      rv$points_colours_viridis <- viridis(1 + input$PlotExtract_Groups)
      rv$points_times_groups <- c(rv$points_times_groups,
                                  "Minimum follow-up",
                                  "Maximum follow-up")
      rv$points_colours <- rep(rv$points_colours_viridis[1],3)
      rv$points_symbol <- rep(4,3)
      rv$lines_required <- c("No", "Yes", "Yes")
    } else if (rv$plot_number >=6){
      rv$points_colours_viridis <- viridis(1 + input$PlotExtract_Groups)
      rv$points_colours <- rep(rv$points_colours_viridis[1],4)
      rv$points_symbol <- rep(4,4)
      rv$lines_required <- c("No", "Yes", "No", "Yes")
    } else {
      rv$points_colours_viridis <- viridis(1 + input$PlotExtract_Groups)
      rv$points_colours <- rep(rv$points_colours_viridis[1],2)
      rv$points_symbol <- rep(4,2)
      rv$lines_required <- c("No", "Yes")
    }
    for (i in 1:input$PlotExtract_Groups) {
      rv$points_colours <- c(rv$points_colours,
                             rep(rv$points_colours_viridis[(i+1)],(PlotExtract_Points_EachGroup_EachTimePoint[rv$plot_number]*
                                                                     input$PlotExtract_TimePoints))
      )
      rv$points_symbol <- c(rv$points_symbol,
                            rep((14+i),(PlotExtract_Points_EachGroup_EachTimePoint[rv$plot_number]*
                                          input$PlotExtract_TimePoints))
      )
      if (i == 1) {
        if (PlotExtract_Points_EachGroup_EachTimePoint[rv$plot_number] == 1) {
          rv$lines_required <- c(rv$lines_required,
                                 rep("Yes", input$PlotExtract_TimePoints)
          )
        } else {
          rv$lines_required <- c(rv$lines_required,
                                 rep(c("Yes", rep("No",(PlotExtract_Points_EachGroup_EachTimePoint[rv$plot_number]-1))),
                                     input$PlotExtract_TimePoints
                                 )
          )
        }
      } else {
        if ((rv$plot_number >=3) & (rv$plot_number <=5)){
          rv$lines_required <- c(rv$lines_required,
                                 rep(c("Yes", rep("No",(PlotExtract_Points_EachGroup_EachTimePoint[rv$plot_number]-1))),
                                     input$PlotExtract_TimePoints
                                 )
          )
        } else {
          rv$lines_required <- c(rv$lines_required,
                                 rep("No", PlotExtract_Points_EachGroup_EachTimePoint[rv$plot_number]*
                                       input$PlotExtract_TimePoints
                                 )
          )
        }
      }
    }
    if (rv$plot_number <=2){
      rv$points_colours <- c(rv$points_colours,
                             rep(rv$points_colours_viridis[1],2)
      )
      rv$points_symbol <- c(rv$points_symbol, 10, 10)
      rv$lines_required <- c(rv$lines_required, "Yes", "Yes")
    }
    output$PlotExtract_Change_TimePoints_UI <- renderUI(
      actionButton("PlotExtract_Change_TimePoints", "Change: number of time points")
    )
    if ((rv$plot_number <=2) | (rv$plot_number >=6)){
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum x value:</b> ', input$PlotExtract_x_min, '<br>',
             '<b>Maximum x value:</b> ', input$PlotExtract_x_max, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups, '<br>',
             '<b>Number of time points:</b> ', input$PlotExtract_TimePoints)
      )
    } else {
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups, '<br>',
             '<b>Number of time points:</b> ', input$PlotExtract_TimePoints)
      )
    }
    output$PlotExtract_PlotType_UI <- NULL
    output$PlotExtract_Confirm_PlotType_UI <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_x_min_UI <- NULL
    output$PlotExtract_x_max_UI <- NULL
    output$PlotExtract_y_min_UI <- NULL
    output$PlotExtract_y_max_UI <- NULL
    output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
    output$PlotExtract_Groups_UI <- NULL
    output$PlotExtract_Confirm_Groups_UI <- NULL
    output$PlotExtract_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
    if ((rv$plot_number <=2) |
        (rv$plot_number >=6)){
      eval(parse(text= PlotClick_No))
      for (i in 1:input$PlotExtract_TimePoints) {
        if (i == 1) {
          output$PlotExtract_KM_TimePoints_1_UI <- renderUI(
            numericInput("PlotExtract_KM_TimePoints_1",
                         "Enter time point 1",
                         min = 1,
                         value = 1)
          )
        } else {
          eval(parse(text = 
                       paste0(
                         'output$PlotExtract_KM_TimePoints_',i,'_UI <- renderUI(
                           numericInput("PlotExtract_KM_TimePoints_',i,'",
                                        "Enter time point ',i,'",
                                        min = ifelse(
                                        (length(input$Plot_Extract_KM_TimePoints_',(i-1),') > 0),
                                        i,
                                        (input$PlotExtract_KM_TimePoints_',(i-1),' + 1)
                                        ),
                                        value = 
                                        ifelse(
                                        (length(input$Plot_Extract_KM_TimePoints_',(i-1),') > 0),
                                        i,
                                        (input$PlotExtract_KM_TimePoints_',(i-1),' + 1)
                                        )
                                        )
                         )'
                       )
          ))
        }
      }
      output$PlotExtract_Confirm_KM_TimePoints_UI <- renderUI(
        actionButton("PlotExtract_Confirm_KM_TimePoints", "Confirm: time points")
      )
      output$PlotExtract_ResetPlot_UI <- NULL
      output$PlotExtract_Remove_Last_UI <- NULL
      output$PlotExtract_DownloadModifiedPlot_UI <- NULL
      output$htmlMsg1_PlotExtract <- NULL
      output$PlotExtract_DisplayNextStep <- NULL
    } else {
      eval(parse(text= PlotClick_Yes))
      output$PlotExtract_KM_TimePoints_1_UI <- NULL
      output$PlotExtract_KM_TimePoints_2_UI <- NULL
      output$PlotExtract_KM_TimePoints_3_UI <- NULL
      output$PlotExtract_KM_TimePoints_4_UI <- NULL
      output$PlotExtract_KM_TimePoints_5_UI <- NULL
      output$PlotExtract_KM_TimePoints_6_UI <- NULL
      output$PlotExtract_KM_TimePoints_7_UI <- NULL
      output$PlotExtract_KM_TimePoints_8_UI <- NULL
      output$PlotExtract_KM_TimePoints_9_UI <- NULL
      output$PlotExtract_KM_TimePoints_10_UI <- NULL
      output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
      output$PlotExtract_Change_KM_TimePoints_UI <- NULL
      output$PlotExtract_ResetPlot_UI <- renderUI(
        actionButton("PlotExtract_ResetPlot", "Remove all data points")
      )
      output$PlotExtract_Remove_Last_UI <- renderUI(
        actionButton("PlotExtract_Remove_Last", "Remove last data point")
      )
      output$PlotExtract_DisplayNextStep <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Next step</b></h3>',
             'Click on the <b>',
             '<span style = "color:darkblue; background-color:yellow;">',
             rv$points_names[(length(rv$x) + 1)],
             '</b></span>'
        )
      )
    }
  })
  # Change number of time points
  observeEvent(input$PlotExtract_Change_TimePoints, {
    eval(parse(text= PlotClick_No))
    rv$points_max <- NULL
    if ((rv$plot_number <=2) | (rv$plot_number >=6)){
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum x value:</b> ', input$PlotExtract_x_min, '<br>',
             '<b>Maximum x value:</b> ', input$PlotExtract_x_max, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups)
      )
    } else {
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups)
      )
    }
    output$PlotExtract_TimePoints_UI <- renderUI(
      sliderInput("PlotExtract_TimePoints",
                  "Enter the number of time points",
                  min = 1,
                  max = 10,
                  value = input$PlotExtract_TimePoints
      )
    )
    output$PlotExtract_Confirm_TimePoints_UI <- renderUI(
      actionButton("PlotExtract_Confirm_TimePoints", "Confirm: number of time points")
    )
    output$PlotExtract_PlotType_UI <- NULL
    output$PlotExtract_Confirm_PlotType_UI <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_ResetPlot_UI <- NULL
    output$PlotExtract_Remove_Last_UI <- NULL
    output$PlotExtract_DownloadModifiedPlot_UI <- NULL
    output$PlotExtract_x_min_UI <- NULL
    output$PlotExtract_x_max_UI <- NULL
    output$PlotExtract_y_min_UI <- NULL
    output$PlotExtract_y_max_UI <- NULL
    output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
    output$PlotExtract_Groups_UI <- NULL
    output$PlotExtract_Confirm_Groups_UI <- NULL
    output$PlotExtract_Change_TimePoints_UI <- NULL
    output$PlotExtract_KM_TimePoints_1_UI <- NULL
    output$PlotExtract_KM_TimePoints_2_UI <- NULL
    output$PlotExtract_KM_TimePoints_3_UI <- NULL
    output$PlotExtract_KM_TimePoints_4_UI <- NULL
    output$PlotExtract_KM_TimePoints_5_UI <- NULL
    output$PlotExtract_KM_TimePoints_6_UI <- NULL
    output$PlotExtract_KM_TimePoints_7_UI <- NULL
    output$PlotExtract_KM_TimePoints_8_UI <- NULL
    output$PlotExtract_KM_TimePoints_9_UI <- NULL
    output$PlotExtract_KM_TimePoints_10_UI <- NULL
    output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
    output$PlotExtract_Change_KM_TimePoints_UI <- NULL
    output$htmlMsg1_PlotExtract <- NULL
    output$PlotExtract_DisplayNextStep <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
  })
  # Confirm KM time points
  observeEvent(input$PlotExtract_Confirm_KM_TimePoints, {
    rv$KM_TimePoints <- vector()
    for (i in 1:input$PlotExtract_TimePoints){
      rv$KM_TimePoints <- c(rv$KM_TimePoints,
                            eval(parse(text =
                                         paste0('input$PlotExtract_KM_TimePoints_',i)
                            ))
      )
    }
    output$htmlMsg1_PlotExtract <- renderUI(
      HTML('<h2 style="color:darkblue; background-color:yellow"><b>
       If you are unable to see the "Next step", "Remove all data points", or "Remove last data point", please scroll the screen up to view these.
       </b></h2>')  
    )
    output$PlotExtract_Change_KM_TimePoints_UI <- renderUI(
      actionButton("PlotExtract_Change_KM_TimePoints", "Change: time points")
    )
    if ((rv$plot_number <=2) | (rv$plot_number >=6)){
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum x value:</b> ', input$PlotExtract_x_min, '<br>',
             '<b>Maximum x value:</b> ', input$PlotExtract_x_max, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups, '<br>',
             '<b>Number of time points:</b> ', input$PlotExtract_TimePoints, '<br>',
             '<b>Time points:</b> ', paste0(rv$KM_TimePoints, collapse = ", ")
        )
      )
      for (i in 1:length(rv$KM_TimePoints)) {
        rv$points_names <- str_replace_all(
          rv$points_names,
          paste0(': time ', i),
          paste0(': time point ', i, ' (',rv$KM_TimePoints[i], ')' )
        )
      }
    } else {
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum x value:</b> ', input$PlotExtract_x_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups, '<br>',
             '<b>Number of time points:</b> ', input$PlotExtract_TimePoints, '<br>',
             '<b>Time points:</b> ', paste0(rv$KM_TimePoints, collapse = ", ")
        )
      )
    }
    eval(parse(text= PlotClick_Yes))
    output$PlotExtract_ResetPlot_UI <- renderUI(
      actionButton("PlotExtract_ResetPlot", "Remove all data points")
    )
    output$PlotExtract_Remove_Last_UI <- renderUI(
      actionButton("PlotExtract_Remove_Last", "Remove last data point")
    )
    output$PlotExtract_DisplayNextStep <- renderUI(
      HTML('<h3 style = "font-size:24px; color:purple;"><b>Next step</b></h3>',
           'Click on the <b>',
           '<span style = "color:darkblue; background-color:yellow;">',
           rv$points_names[(length(rv$x) + 1)],
           '</b></span>'
      )
    )
    output$PlotExtract_PlotType_UI <- NULL
    output$PlotExtract_Confirm_PlotType_UI <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_x_min_UI <- NULL
    output$PlotExtract_x_max_UI <- NULL
    output$PlotExtract_y_min_UI <- NULL
    output$PlotExtract_y_max_UI <- NULL
    output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
    output$PlotExtract_Groups_UI <- NULL
    output$PlotExtract_Confirm_Groups_UI <- NULL
    output$PlotExtract_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_TimePoints_UI <- NULL
    output$PlotExtract_KM_TimePoints_1_UI <- NULL
    output$PlotExtract_KM_TimePoints_2_UI <- NULL
    output$PlotExtract_KM_TimePoints_3_UI <- NULL
    output$PlotExtract_KM_TimePoints_4_UI <- NULL
    output$PlotExtract_KM_TimePoints_5_UI <- NULL
    output$PlotExtract_KM_TimePoints_6_UI <- NULL
    output$PlotExtract_KM_TimePoints_7_UI <- NULL
    output$PlotExtract_KM_TimePoints_8_UI <- NULL
    output$PlotExtract_KM_TimePoints_9_UI <- NULL
    output$PlotExtract_KM_TimePoints_10_UI <- NULL
    output$PlotExtract_Confirm_KM_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
  })
  # Change KM time points
  observeEvent(input$PlotExtract_Change_KM_TimePoints, {
    eval(parse(text= PlotClick_No))
    if ((rv$plot_number <=2) | (rv$plot_number >=6)){
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum x value:</b> ', input$PlotExtract_x_min, '<br>',
             '<b>Maximum x value:</b> ', input$PlotExtract_x_max, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups, '<br>',
             '<b>Number of time points:</b> ', input$PlotExtract_TimePoints)
      )
    } else {
      output$PlotExtract_DisplaySelection <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Your selection</b></h3>',
             '<b>Plot type:</b> ', input$PlotExtract_PlotType, '<br>',
             '<b>Minimum y value:</b> ', input$PlotExtract_y_min, '<br>',
             '<b>Maximum y value:</b> ', input$PlotExtract_y_max, '<br>',
             '<b>Number of groups:</b> ', input$PlotExtract_Groups, '<br>',
             '<b>Number of time points:</b> ', input$PlotExtract_TimePoints)
      )
    }
    for (i in 1:input$PlotExtract_TimePoints) {
      if (i == 1) {
        output$PlotExtract_KM_TimePoints_1_UI <- renderUI(
          numericInput("PlotExtract_KM_TimePoints_1",
                       "Enter time point 1",
                       min = 1,
                       value = rv$KM_TimePoints[1])
        )
      } else {
        eval(parse(text = 
                     paste0(
                       'output$PlotExtract_KM_TimePoints_',i,'_UI <- renderUI(
                           numericInput("PlotExtract_KM_TimePoints_',i,'",
                                        "Enter time point ',i,'",
                                        min = (input$PlotExtract_KM_TimePoints_',(i-1),' + 1),
                                        value = (input$PlotExtract_KM_TimePoints_',(i-1),' + 1))
                         )'
                     )
        ))
      }
    }
    output$PlotExtract_Confirm_KM_TimePoints_UI <- renderUI(
      actionButton("PlotExtract_Confirm_KM_TimePoints", "Confirm: time points")
    )
    output$PlotExtract_PlotType_UI <- NULL
    output$PlotExtract_Confirm_PlotType_UI <- NULL
    output$PlotExtract_SelectionMessage <- NULL
    output$PlotExtract_ResetPlot_UI <- NULL
    output$PlotExtract_Remove_Last_UI <- NULL
    output$PlotExtract_DownloadModifiedPlot_UI <- NULL
    output$PlotExtract_x_min_UI <- NULL
    output$PlotExtract_x_max_UI <- NULL
    output$PlotExtract_y_min_UI <- NULL
    output$PlotExtract_y_max_UI <- NULL
    output$PlotExtract_Confirm_y_min_y_max_UI <- NULL
    output$PlotExtract_Groups_UI <- NULL
    output$PlotExtract_Confirm_Groups_UI <- NULL
    output$PlotExtract_TimePoints_UI <- NULL
    output$PlotExtract_Confirm_TimePoints_UI <- NULL
    output$PlotExtract_Change_KM_TimePoints_UI <- NULL
    output$htmlMsg1_PlotExtract <- NULL
    output$PlotExtract_DisplayNextStep <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    rv$points_values <- NULL
    rv$group_numbers <- NULL
  })
  # If plot is clicked
  observeEvent(input$Plot_Click,{
    if (length(rv$x) < rv$points_max){
      if (rv$plot_number <=2){
        if (length(rv$x) < 1) {
          rv$x <- c(rv$x,input$Plot_Click$x)
          rv$y <- c(rv$y,input$Plot_Click$y)
        } else if (length(rv$x) == 1) {
          rv$x <- c(rv$x,input$Plot_Click$x)
          rv$y <- c(rv$y,rv$y)
        } else if (length(rv$x) == 2) {
          rv$x <- c(rv$x,rv$x[1])
          rv$y <- c(rv$y,input$Plot_Click$y)
        } else if (length(rv$x) < (rv$points_max-2)){
          rv$x <- c(rv$x, 
                    values.to.pixel(
                      rv$KM_TimePoints[as.numeric(rv$points_times_groups[(length(rv$x) + 1)])], 
                      as.numeric(rv$x[1]), as.numeric(rv$x[2]), 
                      as.numeric(rv$x_min), as.numeric(rv$x_max)
                    )
          )
          rv$y <- c(rv$y,input$Plot_Click$y)
        } else {
          rv$x <- c(rv$x,input$Plot_Click$x)
          rv$y <- c(rv$y,input$Plot_Click$y)
        } 
      } else if (rv$plot_number >=6){
        if (length(rv$x) < 1) {
          rv$x <- c(rv$x,input$Plot_Click$x)
          rv$y <- c(rv$y,input$Plot_Click$y)
        } else if (length(rv$x) == 1) {
          rv$x <- c(rv$x,input$Plot_Click$x)
          rv$y <- c(rv$y,rv$y)
        } else if (length(rv$x) == 2) {
          rv$x <- c(rv$x,input$Plot_Click$x)
          rv$y <- c(rv$y,input$Plot_Click$y)
        } else if (length(rv$x) == 3) {
          rv$x <- c(rv$x,rv$x[3])
          rv$y <- c(rv$y,input$Plot_Click$y)
        } else {
          rv$x <- c(rv$x, 
                    values.to.pixel(
                      rv$KM_TimePoints[as.numeric(rv$points_times_groups[(length(rv$x) + 1)])], 
                      as.numeric(rv$x[1]), as.numeric(rv$x[2]), 
                      as.numeric(rv$x_min), as.numeric(rv$x_max)
                    )
          )
          rv$y <- c(rv$y,input$Plot_Click$y)
        }
      } else {
        if (length(rv$x) < 1) {
          rv$x <- c(rv$x,input$Plot_Click$x)
          rv$y <- c(rv$y,input$Plot_Click$y)
        } else if (length(rv$x) == 1) {
          rv$x <- c(rv$x,rv$x)
          rv$y <- c(rv$y,input$Plot_Click$y)
        } else if (rv$lines_required[length(rv$x)+1] == "Yes") {
          rv$x <- c(rv$x,input$Plot_Click$x)
          rv$y <- c(rv$y,input$Plot_Click$y)
        } else {
          rv$x <- c(rv$x, 
                    rv$x[match(rv$points_times_groups[(length(rv$x)+1)],
                               rv$points_times_groups[1:length(rv$x)]
                    )]
          )
          rv$y <- c(rv$y,input$Plot_Click$y)
        }
      }
      if (rv$plot_number <=2){
        if (length(rv$x) <= (rv$points_max-2)){
          rv$points_values <- c(NA, NA, NA,
                                (((rv$y[4:length(rv$y)] - rv$y[1])/(rv$y[3]-rv$y[1]))*
                                   (as.numeric(rv$y_max) - as.numeric(rv$y_min))) + as.numeric(rv$y_min)
          ) 
        } else if (length(rv$x) == (rv$points_max-1)){
          rv$points_values <- c(NA, NA, NA,
                                (((rv$y[4:(length(rv$y)-1)] - rv$y[1])/(rv$y[3]-rv$y[1]))*
                                   (as.numeric(rv$y_max) - as.numeric(rv$y_min))) + as.numeric(rv$y_min),
                                (((rv$x[length(rv$x)] - rv$x[1])/(rv$x[2]-rv$x[1]))*
                                   (as.numeric(rv$x_max) - as.numeric(rv$x_min))) + as.numeric(rv$x_min)
          )                      
        } else {
          rv$points_values <- c(NA, NA, NA,
                                (((rv$y[4:(length(rv$y)-2)] - rv$y[1])/(rv$y[3]-rv$y[1]))*
                                   (as.numeric(rv$y_max) - as.numeric(rv$y_min))) + as.numeric(rv$y_min),
                                (((rv$x[(length(rv$x)-1):length(rv$x)] - rv$x[1])/(rv$x[2]-rv$x[1]))*
                                   (as.numeric(rv$x_max) - as.numeric(rv$x_min))) + as.numeric(rv$x_min)
          )                      
        }
      } else if (rv$plot_number >=6){
        if (length(rv$x) > 4) {
          rv$points_values <- c(NA, NA, NA, NA,
                                (((rv$y[5:length(rv$y)] - rv$y[3])/(rv$y[4]-rv$y[3]))*
                                   (as.numeric(rv$y_max) - as.numeric(rv$y_min))) + as.numeric(rv$y_min)
          )
        } else {
          rv$points_values <- rep(NA, length(rv$x))
        }
      } else {
        if (length(rv$x) > 2) {
          rv$points_values <- c(NA, NA,
                                (((rv$y[3:length(rv$y)] - rv$y[1])/(rv$y[2]-rv$y[1]))*
                                   (as.numeric(rv$y_max) - as.numeric(rv$y_min))) + as.numeric(rv$y_min)
          )
        } else {
          rv$points_values <- rep(NA, length(rv$x))
        }
      }
      output$PlotExtract_DownloadModifiedPlot_UI <- renderUI(
        downloadButton("PlotExtract_DownloadModifiedPlot", HTML("Download modified plot"))
      )
      output$PlotExtract_UploadedPlot <- renderPlot({
        plot({
          par(mar=c(0, 0, 0, 0))
          xlim = c(0, rv$x_pixels)
          ylim = c(0, rv$y_pixels)
          rv$UploadedPlot
        })
        for (i in 1:length(rv$x)) {
          points(rv$x[i],rv$y[i], 
                 type = "p", 
                 pch = rv$points_symbol[i], 
                 col = rv$points_colours[i],
                 cex = 1.5
          )
          if (i > 2) {
            if (rv$lines_required[i] == "Yes") {
              abline(v=rv$x[i], lty = 3, col = "grey")
            }
          } 
        }
        if (length(rv$x) > 1){
          lines(x = rv$x[1:2], y =rv$y[1:2], lty = 1, lwd = 3, col="maroon")
          if ((rv$plot_number <=2) | (rv$plot_number >=6)){
            for (i in 1:length(rv$KM_TimePoints)){
              abline(v=values.to.pixel(
                as.numeric(rv$KM_TimePoints[i]), 
                as.numeric(rv$x[1]), as.numeric(rv$x[2]), 
                as.numeric(rv$x_min), as.numeric(rv$x_max)
              ), lty = 3, col = "grey")
            }        
          }
        }
        if ((rv$plot_number <=2) & (length(rv$x)>2)){
          lines(x = rv$x[c(1,3)], y =rv$y[c(1,3)], lty = 1, lwd = 3, col="maroon")
        }
        if ((rv$plot_number >=6) & (length(rv$x)>3)){
          lines(x = rv$x[3:4], y =rv$y[3:4], lty = 1, lwd = 3, col="maroon")
        }
      }, width = 750,
      height = 750)
      if (rv$plot_number <=2){
        if (length(rv$x) == (rv$points_max-2) | length(rv$x) == (rv$points_max-1)){
          output$PlotExtract_Skip_MinMax_UI<- renderUI(
            actionButton("PlotExtract_Skip_MinMax", "Skip: min/max follow-up")
          )
        } else {
          output$PlotExtract_Skip_MinMax_UI<- NULL
          output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
          output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
          output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
          output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
          output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
          output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
          output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
          output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
          output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
          output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
          output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
          output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
          output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
          output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
          output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
          output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
          output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
          output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
          output$PlotExtract_DownloadResults_UI <- NULL
        }
      }
      if (length(rv$x) < rv$points_max) {
        output$PlotExtract_DisplayNextStep <- renderUI(
          HTML('<h3 style = "font-size:24px; color:purple;"><b>Next step</b></h3>',
               'Click on the <b>',
               '<span style = "color:darkblue; background-color:yellow;">',
               rv$points_names[(length(rv$x) + 1)],
               '</b></span>'
          )
        )
        output$PlotExtract_Confirm_DataPoints_UI <- NULL
      } else {
        output$PlotExtract_DisplayNextStep <- renderUI(
          HTML('<h3 style = "font-size:24px; color:purple;"><b>Next step</b></h3>',
               '<p style = "color:darkblue;background-color:yellow;"><b>You have entered all the data points.</b><br> 
                 <i>Please confirm the data points by clicking on "Confirm data points".</i><br> 
                 Otherwise, change the data points by clicking on <i>"Remove the last data point from this plot"</i> or 
                 <i>"Remove all data points selected in this plot to revise the data points."</i></p>')
        )
        output$PlotExtract_Confirm_DataPoints_UI <- renderUI(
          actionButton("PlotExtract_Confirm_DataPoints", "Confirm data points")
        )
      }
    } else {
      output$PlotExtract_DisplayNextStep <- renderUI(
        HTML('<h3 style = "font-size:24px; color:purple;"><b>Next step</b></h3>',
             '<p style = "color: red;background-color:yellow;">
          You have reached the maximum number of clicks for this plot based on the information provided.
           If you want to change the last point, please click on "Remove the last point in the plot" and click again.
           </p>
               ')
      )
    }
  })
  # Confirm data points
  observeEvent(input$PlotExtract_Confirm_DataPoints,{
    eval(parse(text= PlotClick_No))
    output$PlotExtract_PlotRotate_UI<- NULL
    output$PlotExtract_DisplayNextStep<- NULL
    output$PlotExtract_DisplaySelection<- NULL
    output$PlotExtract_SelectionMessage<- NULL
    output$PlotExtract_ResetPlot_UI<- NULL
    output$PlotExtract_Remove_Last_UI<- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    if (rv$plot_number > 2) {
      output$PlotExtract_DownloadResults_UI <- renderUI(
        downloadButton("PlotExtract_DownloadResults", "Download datapoint values")
      )
      if ((rv$plot_number >=3)  & (rv$plot_number <=5)) {
        rv$PlotExtract_FinalResults <- cbind(
          data.point=rv$points_names[3:length(rv$points_names)],
          values = rv$points_values[3:length(rv$points_values)]
        )
      } else {
        rv$PlotExtract_FinalResults <- cbind(
          data.point=rv$points_names[5:length(rv$points_names)],
          values = rv$points_values[5:length(rv$points_values)]
        )
      }
    } else {
      output$PlotExtract_KM_Min_Max_Question_2_UI <- renderUI(
        HTML(paste0('<p style = "color: darkgreen; background-color:yellow;">
                        Information successfully uploaded.Please enter the number of participants in each group...'  
        ))
      )
      eval(parse(text =
                   create.numeric.inputs.groups(input$PlotExtract_Groups)
      ))
      output$PlotExtract_KM_Submit_Group_Numbers_UI<- renderUI(
        actionButton("PlotExtract_KM_Submit_Group_Numbers", "Submit the group numbers")
      )
    }
  })
  # Skip minimum/maximum follow-up
  observeEvent(input$PlotExtract_Skip_MinMax,{
    output$PlotExtract_PlotRotate_UI<- NULL
    output$PlotExtract_DisplayNextStep<- NULL
    output$PlotExtract_DisplaySelection<- NULL
    output$PlotExtract_SelectionMessage<- NULL
    output$PlotExtract_ResetPlot_UI<- NULL
    output$PlotExtract_Remove_Last_UI<- NULL
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI <- NULL
    eval(parse(text= PlotClick_No))
    output$PlotExtract_KM_Min_Max_Question_1_UI <- renderUI(
      selectInput("PlotExtract_KM_Min_Max_Question_1", 
                  "Select the unit for time",
                  choices = c("",KM_Min_Max_Question_1_Choice),
                  selected = "")
    )
    rv$KM_Calculations_Step1 <- NULL
    rv$KM_Calculations_Step2 <- NULL
    rv$PlotExtract_FinalResults <- NULL
  })
  # KM Question 1
  observeEvent(input$PlotExtract_KM_Min_Max_Question_1,{
    if (input$PlotExtract_KM_Min_Max_Question_1 != "") {
      output$PlotExtract_KM_Min_Max_Question_1_UI <- renderUI(
        HTML(paste0('<b>Units for time in KM curve:</b> ', input$PlotExtract_KM_Min_Max_Question_1))
      )
      output$PlotExtract_KM_Min_Max_Question_2_UI <- renderUI(
        selectInput("PlotExtract_KM_Min_Max_Question_2", 
                    HTML('Select which of the following information you have.<b> 
                      <i>If you have information on multiple rows, 
                      choose the <b>first row</b> for which you have the information.</i>'),
                    choices = c("",KM_Min_Max_Question_2_Choice),
                    selected = "")
      )
      output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- renderUI(
        actionButton("PlotExtract_KM_Min_Max_Reset_Questions", "Change: follow-up answer(s)")
      )
    }
  })
  # KM Question 2
  observeEvent(input$PlotExtract_KM_Min_Max_Question_2,{
    if (input$PlotExtract_KM_Min_Max_Question_2 != "") {
      output$PlotExtract_KM_Min_Max_Question_2_UI <- renderUI(
        HTML(paste0('<b>Information available:</b> ', input$PlotExtract_KM_Min_Max_Question_2))
      )
      eval(parse(text =
                   KM_Min_Max_Questions_3_5[
                     match(
                       input$PlotExtract_KM_Min_Max_Question_2,
                       KM_Min_Max_Question_2_Choice 
                     )
                   ]
      ))
      output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- renderUI(
        actionButton("PlotExtract_KM_Min_Max_Submit_Questions", "Submit: follow-up answers")
      )
    }
  })
  # KM Questions Reset
  observeEvent(input$PlotExtract_KM_Min_Max_Reset_Questions,{
    output$PlotExtract_KM_Min_Max_Question_1_UI <- renderUI(
      selectInput("PlotExtract_KM_Min_Max_Question_1", 
                  "Select the unit for time",
                  choices = c("",KM_Min_Max_Question_1_Choice),
                  selected = "")
    )
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
  })
  # KM Questions submit
  observeEvent(input$PlotExtract_KM_Min_Max_Submit_Questions,{
    rv$group_numbers <- NULL
    if (match(input$PlotExtract_KM_Min_Max_Question_2,KM_Min_Max_Question_2_Choice) <=2) {
      if((!is.na(input$PlotExtract_KM_Min_Max_Question_3)) & (!is.na(input$PlotExtract_KM_Min_Max_Question_4))) {
        output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
        output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
        output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
        output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
        output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
        
        output$PlotExtract_KM_Min_Max_Question_2_UI <- renderUI(
          HTML(paste0('<b>Information available:</b> ', input$PlotExtract_KM_Min_Max_Question_2,
                      '<p style = "color: darkgreen; background-color:yellow;">
                        Information successfully uploaded.'  
          ))
        )
        eval(parse(text =
                     create.numeric.inputs.groups(input$PlotExtract_Groups)
        ))
        output$PlotExtract_KM_Submit_Group_Numbers_UI<- renderUI(
          actionButton("PlotExtract_KM_Submit_Group_Numbers", "Submit the group numbers")
        )
        if (match(input$PlotExtract_KM_Min_Max_Question_2,KM_Min_Max_Question_2_Choice) == 1){
          rv$points_values <- c(rv$points_values,input$PlotExtract_KM_Min_Max_Question_3, input$PlotExtract_KM_Min_Max_Question_4)
        } else if (match(input$PlotExtract_KM_Min_Max_Question_2,KM_Min_Max_Question_2_Choice) == 2){
          rv$points_values <- c(rv$points_values,
                                max(0,(input$PlotExtract_KM_Min_Max_Question_3 - 0.5*input$PlotExtract_KM_Min_Max_Question_4)),
                                (input$PlotExtract_KM_Min_Max_Question_3 + 0.5*input$PlotExtract_KM_Min_Max_Question_4)
          )
        }
      } else {
        output$PlotExtract_KM_Min_Max_Question_2_UI <- renderUI(
          HTML(       '<p style = "color: red; background-color:yellow;">
                        The information is not complete. Please complete the information or change your answers to the questions.</p>')
          
        )
      }
    } else if (match(input$PlotExtract_KM_Min_Max_Question_2,KM_Min_Max_Question_2_Choice) <= 4) {
      if(
        (input$PlotExtract_KM_Min_Max_Question_3 != input$PlotExtract_KM_Min_Max_Question_4) & 
        (input$PlotExtract_KM_Min_Max_Question_3 != input$PlotExtract_KM_Min_Max_Question_5) & 
        (input$PlotExtract_KM_Min_Max_Question_4 != input$PlotExtract_KM_Min_Max_Question_5)
      ) {
        output$PlotExtract_KM_Min_Max_Question_2_UI <- renderUI(
          HTML(paste0('<b>Information available:</b> ', input$PlotExtract_KM_Min_Max_Question_2,
                      '<p style = "color: darkgreen; background-color:yellow;">
                        Information successfully uploaded. Please enter the number of participants in each group...'  
          ))
        )
        output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
        output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
        output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
        output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
        output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
        
        eval(parse(text =
                     create.numeric.inputs.groups(input$PlotExtract_Groups)
        ))
        output$PlotExtract_KM_Submit_Group_Numbers_UI<- renderUI(
          actionButton("PlotExtract_KM_Submit_Group_Numbers", "Submit the group numbers")
        )
        if (match(input$PlotExtract_KM_Min_Max_Question_2,KM_Min_Max_Question_2_Choice) == 3){
          rv$points_values <- c(rv$points_values,
                                KM_min_max_analysis.date(
                                  c(input$PlotExtract_KM_Min_Max_Question_3,
                                    input$PlotExtract_KM_Min_Max_Question_4,
                                    input$PlotExtract_KM_Min_Max_Question_5
                                  ),
                                  input$PlotExtract_KM_Min_Max_Question_1
                                )
          )
        } else if (match(input$PlotExtract_KM_Min_Max_Question_2,KM_Min_Max_Question_2_Choice) == 4){
          rv$points_values <- c(rv$points_values,
                                KM_min_max_submission.date(
                                  c(input$PlotExtract_KM_Min_Max_Question_3,
                                    input$PlotExtract_KM_Min_Max_Question_4,
                                    input$PlotExtract_KM_Min_Max_Question_5
                                  ),
                                  input$PlotExtract_KM_Min_Max_Question_1
                                )
          )
        }
      } else {
        output$PlotExtract_KM_Min_Max_Question_2_UI <- renderUI(
          HTML('<p style = "color: red; background-color:yellow;">
                        Please check the information. Two or more dates are the same, which is not possible.</p>')
        )
      }
    } else {
      output$PlotExtract_KM_Min_Max_Question_2_UI <- renderUI(
        HTML(paste0('<b>Information available:</b> ', input$PlotExtract_KM_Min_Max_Question_2,
                    '<p style = "color: darkgreen; background-color:yellow;">
                        Information successfully uploaded.Please enter the number of participants in each group...'  
        ))
      )
      rv$points_values <- c(rv$points_values, 0, max(rv$KM_TimePoints))
      output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
      output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
      output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
      output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
      
      eval(parse(text =
                   create.numeric.inputs.groups(input$PlotExtract_Groups)
      ))
      output$PlotExtract_KM_Submit_Group_Numbers_UI<- renderUI(
        actionButton("PlotExtract_KM_Submit_Group_Numbers", "Submit the group numbers")
      )
    }
  })
  # KM Group numbers submit
  observeEvent(input$PlotExtract_KM_Submit_Group_Numbers,{
    j <- TRUE
    for (i in 1:input$PlotExtract_Groups) {
      if (is.na(eval(parse(text =
                           paste0('input$PlotExtract_KM_Group_Numbers_', i)
      )))) {
        j <- FALSE
      }
    }
    if (j == TRUE){
      eval(parse(text=
                   remove.numeric.inputs.groups(input$PlotExtract_Groups)
      ))
      output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
      rv$group_numbers <- vector()
      for (i in 1:input$PlotExtract_Groups) {
        rv$group_numbers <- c(rv$group_numbers, 
                              eval(parse(text =
                                           paste0('input$PlotExtract_KM_Group_Numbers_', i)
                              ))
        )
      }
      rv$KM_Calculations_Step1 <- KM_Table(
        rv$points_values, input$PlotExtract_Groups, rv$KM_TimePoints, percent = (rv$plot_number == 1)
      )
      rv$KM_Calculations_Step2 <- KM_lnHR(
        rv$KM_Calculations_Step1$KM_DataTable,
        rv$KM_Calculations_Step1$KM_TimePoints,
        rv$KM_Calculations_Step1$min.follow_up,
        rv$KM_Calculations_Step1$max.follow_up,
        rv$group_numbers
      )
      rv$PlotExtract_FinalResults <- cbind.missing(
        list(
          groups = 1:length(rv$group_numbers),
          ln.hr = c(sapply(rv$KM_Calculations_Step2, `[[`, 2)),
          se.ln.hr = c(sapply(rv$KM_Calculations_Step2, `[[`, 3)),
          reference = paste0("Group ", length(rv$group_numbers)),
          min.follow_up = rv$KM_Calculations_Step1$min.follow_up,
          max.follow_up = rv$KM_Calculations_Step1$max.follow_up,
          group_numbers = rv$group_numbers,
          KM_TimePoints = rv$KM_Calculations_Step1$KM_TimePoints,
          rv$KM_Calculations_Step1$KM_DataTable
        )
      )
      output$PlotExtract_KM_Min_Max_Question_2_UI<- renderUI(
        HTML(
          '<h3 style = "color:darkgreen;background-color:yellow;"><i>You can download the results by clicking on the "Download results" button below.</i></h3>'
        )
      )
      output$PlotExtract_DownloadResults_UI <- renderUI(
        downloadButton("PlotExtract_DownloadResults", "Download the results")
      )
      output$htmlMsg1_PlotExtract <- NULL
      output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    } else {
      output$PlotExtract_KM_Min_Max_Question_2_UI <- renderUI(
        HTML(paste0('<p style = "color: red; background-color:yellow;">
                        One or more groups have missing information on the group numbers.Please enter the number of participants in each group to proceed...'  
        ))
      )
    }
  })
  # Reset plot
  observeEvent(input$PlotExtract_ResetPlot,{
    rv$UploadedPlot <- image_border(
      image_trim(
        image_read(
          input$PlotExtract_UploadPlot$datapath
        )
      ), color = "darkblue",geometry = "1x1"
    )
    eval(parse(text= PlotClick_Yes))
    output$PlotExtract_DisplayNextStep <- renderUI(
      HTML('<h3 style = "font-size:24px; color:purple;"><b>Next step</b></h3>',
           'Click on the <b>',
           '<span style = "color:darkblue; background-color:yellow;">',
           rv$points_names[(length(rv$x) + 1)],
           '</b></span>'
      )
    )
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    output$PlotExtract_Skip_MinMax_UI<- NULL
    output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
    output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
    output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
    output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
    output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
    output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
    output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
    output$PlotExtract_DownloadResults_UI <- NULL
    rv$x <- NULL
    rv$y <- NULL
  })
  # Remove last point
  observeEvent(input$PlotExtract_Remove_Last,{
    if (!is.null(rv$x)) {
      if (length(rv$x) > 1) {
        rv$x <- rv$x[1:(length(rv$x)-1)]
        rv$y <- rv$y[1:(length(rv$y)-1)]
      } else {
        rv$x <- NULL
        rv$y <- NULL
      }
    }
    eval(parse(text= PlotClick_Yes))
    output$PlotExtract_DisplayNextStep <- renderUI(
      HTML('<h3 style = "font-size:24px; color:purple;"><b>Next step</b></h3>',
           'Click on the <b>',
           '<span style = "color:darkblue; background-color:yellow;">',
           rv$points_names[(length(rv$x) + 1)],
           '</b></span>'
      )
    )
    output$PlotExtract_Confirm_DataPoints_UI <- NULL
    if (rv$plot_number <=2){
      if (length(rv$x) == (rv$points_max-2) | length(rv$x) == (rv$points_max-1)){
        output$PlotExtract_Skip_MinMax_UI<- renderUI(
          actionButton("PlotExtract_Skip_MinMax", "Skip: min/max follow-up")
        )
      } else {
        output$PlotExtract_Skip_MinMax_UI<- NULL
        output$PlotExtract_KM_Min_Max_Question_1_UI <- NULL
        output$PlotExtract_KM_Min_Max_Question_2_UI <- NULL
        output$PlotExtract_KM_Min_Max_Question_3_UI <- NULL
        output$PlotExtract_KM_Min_Max_Question_4_UI <- NULL
        output$PlotExtract_KM_Min_Max_Question_5_UI <- NULL
        output$PlotExtract_KM_Min_Max_Reset_Questions_UI <- NULL
        output$PlotExtract_KM_Min_Max_Submit_Questions_UI <- NULL
        output$PlotExtract_KM_Group_Numbers_1_UI<- NULL
        output$PlotExtract_KM_Group_Numbers_2_UI<- NULL
        output$PlotExtract_KM_Group_Numbers_3_UI<- NULL
        output$PlotExtract_KM_Group_Numbers_4_UI<- NULL
        output$PlotExtract_KM_Group_Numbers_5_UI<- NULL
        output$PlotExtract_KM_Group_Numbers_6_UI<- NULL
        output$PlotExtract_KM_Group_Numbers_7_UI<- NULL
        output$PlotExtract_KM_Group_Numbers_8_UI<- NULL
        output$PlotExtract_KM_Group_Numbers_9_UI<- NULL
        output$PlotExtract_KM_Group_Numbers_10_UI<- NULL
        output$PlotExtract_KM_Submit_Group_Numbers_UI<- NULL
        output$PlotExtract_DownloadResults_UI <- NULL
      }
    }
    output$PlotExtract_UploadedPlot <- renderPlot({
      plot({
        par(mar=c(0, 0, 0, 0))
        xlim = c(0, rv$x_pixels)
        ylim = c(0, rv$y_pixels)
        rv$UploadedPlot
      })
      for (i in 1:length(rv$x)) {
        points(rv$x[i],rv$y[i], 
               type = "p", 
               pch = rv$points_symbol[i], 
               col = rv$points_colours[i],
               cex = 1.5
        )
        if (i > 2) {
          if (rv$lines_required[i] == "Yes") {
            abline(v=rv$x[i], lty = 3, col = "grey")
          }
        } 
      }
      if (length(rv$x) > 1){
        lines(x = rv$x[1:2], y =rv$y[1:2], lty = 1, lwd = 3, col="maroon")
        if ((rv$plot_number <=2) | (rv$plot_number >=6)){
          for (i in 1:length(rv$KM_TimePoints)){
            abline(v=values.to.pixel(
              as.numeric(rv$KM_TimePoints[i]), 
              as.numeric(rv$x[1]), as.numeric(rv$x[2]), 
              as.numeric(rv$x_min), as.numeric(rv$x_max)
            ), lty = 3, col = "grey")
          }        
        }
      }
      if ((rv$plot_number <=2) & (length(rv$x)>2)){
        lines(x = rv$x[c(1,3)], y =rv$y[c(1,3)], lty = 1, lwd = 3, col="maroon")
      }
      if ((rv$plot_number >=6) & (length(rv$x)>3)){
        lines(x = rv$x[3:4], y =rv$y[3:4], lty = 1, lwd = 3, col="maroon")
      }
    }, width = 750,
    height = 750)
  })
  # Plot rotate
  observeEvent(input$PlotExtract_PlotRotate,{
    rv$UploadedPlot <- image_rotate(rv$UploadedPlot,270)
  })
  # Outputs
  output$error <- renderTable(rv$points_names)
  output$PlotExtract_DownloadModifiedPlot <- downloadHandler( 
    filename = "Modified plot.png", 
    content = function(file) {
      png(file)
      plot({
        par(mar=c(0, 0, 0, 0))
        xlim = c(0, rv$x_pixels)
        ylim = c(0, rv$y_pixels)
        rv$UploadedPlot
      })
      for (i in 1:length(rv$x)) {
        points(rv$x[i],rv$y[i], 
               type = "p", 
               pch = rv$points_symbol[i], 
               col = rv$points_colours[i],
               cex = 1.5
        )
        if (i > 2) {
          if (rv$lines_required[i] == "Yes") {
            abline(v=rv$x[i], lty = 3, col = "grey")
          }
        } 
      }
      if (length(rv$x) > 1){
        lines(x = rv$x[1:2], y =rv$y[1:2], lty = 1, lwd = 3, col="maroon")
        if ((rv$plot_number <=2) | (rv$plot_number >=6)){
          for (i in 1:length(rv$KM_TimePoints)){
            abline(v=values.to.pixel(
              as.numeric(rv$KM_TimePoints[i]), 
              as.numeric(rv$x[1]), as.numeric(rv$x[2]), 
              as.numeric(rv$x_min), as.numeric(rv$x_max)
            ), lty = 3, col = "grey")
          }        
        }
      }
      if ((rv$plot_number <=2) & (length(rv$x)>2)){
        lines(x = rv$x[c(1,3)], y =rv$y[c(1,3)], lty = 1, lwd = 3, col="maroon")
      }
      if ((rv$plot_number >=6) & (length(rv$x)>3)){
        lines(x = rv$x[3:4], y =rv$y[3:4], lty = 1, lwd = 3, col="maroon")
      }
      dev.off()
    } 
  )
  output$PlotExtract_DownloadResults <- downloadHandler( 
    filename = "Data points values.csv",
    content = function(file) {
      write.csv(
        rv$PlotExtract_FinalResults,
        file, 
        row.names = FALSE, na="")
    } 
  )

  # Process data (Intervention review) events ####
  observeEvent(input$Process_Int, {
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[8]))
    panelchoice <- "panel10"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[c(1:2,10)], 
                       selected = FirstSelection[10])
    output$htmlMsg1_Process_Int <- NULL
    output$Header_Process_Int <- NULL
  })
  observeEvent(input$skip_instructions_Process_Int, {
    output$htmlInstructions1_Process_Int <- NULL
    output$htmlInstructions2_Process_Int <- renderUI(HTML(Instructions_Process_Int_1))
    output$skip_instructions_Process_Int_UI <- NULL
  })
  
  # Interpretation (Intervention review) events ####
  observeEvent(input$Interpret_Int, {
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[8]))
    panelchoice <- "panel11"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[c(1:2,11)], 
                       selected = FirstSelection[11])
    output$htmlMsg1_Interpret_Int <- NULL
    output$Header_Interpret_Int <- NULL
  })
  observeEvent(input$skip_instructions_Interpret_Int, {
    output$htmlInstructions1_Interpret_Int <- NULL
    output$htmlInstructions2_Interpret_Int <- renderUI(HTML(Instructions_Interpret_Int_1))
    output$skip_instructions_Interpret_Int_UI <- NULL
  })
  
  # Meta-analysis (Intervention review) ####
  observeEvent(input$MA_Int, {
    rv$ResetData = "Reset"
    # The activity selector choice should be only 1:3 and the choice should move to 3
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[3]))
    panelchoice = "panel3"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[1:3], selected = FirstSelection[3])
  })
  
  observeEvent(input$skip_instructions_Int, {
    rv$ResetData = "Reset"
    # The activity selector choice should be only 1:4 and the choice should move to 4
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[4]))
    panelchoice = "panel4"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[1:4], selected = FirstSelection[4])
  })
  
  observeEvent(input$DataUpload_instructions_page_Int, {
    rv$ResetData = "Reset"
    # The activity selector choice should be only 1:4 and the choice should move to 4
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[4]))
    panelchoice = "panel4"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[1:4], selected = FirstSelection[4])
  })
  
  observeEvent(rv$ResetData, {
    if (rv$ResetData == "Reset") {
      # Remove all user interfaces in the pages
      output$htmlMsg1_Int <- NULL
      output$htmlMsg2_Int <- NULL
      output$htmlUpload_MetaAnalysisPlan_Int_Error_Warning <- NULL
      output$htmlMA_Modify_Msg <- NULL
      
      output$Header_Upload_Data_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>Upload Data</b></h3>'))
      output$Upload_Data_Int_UI <- renderUI(
        fileInput("Upload_Data_Int", "Please upload the data file (Accepted format: txt, csv)",
                  width = "60%",
                  multiple = FALSE,
                  accept = c(".txt",".csv")
        ),
      )
      output$Header_MetaAnalysisPlan_Choice_Int_UI <- NULL
      output$MetaAnalysisPlan_Choice_Int_UI <- NULL
      output$Header_Upload_MetaAnalysisPlan_Int_UI <- NULL
      output$Upload_MetaAnalysisPlan_Int_UI <- NULL
      output$MA_Outcome_UI <- NULL
      output$MA_EffectMeasure_UI <- NULL
      output$MA_ContinuityCorrection_UI <- NULL
      output$MA_RareEventsMethod_UI <- NULL
      output$MA_FixedEffect_UI <- NULL
      output$MA_PredictionInterval_UI <- NULL
      output$MA_HKAdjustment_UI <- NULL
      output$MA_Method_UI <- NULL
      output$MA_Summary_UI <- NULL
      output$MA_Minimum_Studies_UI <- NULL
      output$MA_Metabias_Any_UI <- NULL
      output$MA_Metabias_Heterogeneity_UI <- NULL
      output$MA_IMOR1_UI <- NULL
      output$MA_IMOR2_UI <- NULL
      output$MA_SubgroupSelection_UI <- NULL
      output$Reset_MA_UI <- NULL
      output$Modify_MA_Row_UI <- NULL
      output$Modify_MA_RowsOfSimilarType_UI <- NULL
      output$ModifyOneMoreMA_Row_UI <- NULL
      output$Run_MetaAnalysisPlan_UI <- NULL
      output$Reset_MetaAnalysisPlan_Int_UI <- NULL
      output$Header_SelectedMetaAnalysisPlan_Int_UI <- NULL
      output$Download_SelectedMetaAnalysisPlan_Int_UI <- NULL
      output$SelectedMetaAnalysisPlan_Int_UI <- NULL
      output$Header_DefaultMetaAnalysisPlan_Int_UI <- NULL
      output$Download_DefaultMetaAnalysisPlan_Int_UI <- NULL
      output$DefaultMetaAnalysisPlan_Int_UI <- NULL
      output$Header_RevManMetaAnalysisPlan_Int_UI <- NULL
      output$Download_RevManMetaAnalysisPlan_Int_UI <- NULL
      output$RevManMetaAnalysisPlan_Int_UI <- NULL
      output$Reset_MetaAnalysisPlan_Int_UI_2 <- NULL
      output$Header_ResultsTable_Int_UI <- NULL
      output$OutcomeSummary_Int_UI <- NULL
      output$ResultsTableDownload_Int_UI <- NULL
      output$ResultsTable_Int_UI <- NULL
      output$AllPlots_Download_Int_UI <- NULL
      
      # Return Variables to NULL
      rv$InputData <- NULL
      rv$outcome.summary_Int <- NULL
      rv$df_Outcome <- NULL
      rv$MA <- NULL
      rv$MetaBias <- NULL
      rv$SA <- NULL
      rv$MetaReg <- NULL
      rv$Subgroup_1 <- NULL
      rv$Subgroup_2 <- NULL
      rv$Subgroup_3 <- NULL
      rv$Subgroup_4 <- NULL
      rv$Subgroup_5 <- NULL
      rv$Subgroup_6 <- NULL
      rv$Subgroup_7 <- NULL
      rv$Subgroup_8 <- NULL
      rv$Subgroup_9 <- NULL
      rv$Subgroup_10 <- NULL
      rv$Metabias.Min <- NULL
      rv$SelectedCovariates <- NULL
      rv$SelectedCovariatesColumns <- NULL
      rv$SelectedCovariatesColumnsSubgroup <- NULL
      rv$MetaRegText <- NULL
      rv$OldColumnNames <- NULL
      rv$NewColumnNames <- NULL
      rv$DefaultMetaAnalysisPlan_Int <- NULL
      rv$RevManMetaAnalysisPlan_Int <- NULL
      rv$UploadedMetaAnalysisPlan_Int <- NULL
      rv$EffectMeasure <- NULL
      rv$Analysis <- NULL
      rv$UploadPlanCheck <- NULL
      rv$ResetData <- NULL
      rv$ResetPlan <- NULL
      rv$ModifyPlan <- NULL
      rv$RunAnalysis <- NULL
      rv$AcceptModification <- NULL
      rv$RowsForModification <- NULL
      rv$OutcomeRow <- NULL
      rv$plot1 <- NULL
      rv$plot2 <- NULL
      rv$plot3 <- NULL
      rv$plotSA1 <- NULL
      rv$plotSA2 <- NULL
      rv$plotSA3 <- NULL
      rv$plotSubA1 <- NULL
      rv$plotSubA2 <- NULL
      rv$plotSubA3 <- NULL
      rv$plotSubA4 <- NULL
      rv$plotSubA5 <- NULL
      rv$plotSubA6 <- NULL
      rv$plotSubA7 <- NULL
      rv$plotSubA8 <- NULL
      rv$plotSubA9 <- NULL
      rv$plotSubA10 <- NULL
    }
  })
  
  observeEvent(rv$ResetPlan, {
    if (rv$ResetPlan == "Reset") {
      # Similar to the full reset except the status just after data upload should be restored      
      # User interfaces in the pages
      output$htmlUpload_MetaAnalysisPlan_Int_Error_Warning <- NULL
      output$htmlMA_Modify_Msg <- NULL
      
      output$Header_Upload_Data_Int_UI <- NULL
      output$Upload_Data_Int_UI <- NULL
      output$Header_MetaAnalysisPlan_Choice_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>Meta-analysis plan (intervention review)</b></h3>'))
      output$MetaAnalysisPlan_Choice_Int_UI <- renderUI(
        radioButtons("MetaAnalysisPlan_Choice_Int", 
                     "Please select from one of the following options.", 
                     choices = MetaAnalysisPlanChoice_Int,
                     width = "100%",
                     inline = FALSE,
                     selected = character(0)
        )
      )
      output$Header_Upload_MetaAnalysisPlan_Int_UI <- NULL
      output$Upload_MetaAnalysisPlan_Int_UI <- NULL
      output$MA_Outcome_UI <- NULL
      output$MA_EffectMeasure_UI <- NULL
      output$MA_ContinuityCorrection_UI <- NULL
      output$MA_RareEventsMethod_UI <- NULL
      output$MA_FixedEffect_UI <- NULL
      output$MA_PredictionInterval_UI <- NULL
      output$MA_HKAdjustment_UI <- NULL
      output$MA_Method_UI <- NULL
      output$MA_Summary_UI <- NULL
      output$MA_Minimum_Studies_UI <- NULL
      output$MA_Metabias_Any_UI <- NULL
      output$MA_Metabias_Heterogeneity_UI <- NULL
      output$MA_IMOR1_UI <- NULL
      output$MA_IMOR2_UI <- NULL
      output$MA_SubgroupSelection_UI <- NULL
      output$Reset_MA_UI <- NULL
      output$Modify_MA_Row_UI <- NULL
      output$Modify_MA_RowsOfSimilarType_UI <- NULL
      output$ModifyOneMoreMA_Row_UI <- NULL
      output$Run_MetaAnalysisPlan_UI <- NULL
      output$Reset_MetaAnalysisPlan_Int_UI <- NULL
      output$Header_SelectedMetaAnalysisPlan_Int_UI <- NULL
      output$Download_SelectedMetaAnalysisPlan_Int_UI <- NULL
      output$SelectedMetaAnalysisPlan_Int_UI <- NULL
      output$Reset_MetaAnalysisPlan_Int_UI_2 <- NULL
      output$Header_ResultsTable_Int_UI <- NULL
      output$OutcomeSummary_Int_UI <- NULL
      output$ResultsTableDownload_Int_UI <- NULL
      output$ResultsTable_Int_UI <- NULL
      output$AllPlots_Download_Int_UI <- NULL
      
      # Return some Variables to NULL
      rv$MA <- NULL
      rv$MetaBias <- NULL
      rv$SA <- NULL
      rv$MetaReg <- NULL
      rv$Subgroup_1 <- NULL
      rv$Subgroup_2 <- NULL
      rv$Subgroup_3 <- NULL
      rv$Subgroup_4 <- NULL
      rv$Subgroup_5 <- NULL
      rv$Subgroup_6 <- NULL
      rv$Subgroup_7 <- NULL
      rv$Subgroup_8 <- NULL
      rv$Subgroup_9 <- NULL
      rv$Subgroup_10 <- NULL
      rv$Metabias.Min <- NULL
      rv$SelectedCovariates <- NULL
      rv$SelectedCovariatesColumns <- NULL
      rv$SelectedCovariatesColumnsSubgroup <- NULL
      rv$EffectMeasure <- NULL
      rv$Analysis <- NULL
      rv$UploadPlanCheck <- NULL
      rv$ResetData <- NULL
      rv$ResetPlan <- NULL
      rv$ModifyPlan <- NULL
      rv$RunAnalysis <- NULL
      rv$AcceptModification <- NULL
      rv$RowsForModification <- NULL
      rv$OutcomeRow <- NULL
      rv$plot1 <- NULL
      rv$plot2 <- NULL
      rv$plot3 <- NULL
      rv$plotSA1 <- NULL
      rv$plotSA2 <- NULL
      rv$plotSA3 <- NULL
      rv$plotSubA1 <- NULL
      rv$plotSubA2 <- NULL
      rv$plotSubA3 <- NULL
      rv$plotSubA4 <- NULL
      rv$plotSubA5 <- NULL
      rv$plotSubA6 <- NULL
      rv$plotSubA7 <- NULL
      rv$plotSubA8 <- NULL
      rv$plotSubA9 <- NULL
      rv$plotSubA10 <- NULL
      
      # The activity selector choice should be only 1:4 and the choice should move to 4
      output$htmlTitle <- renderUI(HTML(MainHeaderSelection[4]))
      panelchoice = "panel4"
      updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
      updateRadioButtons(inputId = "Activity", choices = FirstSelection[1:4], selected = FirstSelection[4])
    }
  })
  
  observeEvent(input$UploadData_Int, {
    rv$ResetData = "Reset"
    # The activity selector choice should be only 1:4 and the choice should move to 4
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[4]))
    panelchoice = "panel4"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[1:4], selected = FirstSelection[4])
  })
  
  observeEvent(input$Upload_Data_Int, {
    # Check if the file is txt, csv and import it
    # if the extension is not txt or csv do nothing more than a warning
    if ((!is.na(input$Upload_Data_Int$name)) & (input$Upload_Data_Int$name !="")){
      if (! any(c(file_ext(input$Upload_Data_Int$datapath)=="txt",file_ext(input$Upload_Data_Int$datapath)=="csv"))){
        output$htmlMsg1_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>Please upload
             a csv file or tab delimited file</b></h2>')
        )
        # If the file is empty, just say that it is empty
      } else if (file.size(input$Upload_Data_Int$datapath)<8){
        output$htmlMsg1_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>Please upload a file that contains data</b></h2>')
        )
      } else {
        # To avoid change in column names, use check.names=FALSE
        if (file_ext(input$Upload_Data_Int$datapath)=="txt"){
          rv$InputData <-read.delim(input$Upload_Data_Int$datapath,header=TRUE, stringsAsFactors=FALSE, sep = '\t', check.names=FALSE)        
        } else if (file_ext(input$Upload_Data_Int$datapath)=="csv"){
          rv$InputData <-read.csv(input$Upload_Data_Int$datapath, header=TRUE, stringsAsFactors=FALSE, sep = ',', check.names=FALSE)
        }
        # Now check whether column names of the InputData match
        if (all(c(ncol(rv$InputData) > 27,!FALSE %in% (colnames(rv$InputData)[1:28] == colnames(SampleData_Int)[1:28])))) {
          # Replace "" and " " with NA
          rv$InputData[rv$InputData == ""] <- NA
          rv$InputData[rv$InputData == " "] <- NA
          if(!FALSE %in% (!is.na(match(rv$InputData[!is.na(rv$InputData[,2]),2], SampleData_Int[!is.na(SampleData_Int[,2]),2])))) {
            # Now check whether the third columns has anything other than the list of choices for third column
            if(!FALSE %in% (!is.na(match(rv$InputData[!is.na(rv$InputData[,3]),3], SampleData_Int[!is.na(SampleData_Int[,3]),3])))) {
              # Now check whether the first four rows of 28th column are empty
              if(!TRUE %in% (is.na(rv$InputData[1:4,28]))) {
                withProgress(message = 'Data upload', value = 0, {
                  # Turn off the upload data interface
                  output$Header_Upload_Data_Int_UI <- NULL
                  output$Upload_Data_Int_UI <- NULL
                  output$htmlMsg1_Int <- renderUI(
                    HTML('<h2 style="color:darkgreen; background-color:yellow">
                  <b><i>Completed data upload: now preparing data for analysis</i></b>
                       </h2>')
                  )
                  incProgress(1/10, detail = 'Completed data upload: now preparing data for analysis')
                  # Prepare the data for analysis
                  # The outcome, outcome type, better or worse, and units need to be specified only for the first time
                  # However, this is required for each row to allow analysis
                  for (i in 1:nrow(rv$InputData)){
                    rv$InputData[i,1] <- ifelse(is.na(rv$InputData[i,1]),rv$InputData[i-1,1],rv$InputData[i,1])
                    rv$InputData[i,2] <- ifelse(is.na(rv$InputData[i,2]),rv$InputData[i-1,2],rv$InputData[i,2])
                    rv$InputData[i,3] <- ifelse(is.na(rv$InputData[i,3]),rv$InputData[i-1,3],rv$InputData[i,3])
                    # Units are applicable for continuous outcome only, but even that may not have units always; therefore the formula is different for units
                    rv$InputData[i,11] <- ifelse(rv$InputData[i,2] != "Continuous",NA,ifelse(!is.na(rv$InputData[i,11]),rv$InputData[i,11],ifelse(rv$InputData[i,1] != rv$InputData[i-1,1],NA, ifelse(!is.na(rv$InputData[i-1,11]),rv$InputData[i-1,11],NA))))
                  }
                  
                  # Ensure that certain fields are factors and others are numeric
                  rv$InputData[,c(1:4,11:12,20,27:28)]<- lapply(rv$InputData[,c(1:4,11:12,20,27:28)],factor)
                  rv$InputData[,c(5:10,13:19,21:26)]<- lapply(rv$InputData[,c(5:10,13:19,21:26)],as.numeric)
                  
                  # The subgroups need to be based on the type of data provided
                  if (ncol(rv$InputData) > 28) {
                    for (j in 29:ncol(rv$InputData)) {
                      if (is.character(rv$InputData[,j])){
                        rv$InputData[is.na(rv$InputData[,j]),j] <- "Not stated"
                        rv$InputData[,j] <- factor(rv$InputData[,j])
                      }
                    }
                  } else {
                    rv$InputData[,29] <- rep("Not stated",nrow(rv$InputData))
                    colnames(rv$InputData)[29] <- "Subgroup1"
                  }
                  
                  # For regression, spaces or unacceptable characters in field names need to be replaced as it results in errors
                  # Not possible to include in quotes either
                  # Therefore the column names have to replaced
                  # First store the old column names to revert back
                  rv$OldColumnNames <- colnames(rv$InputData)
                  colnames(rv$InputData)[29:ncol(rv$InputData)] <- make.names(colnames(rv$InputData)[29:ncol(rv$InputData)],unique=TRUE)
                  # To make the regression output easier to interpret, add some text to end of variable names
                  if (ncol(rv$InputData) >29){
                    colnames(rv$InputData)[29:ncol(rv$InputData)] <- paste0(colnames(rv$InputData)[29:ncol(rv$InputData)],ifelse(sapply(rv$InputData[,29:ncol(rv$InputData)],is.numeric),'_per.unit.increase','_Level_'))
                  } else {
                    colnames(rv$InputData)[29] <- paste0(colnames(rv$InputData)[29],ifelse(is.numeric(rv$InputData[,29]),'_per.unit.increase','_Level_'))
                  }
                  # Store this to change when the analysis is performed
                  rv$NewColumnNames <- colnames(rv$InputData)
                  # Revert back to old names
                  colnames(rv$InputData) <- rv$OldColumnNames
                  
                  # Now create a file to store details of the outcome
                  rv$outcome.summary_Int <- rv$InputData[,c(1:3,11)]
                  rv$outcome.summary_Int <- unique(rv$outcome.summary_Int)
                  rv$outcome.summary_Int$Studies <- rep(NA,nrow(rv$outcome.summary_Int))
                  rv$outcome.summary_Int$Participants <- rep(NA,nrow(rv$outcome.summary_Int))
                  rv$outcome.summary_Int$EffectMeasure <- rep(NA,nrow(rv$outcome.summary_Int))
                  rv$outcome.summary_Int[,1:4] <- sapply(rv$outcome.summary_Int[,1:4],as.character)
                  
                  # Create files for meta-analysis
                  for (i in 1:nrow(rv$outcome.summary_Int)){
                    # One file per outcome
                    rv$df_Outcome[[i]] <- rv$InputData[rv$InputData[,1] == rv$outcome.summary_Int[i,1],]
                    # drop the rows if some details are missing. This depends upon the type of outcome
                    if (tolower(rv$outcome.summary_Int[i,2]) == "binary") {
                      # For binary outcome, if any of 4,5,6,7,8  are missing drop the row
                      if (nrow(rv$df_Outcome[[i]]) > 1) {
                        rv$df_Outcome[[i]] <- rv$df_Outcome[[i]][rowSums(sapply(rv$df_Outcome[[i]][,4:8],is.na) == TRUE) == 0,]
                      } else {
                        if (TRUE %in% (sapply(rv$df_Outcome[[i]][,4:8],is.na) == TRUE)) {
                          rv$df_Outcome[[i]] <- rv$df_Outcome[[i]][-1,]
                        }
                      }
                      rv$outcome.summary_Int[i,7] <- "OR"
                    } else if (tolower(rv$outcome.summary_Int[i,2]) == "continuous"){
                      # Some imputations can be performed for missing standard deviations- so, no need to drop them
                      # For continuous outcome, if any of 4,5,6,7,9 are missing drop the row
                      if (nrow(rv$df_Outcome[[i]]) > 1) {
                        rv$df_Outcome[[i]] <- rv$df_Outcome[[i]][rowSums(sapply(rv$df_Outcome[[i]][,c(4:7,9)],is.na) == TRUE) == 0,]
                      } else {
                        if (TRUE %in% (sapply(rv$df_Outcome[[i]][,c(4:7,9)],is.na) == TRUE)) {
                          rv$df_Outcome[[i]] <- rv$df_Outcome[[i]][-1,]
                        }
                      }
                      # if the SD is missing (even after imputation), it should be marked in column 13
                      rv$df_Outcome[[i]][,13] <- ifelse(is.na(rv$df_Outcome[[i]][,8])|is.na(rv$df_Outcome[[i]][,10]),2,rv$df_Outcome[[i]][,13])
                      # impute the SD from max SD
                      rv$df_Outcome[[i]][,8] <- ifelse(is.na(rv$df_Outcome[[i]][,8]),max(rv$df_Outcome[[i]][,8], na.rm = TRUE),rv$df_Outcome[[i]][,8])
                      rv$df_Outcome[[i]][,10] <- ifelse(is.na(rv$df_Outcome[[i]][,10]),max(rv$df_Outcome[[i]][,10], na.rm = TRUE),rv$df_Outcome[[i]][,10])
                      # Imputation in column 13
                      rv$df_Outcome[[i]][,13] <- as.character(rv$df_Outcome[[i]][,13])
                      rv$df_Outcome[[i]][,13] <- ifelse(!is.na(rv$df_Outcome[[i]][,13]),"Mean or Standard deviation imputed",NA)
                      rv$df_Outcome[[i]][,13] <- as.factor(rv$df_Outcome[[i]][,13])
                      # Scales (in column 12)
                      rv$df_Outcome[[i]][,12] <- as.factor(rv$df_Outcome[[i]][,12])
                      rv$outcome.summary_Int[i,7] <- ifelse(length(unique(rv$df_Outcome[[i]][,12]))>1,"SMD","MD")
                    } else {
                      # For count and time outcomes and summary measures if 4,7 or 8 are missing drop the row
                      if (nrow(rv$df_Outcome[[i]]) > 1) {
                        rv$df_Outcome[[i]] <- rv$df_Outcome[[i]][rowSums(sapply(rv$df_Outcome[[i]][,c(4,7:8)],is.na) == TRUE) == 0,]
                      } else {
                        if (TRUE %in% (sapply(rv$df_Outcome[[i]][,c(4,7:8)],is.na) == TRUE)) {
                          rv$df_Outcome[[i]] <- rv$df_Outcome[[i]][-1,]
                        }
                      }
                      rv$outcome.summary_Int[i,7] <- ifelse(tolower(rv$outcome.summary_Int[i,2]) == "count","RR",
                                                            ifelse(tolower(rv$outcome.summary_Int[i,2]) == "time","HR",
                                                                   ifelse(tolower(rv$outcome.summary_Int[i,2]) == "summary_difference","SMD","OR"
                                                                   )))
                    }
                    # Convert factors to character and then back to factor to allow further analysis
                    rv$df_Outcome[[i]][,sapply(rv$df_Outcome[[i]],is.factor)] <- lapply(rv$df_Outcome[[i]][,sapply(rv$df_Outcome[[i]],is.factor)],as.character)
                    rv$df_Outcome[[i]][,sapply(rv$df_Outcome[[i]],is.character)] <- lapply(rv$df_Outcome[[i]][,sapply(rv$df_Outcome[[i]],is.character)],factor)
                    
                    # Now calculate the number of trials and number of participants
                    rv$outcome.summary_Int[i,5] <- nrow(rv$df_Outcome[[i]])
                    rv$outcome.summary_Int[i,6] <- sum(rv$df_Outcome[[i]][,5:6],na.rm=TRUE)
                    
                    # For all outcomes change the column names so that metareg can be performed
                    colnames(rv$df_Outcome[[i]]) <- rv$NewColumnNames
                    
                  }
                  output$htmlMsg1_Int <- renderUI(
                    HTML('<h2 style="color:darkgreen; background-color:yellow">
                  <b><i>Meta-analysis plan based on defaults created. Modify the plan as necessary before you run the analysis</i></b>
                       </h2>')
                  )
                  
                  # Now for the code to generate
                  # First outcome names that run without error
                  rv$OutcomeNamesForCodes <- make.names(rv$outcome.summary_Int[,1], unique=TRUE)
                  # Make sure that we start with a clean state if new data is uploaded
                  rv$GenerateCode <- GenerateCode
                  # Now create the file for analysis
                  for (i in 1:nrow(rv$outcome.summary_Int)) {
                    # Now column names names that run without error
                    rv$ColumnNamesForCodes <- make.names(colnames(rv$df_Outcome[[i]]),unique=TRUE)
                    # Now some alteration in data for subgroups
                    for (j in 29:ncol(rv$InputData)) {
                      if (! is.numeric(rv$InputData[,j])){
                        rv$df_Outcome[[i]][is.na(rv$df_Outcome[[i]][,j]),j] <- "Not stated"
                      }
                    }
                    
                    # Next generate the different columns
                    for (j in 1:ncol(rv$df_Outcome[[i]])) {
                      if (is.numeric(rv$df_Outcome[[i]][,j])){
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0(rv$ColumnNamesForCodes[j], ' <- c(', paste0(rv$df_Outcome[[i]][,j],collapse = ", "),')')
                        )
                      } else {
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 str_replace_all(
                                                   paste0(rv$ColumnNamesForCodes[j], ' <- c(', paste0('"',rv$df_Outcome[[i]][,j],'"',collapse = ", "),')'),
                                                   '"NA"',
                                                   'NA'
                                                 )
                        )
                      }
                    }
                    
                    # Now to combine them into a single file
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0(rv$OutcomeNamesForCodes[i], ' <- as.data.frame(cbind(', paste0(rv$ColumnNamesForCodes,collapse = ", "),'))')
                    )
                    
                    # Now convert them to numeric and factors
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0(rv$OutcomeNamesForCodes[i], '[,c(1:4,11:13,20,27:28)]<- lapply(', rv$OutcomeNamesForCodes[i], '[,c(1:4,11:13,20,27:28)],factor)'),
                                             paste0(rv$OutcomeNamesForCodes[i], '[,c(5:10,14:19,21:26)]<- lapply(', rv$OutcomeNamesForCodes[i], '[,c(5:10,14:19,21:26)],as.numeric)')
                    )
                    # The subgroups need to be based on the type of data provided
                    for (j in 29:ncol(rv$InputData)) {
                      if (! is.numeric(rv$InputData[,j])){
                        rv$GenerateCode <- rbind(rv$GenerateCode,
                                                 paste0(rv$OutcomeNamesForCodes[i], '[,',j,'] <- factor(', rv$OutcomeNamesForCodes[i],'[,',j,'])')
                        )
                      } else {
                        rv$GenerateCode <- rbind(rv$GenerateCode,
                                                 paste0(rv$OutcomeNamesForCodes[i], '[,',j,'] <- as.numeric(', rv$OutcomeNamesForCodes[i],'[,',j,'])')
                        )
                      }
                    }
                  }
                  
                  incProgress(9/10, detail = 'Data preparation completed: creating the meta-analysis plan based on defaults')
                  
                  # Now create a meta-analysis plan
                  rv$DefaultMetaAnalysisPlan_Int <- data.frame(cbind(rv$outcome.summary_Int[,c(1,7)],
                                                                     rep(NA,nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)),
                                                                     rep("Yes",nrow(rv$outcome.summary_Int)),rep("Yes",nrow(rv$outcome.summary_Int)),
                                                                     rep("Yes",nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)),
                                                                     rep("Yes",nrow(rv$outcome.summary_Int)),rep(10,nrow(rv$outcome.summary_Int)),
                                                                     rep(NA,nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)),
                                                                     rep(NA,nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)),
                                                                     rep(NA,nrow(rv$outcome.summary_Int))
                  ))
                  rv$RevManMetaAnalysisPlan_Int <- data.frame(cbind(rv$outcome.summary_Int[,c(1,7)],
                                                                    rep(NA,nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)),
                                                                    rep("Yes",nrow(rv$outcome.summary_Int)),rep("No",nrow(rv$outcome.summary_Int)),
                                                                    rep("No",nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)),
                                                                    rep("Yes",nrow(rv$outcome.summary_Int)),rep(10,nrow(rv$outcome.summary_Int)),
                                                                    rep(NA,nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)),
                                                                    rep(NA,nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)),
                                                                    rep(NA,nrow(rv$outcome.summary_Int))
                  ))
                  colnames(rv$DefaultMetaAnalysisPlan_Int) <- c("Outcome", "Effect measure", 
                                                                "Rare events (continuity correction)", "Rare events (method)", 
                                                                "Fixed-effect", "Prediction interval", 
                                                                "Hartung and Knapp adjustment", "Meta-analysis method",
                                                                "Main meta-analysis summary", "Minimum studies for tests for funnel plot asymmetry",
                                                                "Meta-bias method (Any)", "Meta-bias method (Heterogeneity)",
                                                                "Information Missingness Odds Ratio (IMOR) (Intervention)", "Information Missingness Odds Ratio (IMOR) (Control)",
                                                                "Moderator variables to be included"
                  )
                  colnames(rv$RevManMetaAnalysisPlan_Int) <- colnames(rv$DefaultMetaAnalysisPlan_Int)
                  
                  # Go through each outcome and create a default plan
                  for (i in 1:nrow(rv$outcome.summary_Int)) {
                    rv$DefaultMetaAnalysisPlan_Int[i,15] <- ifelse(ncol(rv$InputData) >28,rep(paste0(colnames(rv$InputData)[29:ncol(rv$InputData)],collapse = ", "),nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)))
                    rv$RevManMetaAnalysisPlan_Int[i,15] <- ifelse(ncol(rv$InputData) >28,rep(paste0(colnames(rv$InputData)[29:ncol(rv$InputData)],collapse = ", "),nrow(rv$outcome.summary_Int)),rep(NA,nrow(rv$outcome.summary_Int)))
                    if (tolower(rv$outcome.summary_Int[i,2]) == "binary") {
                      rv$DefaultMetaAnalysisPlan_Int[i,3] <- "Continuity correction with 0.5 for events and no events"
                      rv$DefaultMetaAnalysisPlan_Int[i,4] <- "Generalised Linear Mixed Model (only for odds ratios)"
                      rv$DefaultMetaAnalysisPlan_Int[i,8] <- "MH"
                      rv$DefaultMetaAnalysisPlan_Int[i,11] <- "Harbord"
                      rv$DefaultMetaAnalysisPlan_Int[i,12] <- "ASD_Thompson"
                      rv$DefaultMetaAnalysisPlan_Int[i,13] <- ifelse(rv$outcome.summary_Int[i,3]== "Worse",2,0.5)
                      rv$DefaultMetaAnalysisPlan_Int[i,14] <- ifelse(rv$outcome.summary_Int[i,3]== "Worse",2,0.5)
                      rv$RevManMetaAnalysisPlan_Int[i,3] <- "Continuity correction with 0.5 for events and no events"
                      rv$RevManMetaAnalysisPlan_Int[i,4] <- "Peto odds ratio (odds ratio and fixed-effect model only)"
                      rv$RevManMetaAnalysisPlan_Int[i,8] <- "MH"
                      rv$RevManMetaAnalysisPlan_Int[i,11] <- "Harbord"
                      rv$RevManMetaAnalysisPlan_Int[i,12] <- "ASD_Thompson"
                      rv$RevManMetaAnalysisPlan_Int[i,13] <- 1
                      rv$RevManMetaAnalysisPlan_Int[i,14] <- 1
                    } else if (tolower(rv$outcome.summary_Int[i,2]) == "continuous"){
                      if (rv$DefaultMetaAnalysisPlan_Int[i,2] == "SMD") {
                        rv$DefaultMetaAnalysisPlan_Int[i,8] <- "Hedges_TRUE"
                      }
                      rv$DefaultMetaAnalysisPlan_Int[i,11] <- "Egger"
                      if (rv$RevManMetaAnalysisPlan_Int[i,2] == "SMD") {
                        rv$RevManMetaAnalysisPlan_Int[i,8] <- "Hedges_FALSE"
                      }
                      rv$RevManMetaAnalysisPlan_Int[i,11] <- "Egger"
                    } else {
                      rv$DefaultMetaAnalysisPlan_Int[i,11] <- "Egger"
                      rv$RevManMetaAnalysisPlan_Int[i,11] <- "Egger"
                    }
                  }
                  
                  # It should be possible to upload new data from this stage
                  output$UploadData_Int_UI <- renderUI(
                    actionButton("UploadData_Int","Upload New Data (intervention review)")
                  )
                  
                  # Now the choices for the plan and the plans should appear
                  output$Header_MetaAnalysisPlan_Choice_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>Meta-analysis plan (intervention review)</b></h3>'))
                  output$MetaAnalysisPlan_Choice_Int_UI <- renderUI(
                    radioButtons("MetaAnalysisPlan_Choice_Int", 
                                 "Please select from one of the following options.", 
                                 choices = MetaAnalysisPlanChoice_Int,
                                 width = "100%",
                                 inline = FALSE,
                                 selected = character(0)
                    )
                  )
                  
                  # Meta-analysis plan page
                  output$Header_DefaultMetaAnalysisPlan_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>Default meta-analysis plan (intervention review)</b></h3>'))
                  output$Download_DefaultMetaAnalysisPlan_Int_UI <- renderUI(downloadButton("default.ma.plan_Int", HTML("Download default meta-analysis plan (intervention review)")))
                  output$DefaultMetaAnalysisPlan_Int_UI <- renderUI(
                    tableOutput("DefaultMetaAnalysisPlan_Int")
                  )
                  output$Header_RevManMetaAnalysisPlan_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>RevMan meta-analysis plan (intervention review)</b></h3>'))
                  output$Download_RevManMetaAnalysisPlan_Int_UI <- renderUI(downloadButton("revman.ma.plan_Int", HTML("Download RevMan meta-analysis plan (intervention review)")))
                  output$RevManMetaAnalysisPlan_Int_UI <- renderUI(
                    tableOutput("RevManMetaAnalysisPlan_Int")
                  )
                  output$htmlMsg1_Int <- renderUI(
                    HTML('<h2 style="color:darkgreen; background-color:yellow">
                  <b>Data upload: complete<br>
                  Meta-analysis plan: not based on external uploads<br>
                  <i>Modify the plan as necessary before you run the analysis.</i></b>
                       </h2>')
                  )
                  incProgress(10/10, detail = 'Data upload: complete; Meta-analysis plan: not based on external uploads; Modify the plan as necessary before you run the analysis.')
                })  
              } else {
                output$htmlMsg1_Int <- renderUI(
                  HTML(paste0('<h2 style="color:red; background-color:yellow"><b>Please upload a file that is prepared as per the instructions: </b><br>
                 <i>The first four entries of the 28th column should have some names for intervention and control.</i>',
                              '</h2>'))
                )  
              }
            } else {
              output$htmlMsg1_Int <- renderUI(
                HTML(paste0('<h2 style="color:red; background-color:yellow"><b>Please upload a file that is prepared as per the instructions: </b><br>
                 <i>The third column should have only one of the following choices:<br>
                          "Worse", "Better".</i>',
                            '</h2>'))
              )  
            }
          } else {
            output$htmlMsg1_Int <- renderUI(
              HTML(paste0('<h2 style="color:red; background-color:yellow"><b>Please upload a file that is prepared as per the instructions: </b>
                 The second column should have only one of the following outcome types:<br>
                        "Binary", "Count", "Continuous", "Time", "Summary_Ratio", "Summary_Difference".</i>',
                          '</h2>'))
            )  
          }
        } else {
          output$htmlMsg1_Int <- renderUI(
            HTML('<h2 style="color:red; background-color:yellow"><b>Please upload a file that is prepared as per the instructions:</b><br>
               <i>The headings of the first 28 columns do not match the headings in the template.</i></h2>')
          )
        }
      }
    }
  })
  
  observeEvent(input$MetaAnalysisPlan_Choice_Int, {
    # Option to change radiobutton should disappear
    output$Header_MetaAnalysisPlan_Choice_Int_UI <- NULL
    output$MetaAnalysisPlan_Choice_Int_UI <- NULL
    
    if (input$MetaAnalysisPlan_Choice_Int == "I want to use the default plan for meta-analysis of interventions (available below)" |
        input$MetaAnalysisPlan_Choice_Int ==  "I want to use the RevMan plan for meta-analysis of interventions (available below)") {
      if (input$MetaAnalysisPlan_Choice_Int == "I want to use the default plan for meta-analysis of interventions (available below)") {
        rv$UploadedMetaAnalysisPlan_Int <- rv$DefaultMetaAnalysisPlan_Int
      } else {
        rv$UploadedMetaAnalysisPlan_Int <- rv$RevManMetaAnalysisPlan_Int
      }
      output$Upload_MetaAnalysisPlan_Int_UI <- NULL
      rv$UploadPlanCheck <- NULL
      rv$ModifyPlan = "No"
      rv$RunAnalysis = "Run"
      rv$ResetData = "No"
      rv$ResetPlan = "No"
      rv$AcceptModification = "No"
      rv$RowsForModification <- NULL
      
      # From this stage, run analysis and resetting the meta-analysis plan should be available
      output$Run_MetaAnalysisPlan_UI <- renderUI(
        actionButton("Run_MetaAnalysisPlan", "Run the current meta-analysis plan")          
      )
      output$Reset_MetaAnalysisPlan_Int_UI <- renderUI(
        actionButton("Reset_MetaAnalysisPlan_Int", "Change option for meta-analysis plan (intervention review)")          
      )
      
    } else if (input$MetaAnalysisPlan_Choice_Int == "I want to use my own meta-analysis plan that I have prepared previously for intervention reviews using this programme without any modifications" |
               input$MetaAnalysisPlan_Choice_Int == "I want to use my own meta-analysis plan that I have prepared previously for intervention reviews using this programme after modifying it") {
      
      output$Header_Upload_MetaAnalysisPlan_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>Upload meta-analysis plan (intervention review)</b></h3>'))
      output$Upload_MetaAnalysisPlan_Int_UI <- renderUI(
        fileInput("Upload_MA_Plan_Int", "Please upload the intervention review meta-analysis plan file (Accepted format: txt, csv)",
                  width = "60%",
                  multiple = FALSE,
                  accept = c(".txt",".csv")
        ),
      )
      rv$UploadPlanCheck <- NULL
      rv$ModifyPlan = "No"
      rv$RunAnalysis = "No"
      rv$ResetData = "No"
      rv$ResetPlan = "No"
      rv$AcceptModification = "No"
      rv$RowsForModification <- NULL
      
      # From this stage, Reset plan analysis should be available
      output$Reset_MetaAnalysisPlan_Int_UI <- renderUI(
        actionButton("Reset_MetaAnalysisPlan_Int", "Change option for meta-analysis plan (intervention review)")          
      )
    } else if (input$MetaAnalysisPlan_Choice_Int == "I want to modify the default plan (available below for intervention reviews) and use the modified plan in the future if necessary" |
               input$MetaAnalysisPlan_Choice_Int == "I want to modify the RevMan plan (available below for intervention reviews) and use the modified plan in the future if necessary") {
      
      if (input$MetaAnalysisPlan_Choice_Int == "I want to modify the default plan (available below for intervention reviews) and use the modified plan in the future if necessary") {
        rv$UploadedMetaAnalysisPlan_Int <- rv$DefaultMetaAnalysisPlan_Int
      } else {
        rv$UploadedMetaAnalysisPlan_Int <- rv$RevManMetaAnalysisPlan_Int
      }
      
      output$Upload_MetaAnalysisPlan_Int_UI <- NULL
      rv$UploadPlanCheck <- NULL
      rv$ModifyPlan = "Modify"
      rv$RunAnalysis = "No"
      rv$ResetData = "No"
      rv$ResetPlan = "No"
      rv$AcceptModification = "No"
      rv$RowsForModification <- NULL
      
      output$Header_SelectedMetaAnalysisPlan_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>Current meta-analysis plan (intervention review)</b></h3>'))
      output$Download_SelectedMetaAnalysisPlan_Int_UI <- renderUI(downloadButton("Selected.ma.plan_Int", HTML("Download selected meta-analysis plan (intervention review)")))
      output$SelectedMetaAnalysisPlan_Int_UI <- renderUI(
        tableOutput("SelectedMetaAnalysisPlan_Int")
      )
      
      # From this stage, run analysis and resetting the meta-analysis plan should be available
      output$Run_MetaAnalysisPlan_UI <- renderUI(
        actionButton("Run_MetaAnalysisPlan", "Run the current meta-analysis plan")          
      )
      output$Reset_MetaAnalysisPlan_Int_UI <- renderUI(
        actionButton("Reset_MetaAnalysisPlan_Int", "Change option for meta-analysis plan (intervention review)")          
      )
    }
  })
  
  observeEvent(input$Upload_MA_Plan_Int, {
    # Check if the file is txt, csv and import it
    # if the extension is not txt or csv do nothing more than a warning
    if ((!is.na(input$Upload_MA_Plan_Int$name)) & (input$Upload_MA_Plan_Int$name !="")){
      if (! any(c(file_ext(input$Upload_MA_Plan_Int$datapath)=="txt",file_ext(input$Upload_MA_Plan_Int$datapath)=="csv"))){
        output$htmlMsg1_Int <- renderUI(
          HTML('<h2 style="color:darkgreen; background-color:yellow"><b>Data upload: complete</h2><br>
        <h2 style="color:darkgreen; background-color:yellow"><b>Please upload
             a csv file or tab delimited file</b></h2><br><h2 style="color:red; background-color:yellow"><b>Please upload
             a csv file or tab delimited file</b></h2>')
        )
        # If the file is empty, just say that it is empty
        
      } else if (file.size(input$Upload_MA_Plan_Int$datapath)<8){
        output$htmlMsg1_Int <- renderUI(
          HTML('<h2 style="color:darkgreen; background-color:yellow"><b>Data upload: complete</h2>
             <br><h2 style="color:red; background-color:yellow"><b>Please upload a file that contains data</b></h2>')
        )
      } else {
        # To avoid change in column names, use check.names=FALSE
        if (file_ext(input$Upload_MA_Plan_Int$datapath)=="txt"){
          rv$UploadedMetaAnalysisPlan_Int <-read.delim(input$Upload_MA_Plan_Int$datapath,header=TRUE, stringsAsFactors=FALSE, sep = '\t', check.names=FALSE)        
        } else if (file_ext(input$Upload_MA_Plan_Int$datapath)=="csv"){
          rv$UploadedMetaAnalysisPlan_Int <-read.csv(input$Upload_MA_Plan_Int$datapath, header=TRUE, stringsAsFactors=FALSE, sep = ',', check.names=FALSE)
        }
        if (all(c(ncol(rv$UploadedMetaAnalysisPlan_Int) == 15,!FALSE %in% (colnames(rv$UploadedMetaAnalysisPlan_Int) == colnames(SampleMetaAnalysisPlan_Int))))) {
          # Replace "" and " " with NA
          rv$UploadedMetaAnalysisPlan_Int[rv$UploadedMetaAnalysisPlan_Int == ""] <- NA
          rv$UploadedMetaAnalysisPlan_Int[rv$UploadedMetaAnalysisPlan_Int == " "] <- NA
          rv$UploadPlanCheck <- rv$DefaultMetaAnalysisPlan_Int
          rv$UploadPlanCheck[,2:15] <- NA
          # Now check each column and confirm that there are no unexpected values in the columns
          # Ensure that the outcomes are in the same order as outcome summary
          if(!FALSE %in% (rv$outcome.summary_Int[,1] == rv$UploadedMetaAnalysisPlan_Int[,1])) {
            # Now go through each row and ensure that the values are appropriate for outcometype
            for (i in 1:nrow(rv$outcome.summary_Int)) {
              if(tolower(rv$outcome.summary_Int[i,2]) == "binary") {
                rv$UploadPlanCheck[i,2] <- rv$UploadedMetaAnalysisPlan_Int[i,2] %in% EffectMeasure_Binary_Choice_Converter
                rv$UploadPlanCheck[i,3] <- rv$UploadedMetaAnalysisPlan_Int[i,3] %in% RareEvents_Correction_Choice
                rv$UploadPlanCheck[i,4] <- rv$UploadedMetaAnalysisPlan_Int[i,4] %in% RareEvents_Method_Choice
                rv$UploadPlanCheck[i,5] <- rv$UploadedMetaAnalysisPlan_Int[i,5] %in% FixedEffect_Choice
                rv$UploadPlanCheck[i,6] <- rv$UploadedMetaAnalysisPlan_Int[i,6] %in% PredictionInterval_Choice
                rv$UploadPlanCheck[i,7] <- rv$UploadedMetaAnalysisPlan_Int[i,7] %in% HKAdjustment_Choice
                rv$UploadPlanCheck[i,8] <- rv$UploadedMetaAnalysisPlan_Int[i,8] %in% MA_Method_Binary_Choice_Converter
                rv$UploadPlanCheck[i,9] <- rv$UploadedMetaAnalysisPlan_Int[i,9] %in% c("Yes","No")
                rv$UploadPlanCheck[i,10] <- all(c(is.numeric(rv$UploadedMetaAnalysisPlan_Int[i,10]),rv$UploadedMetaAnalysisPlan_Int[i,10]>3,rv$UploadedMetaAnalysisPlan_Int[i,10]<=20))
                rv$UploadPlanCheck[i,11] <- rv$UploadedMetaAnalysisPlan_Int[i,11] %in% Metabias_Any_Choice
                rv$UploadPlanCheck[i,12] <- rv$UploadedMetaAnalysisPlan_Int[i,12] %in% Metabias_Heterogeneity_Choice_Converter
                rv$UploadPlanCheck[i,13] <- all(c(is.numeric(rv$UploadedMetaAnalysisPlan_Int[i,13]),rv$UploadedMetaAnalysisPlan_Int[i,13]>0.01,rv$UploadedMetaAnalysisPlan_Int[i,13]<100))
                rv$UploadPlanCheck[i,14] <- all(c(is.numeric(rv$UploadedMetaAnalysisPlan_Int[i,14]),rv$UploadedMetaAnalysisPlan_Int[i,14]>0.01,rv$UploadedMetaAnalysisPlan_Int[i,14]<100))
                rv$UploadPlanCheck[i,15] <- any(c(is.na(rv$UploadedMetaAnalysisPlan_Int[i, 15]), 
                                                  !TRUE %in% is.na(match(strsplit(rv$UploadedMetaAnalysisPlan_Int[i, 15],", ")[[1]],
                                                                         rv$OldColumnNames))))
              } else if (tolower(rv$outcome.summary_Int[i,2]) == "continuous") {
                rv$UploadPlanCheck[i,2] <- rv$UploadedMetaAnalysisPlan_Int[i,2] %in% EffectMeasure_Continuous_Choice_Converter
                rv$UploadPlanCheck[i,3] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 3])
                rv$UploadPlanCheck[i,4] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 4])
                rv$UploadPlanCheck[i,5] <- rv$UploadedMetaAnalysisPlan_Int[i,5] %in% FixedEffect_Choice
                rv$UploadPlanCheck[i,6] <- rv$UploadedMetaAnalysisPlan_Int[i,6] %in% PredictionInterval_Choice
                rv$UploadPlanCheck[i,7] <- rv$UploadedMetaAnalysisPlan_Int[i,7] %in% HKAdjustment_Choice
                rv$UploadPlanCheck[i,8] <- ifelse(rv$UploadedMetaAnalysisPlan_Int[i,2] != "SMD", is.na(rv$UploadedMetaAnalysisPlan_Int[i,8]),rv$UploadedMetaAnalysisPlan_Int[i,8] %in% MA_Method_SMD_Choice_Converter)
                rv$UploadPlanCheck[i,9] <- rv$UploadedMetaAnalysisPlan_Int[i,9] %in% c("Yes","No")
                rv$UploadPlanCheck[i,10] <- all(c(is.numeric(rv$UploadedMetaAnalysisPlan_Int[i,10]),rv$UploadedMetaAnalysisPlan_Int[i,10]>3,rv$UploadedMetaAnalysisPlan_Int[i,10]<=20))
                rv$UploadPlanCheck[i,11] <- rv$UploadedMetaAnalysisPlan_Int[i,11] %in% Metabias_Any_Choice[1:3]
                rv$UploadPlanCheck[i,12] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 12])
                rv$UploadPlanCheck[i,13] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 13])
                rv$UploadPlanCheck[i,14] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 14])
                rv$UploadPlanCheck[i,15] <- any(c(is.na(rv$UploadedMetaAnalysisPlan_Int[i, 15]), 
                                                  !TRUE %in% is.na(match(strsplit(rv$UploadedMetaAnalysisPlan_Int[i, 15],", ")[[1]],
                                                                         rv$OldColumnNames))))
              } else if (tolower(rv$outcome.summary_Int[i,2]) == "count") {
                rv$UploadPlanCheck[i,2] <- rv$UploadedMetaAnalysisPlan_Int[i,2] %in% EffectMeasure_Count_Choice_Converter
                rv$UploadPlanCheck[i,2] <- rv$UploadedMetaAnalysisPlan_Int[i,2] %in% c(EffectMeasure_Binary_Choice_Converter, EffectMeasure_Continuous_Choice_Converter, "HR")
                rv$UploadPlanCheck[i,3] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 3])
                rv$UploadPlanCheck[i,4] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 4])
                rv$UploadPlanCheck[i,5] <- rv$UploadedMetaAnalysisPlan_Int[i,5] %in% FixedEffect_Choice
                rv$UploadPlanCheck[i,6] <- rv$UploadedMetaAnalysisPlan_Int[i,6] %in% PredictionInterval_Choice
                rv$UploadPlanCheck[i,7] <- rv$UploadedMetaAnalysisPlan_Int[i,7] %in% HKAdjustment_Choice
                rv$UploadPlanCheck[i,8] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 8])
                rv$UploadPlanCheck[i,9] <- rv$UploadedMetaAnalysisPlan_Int[i,9] %in% c("Yes","No")
                rv$UploadPlanCheck[i,10] <- all(c(is.numeric(rv$UploadedMetaAnalysisPlan_Int[i,10]),rv$UploadedMetaAnalysisPlan_Int[i,10]>3,rv$UploadedMetaAnalysisPlan_Int[i,10]<=20))
                rv$UploadPlanCheck[i,11] <- rv$UploadedMetaAnalysisPlan_Int[i,11] %in% Metabias_Any_Choice[1:3]
                rv$UploadPlanCheck[i,12] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 12])
                rv$UploadPlanCheck[i,13] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 13])
                rv$UploadPlanCheck[i,14] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 14])
                rv$UploadPlanCheck[i,15] <- any(c(is.na(rv$UploadedMetaAnalysisPlan_Int[i, 15]), 
                                                  !TRUE %in% is.na(match(strsplit(rv$UploadedMetaAnalysisPlan_Int[i, 15],", ")[[1]],
                                                                         rv$OldColumnNames))))
              }  else {
                rv$UploadPlanCheck[i,2] <- rv$UploadedMetaAnalysisPlan_Int[i,2] %in% c(EffectMeasure_Binary_Choice_Converter, EffectMeasure_Continuous_Choice_Converter, "HR")
                rv$UploadPlanCheck[i,3] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 3])
                rv$UploadPlanCheck[i,4] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 4])
                rv$UploadPlanCheck[i,5] <- rv$UploadedMetaAnalysisPlan_Int[i,5] %in% FixedEffect_Choice
                rv$UploadPlanCheck[i,6] <- rv$UploadedMetaAnalysisPlan_Int[i,6] %in% PredictionInterval_Choice
                rv$UploadPlanCheck[i,7] <- rv$UploadedMetaAnalysisPlan_Int[i,7] %in% HKAdjustment_Choice
                rv$UploadPlanCheck[i,8] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 8])
                rv$UploadPlanCheck[i,9] <- rv$UploadedMetaAnalysisPlan_Int[i,9] %in% c("Yes","No")
                rv$UploadPlanCheck[i,10] <- all(c(is.numeric(rv$UploadedMetaAnalysisPlan_Int[i,10]),rv$UploadedMetaAnalysisPlan_Int[i,10]>3,rv$UploadedMetaAnalysisPlan_Int[i,10]<=20))
                rv$UploadPlanCheck[i,11] <- rv$UploadedMetaAnalysisPlan_Int[i,11] %in% Metabias_Any_Choice[1:3]
                rv$UploadPlanCheck[i,12] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 12])
                rv$UploadPlanCheck[i,13] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 13])
                rv$UploadPlanCheck[i,14] <- is.na(rv$UploadedMetaAnalysisPlan_Int[i, 14])
                rv$UploadPlanCheck[i,15] <- any(c(is.na(rv$UploadedMetaAnalysisPlan_Int[i, 15]), 
                                                  !TRUE %in% is.na(match(strsplit(rv$UploadedMetaAnalysisPlan_Int[i, 15],", ")[[1]],
                                                                         rv$OldColumnNames))))
              }
            }
            if (!TRUE %in% (rowSums(rv$UploadPlanCheck == FALSE)>0)) {
              rv$UploadedMetaAnalysisPlan_Int[,c(10,13,14)] <- lapply(rv$UploadedMetaAnalysisPlan_Int[,c(10,13,14)],as.numeric)
              
              output$htmlMsg1_Int <- renderUI(
                HTML('<h2 style="color:darkgreen; background-color:yellow">
                  <b>Data upload: complete<br>
                  Meta-analysis plan: based on uploaded file<br>
                  <i>Modify the plan as necessary before you run the analysis.</i></b>
                       </h2>')
              )
              
              output$Header_Upload_MetaAnalysisPlan_Int_UI <- NULL 
              output$Upload_MetaAnalysisPlan_Int_UI <- NULL
              rv$UploadPlanCheck <- NULL
              rv$ResetData = "No"
              rv$ResetPlan = "No"
              rv$AcceptModification = "No"
              rv$RowsForModification <- NULL
              
              output$Header_SelectedMetaAnalysisPlan_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>Current meta-analysis plan (intervention review)</b></h3>'))
              output$Download_SelectedMetaAnalysisPlan_Int_UI <- renderUI(downloadButton("Selected.ma.plan_Int", HTML("Download selected meta-analysis plan (intervention review)")))
              output$SelectedMetaAnalysisPlan_Int_UI <- renderUI(
                tableOutput("SelectedMetaAnalysisPlan_Int")
              )
              
              # From this stage, run the meta-analysis plan should be available
              output$Run_MetaAnalysisPlan_UI <- renderUI(
                actionButton("Run_MetaAnalysisPlan", "Run the current meta-analysis plan")          
              )
              
              # run or modify depends upon the input$MetaAnalysisPlan_Choice_Int value
              if (input$MetaAnalysisPlan_Choice_Int == "I want to use my own meta-analysis plan that I have prepared previously for intervention reviews using this programme without any modifications") {
                rv$ModifyPlan = "No"
                rv$RunAnalysis = "Run"
              } else {
                rv$ModifyPlan = "Modify"
                rv$RunAnalysis = "No"
              }
            } else {
              output$htmlMsg1_Int <- renderUI(
                HTML(paste0('<h2 style="color:darkgreen; background-color:yellow"><b>Data upload: complete</h2><br>
                  <h2 style="color:red; background-color:yellow"><b>Please upload a file that is prepared as per the instructions.</b><br>
                 The following outcome names have one or more invalid entries: <i>', paste0(rv$UploadPlanCheck[rowSums(rv$UploadPlanCheck == FALSE)>0, 1],collapse = ', '),
                            '</i></h2>'))
              )  
            }
          } else {
            output$htmlMsg1_Int <- renderUI(
              HTML(paste0('<h2 style="color:darkgreen; background-color:yellow"><b>Data upload: complete</h2><br>
                  <h2 style="color:red; background-color:yellow"><b>Please upload a file that is prepared as per the instructions: </b>
                 <i>The order of outcome names in the data file and the meta-analysis plan do not match.<br>
                        If you have changed the name, number or order of outcomes in the data file, please prepare a new plan using the program.</i></h2>'))
            )  
          }
        } else {
          output$htmlMsg1_Int <- renderUI(
            HTML('<h2 style="color:darkgreen; background-color:yellow"><b>Data upload: complete</h2><br>
                  <h2 style="color:red; background-color:yellow"><b>Please upload a file that is prepared as per the instructions:</b><br>
               <i>The headings of the columns do not match the headings in the template.</i></h2>')
          )
        }
      }
    }
  })
  
  observeEvent(rv$ModifyPlan, {
    if (rv$ModifyPlan == "Modify"){
      output$Header_Upload_MetaAnalysisPlan_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>Modifying meta-analysis plan (intervention review)</b></h3>'))
      output$Upload_MetaAnalysisPlan_Int_UI <- NULL
      output$MA_Outcome_UI <- renderUI(
        selectInput("MA_Outcome", "Please select the outcome you want to modify:", choices = c("", rv$outcome.summary_Int[,1]),
                    width = "100%", selected = character(0), selectize = FALSE)
      )
      output$MA_EffectMeasure_UI <- NULL
      output$MA_ContinuityCorrection_UI <- NULL
      output$MA_RareEventsMethod_UI <- NULL
      output$MA_FixedEffect_UI <- NULL
      output$MA_PredictionInterval_UI <- NULL
      output$MA_HKAdjustment_UI <- NULL
      output$MA_Method_UI <- NULL
      output$MA_Summary_UI <- NULL
      output$MA_Minimum_Studies_UI <- NULL
      output$MA_Metabias_Any_UI <- NULL
      output$MA_Metabias_Heterogeneity_UI <- NULL
      output$MA_IMOR1_UI <- NULL
      output$MA_IMOR2_UI <- NULL
      output$MA_SubgroupSelection_UI <- NULL
      output$Reset_MA_UI <- NULL
      output$Modify_MA_Row_UI <- NULL
      output$Modify_MA_RowsOfSimilarType_UI <- NULL
      output$ModifyOneMoreMA_Row_UI <- NULL
      output$htmlMA_Modify_Msg <- NULL
    } else {
      output$Header_Upload_MetaAnalysisPlan_Int_UI <- NULL
      output$MA_Outcome_UI <- NULL
      output$MA_EffectMeasure_UI <- NULL
      output$MA_ContinuityCorrection_UI <- NULL
      output$MA_RareEventsMethod_UI <- NULL
      output$MA_FixedEffect_UI <- NULL
      output$MA_PredictionInterval_UI <- NULL
      output$MA_HKAdjustment_UI <- NULL
      output$MA_Method_UI <- NULL
      output$MA_Summary_UI <- NULL
      output$MA_Minimum_Studies_UI <- NULL
      output$MA_Metabias_Any_UI <- NULL
      output$MA_Metabias_Heterogeneity_UI <- NULL
      output$MA_IMOR1_UI <- NULL
      output$MA_IMOR2_UI <- NULL
      output$MA_SubgroupSelection_UI <- NULL
      output$Reset_MA_UI <- NULL
      output$Modify_MA_Row_UI <- NULL
      output$Modify_MA_RowsOfSimilarType_UI <- NULL
      output$ModifyOneMoreMA_Row_UI <- NULL
      output$htmlMA_Modify_Msg <- NULL
    }
  })
  
  observeEvent(input$MA_Outcome, {
    if (all(c(input$MA_Outcome != "", !is.null(input$MA_Outcome), input$MA_Outcome != character(0)))) {
      if (!is.na(match(input$MA_Outcome, rv$outcome.summary_Int[,1]))) {
        rv$OutcomeRow <- match(input$MA_Outcome, rv$outcome.summary_Int[,1])
        output$MA_Outcome_UI <- renderUI(HTML(paste0('<b>Outcome being modified: </b>',input$MA_Outcome,'<br><b>Type of outcome: </b>',rv$outcome.summary_Int[rv$OutcomeRow,2])))
        # Some choices are present regardless of outcome type
        output$MA_FixedEffect_UI <- renderUI(
          radioButtons("MA_FixedEffect", 
                       "Do you want to perform meta-analysis using the fixed-effect model (in addition to random-effects model)?", 
                       choices = c("Yes","No"),
                       width = "100%",
                       inline = TRUE,
                       selected = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 5]
          )
        )
        output$MA_PredictionInterval_UI <- renderUI(
          radioButtons("MA_PredictionInterval", 
                       "Do you want to calculate the prediction interval?", 
                       choices = c("Yes","No"),
                       width = "100%",
                       inline = TRUE,
                       selected = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 6]
          )
        )
        output$MA_HKAdjustment_UI <- renderUI(
          radioButtons("MA_HKAdjustment", 
                       "Do you want to perform Hartung and Knapp adjustment for the random-effects model confidence intervals)?", 
                       choices = c("Yes","No"),
                       width = "100%",
                       inline = TRUE,
                       selected = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 7]
          )
        )
        output$MA_Summary_UI <- renderUI(
          radioButtons("MA_Summary", 
                       "Do you want the meta-analysis results (rather than just the results of the individual studies or subgroups)?", 
                       choices = c("Yes","No"),
                       width = "100%",
                       inline = TRUE,
                       selected = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 9]
          )
        )
        output$MA_Minimum_Studies_UI <- renderUI(
          sliderInput("MA_Minimum_Studies", 
                      "How many studies should there be as a minimum to perform tests for funnel plot asymmetry?", 
                      min = 4, max = 20,
                      step = 1,
                      round = TRUE,
                      width = "100%",
                      value = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 10]
          )
        )
        output$MA_SubgroupSelection_UI <- renderUI(
          checkboxGroupInput("MA_SubgroupSelection", 
                             "Please select the moderator variables that you want to include in the metaregression and perform subgroup analysis", 
                             choices = rv$OldColumnNames[29:length(rv$OldColumnNames)],
                             width = "100%",
                             inline = TRUE,
                             selected =  strsplit(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 15],", ")[[1]]
          )
        )
        
        if (tolower(rv$outcome.summary_Int[rv$OutcomeRow,2]) == "binary") {
          output$MA_EffectMeasure_UI <- renderUI(
            radioButtons("MA_EffectMeasure", 
                         "Which effect measure do you want to use?", 
                         choices = EffectMeasure_Binary_Choice,
                         width = "100%",
                         inline = TRUE,
                         selected = EffectMeasure_Binary_Choice[match(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 2],EffectMeasure_Binary_Choice_Converter)]
            )
          )
          output$MA_ContinuityCorrection_UI <- renderUI(
            radioButtons("MA_ContinuityCorrection", 
                         "What continuity correction should be used in studies with zero events?", 
                         choices = RareEvents_Correction_Choice,
                         width = "100%",
                         inline = TRUE,
                         selected = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 3]
            )
          )
          output$MA_RareEventsMethod_UI <- renderUI(
            radioButtons("MA_RareEventsMethod", 
                         "Which method should be used for meta-analysis of studies with rare events?", 
                         choices = RareEvents_Method_Choice,
                         width = "100%",
                         inline = TRUE,
                         selected = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 4]
            )
          )
          output$MA_Method_UI <- renderUI(
            radioButtons("MA_Method", 
                         "Which method should be used for meta-analysis?", 
                         choices = MA_Method_Binary_Choice,
                         width = "100%",
                         inline = TRUE,
                         selected = MA_Method_Binary_Choice[match(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 8],MA_Method_Binary_Choice_Converter)]
            )
          )
          output$MA_Metabias_Any_UI <- renderUI(
            radioButtons("MA_Metabias_Any", 
                         "Which tests do you want to use for assessing funnel plot asymmetry?", 
                         choices = Metabias_Any_Choice,
                         width = "100%",
                         inline = TRUE,
                         selected = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 11]
            )
          )
          output$MA_Metabias_Heterogeneity_UI <- renderUI(
            radioButtons("MA_Metabias_Heterogeneity", 
                         "Which tests do you want to use for assessing funnel plot asymmetry when there is high heterogeneity?", 
                         choices = Metabias_Heterogeneity_Choice,
                         width = "100%",
                         inline = TRUE,
                         selected = Metabias_Heterogeneity_Choice[match(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 12],Metabias_Heterogeneity_Choice_Converter)]
            )
          )
          output$MA_IMOR1_UI <- renderUI(
            sliderInput("MA_IMOR1", 
                        "What is the informative missingness odds ratio that should be used for intervention group?", 
                        min = 0.01, max = 100,
                        step = 0.01,
                        round = FALSE,
                        width = "100%",
                        value = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 13]
            )
          )
          output$MA_IMOR2_UI <- renderUI(
            sliderInput("MA_IMOR2", 
                        "What is the informative missingness odds ratio that should be used for control group?", 
                        min = 0.01, max = 100,
                        step = 0.01,
                        round = FALSE,
                        width = "100%",
                        value = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 14]
            )
          )
          
          # Continuous outcomes begin here  
        } else if (tolower(rv$outcome.summary_Int[rv$OutcomeRow,2]) == "continuous") {
          output$MA_EffectMeasure_UI <- renderUI(
            radioButtons("MA_EffectMeasure", 
                         "Which effect measure do you want to use?", 
                         choices = EffectMeasure_Continuous_Choice,
                         width = "100%",
                         inline = TRUE,
                         selected = EffectMeasure_Continuous_Choice[match(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 2],EffectMeasure_Continuous_Choice_Converter)]
            )
          )
          output$MA_Method_UI <- renderUI(
            radioButtons("MA_Method", 
                         "Which method should be used for meta-analysis for standardised mean difference (applicable only if the effect measure is standardised mean difference)?", 
                         choices = MA_Method_SMD_Choice,
                         width = "100%",
                         inline = TRUE,
                         selected = ifelse(is.na(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 8]),
                                           "Hedges's g with exact SMD",
                                           MA_Method_SMD_Choice[match(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 8],MA_Method_SMD_Choice_Converter)])
            )
          )
          output$MA_Metabias_Any_UI <- renderUI(
            radioButtons("MA_Metabias_Any", 
                         "Which tests do you want to use for assessing funnel plot asymmetry?", 
                         choices = Metabias_Any_Choice[1:3],
                         width = "100%",
                         inline = TRUE,
                         selected = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 11]
            )
          )
          # Null for the ones that are specific to binary outcomes
          output$MA_ContinuityCorrection_UI <- NULL
          output$MA_RareEventsMethod_UI <- NULL
          output$MA_Metabias_Rare_UI <- NULL
          output$MA_IMOR1_UI <- NULL
          output$MA_IMOR2_UI <- NULL
          
          # All other types of outcomes
        } else {
          output$MA_Metabias_Any_UI <- renderUI(
            radioButtons("MA_Metabias_Any", 
                         "Which tests do you want to use for assessing funnel plot asymmetry?", 
                         choices = Metabias_Any_Choice[1:3],
                         width = "100%",
                         inline = TRUE,
                         selected = rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 11]
            )
          )
          if (tolower(rv$outcome.summary_Int[rv$OutcomeRow,2]) == "summary_ratio") {
            output$MA_EffectMeasure_UI <- renderUI(
              radioButtons("MA_EffectMeasure", 
                           "Which effect measure do you want to use?", 
                           choices = EffectMeasure_Ratio_Choice,
                           width = "100%",
                           inline = TRUE,
                           selected = EffectMeasure_Ratio_Choice[match(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 2],EffectMeasure_Ratio_Choice_Converter)]
              )
            )
          } else if (tolower(rv$outcome.summary_Int[rv$OutcomeRow,2]) == "count") {
            output$MA_EffectMeasure_UI <- renderUI(
              radioButtons("MA_EffectMeasure", 
                           "Which effect measure do you want to use?", 
                           choices = EffectMeasure_Count_Choice,
                           width = "100%",
                           inline = TRUE,
                           selected = EffectMeasure_Count_Choice[match(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 2],EffectMeasure_Count_Choice_Converter)]
              )
            )
          } else {
            output$MA_EffectMeasure_UI <- renderUI(
              radioButtons("MA_EffectMeasure", 
                           "Which effect measure do you want to use?", 
                           choices = EffectMeasure_Difference_Choice,
                           width = "100%",
                           inline = TRUE,
                           selected = EffectMeasure_Difference_Choice[match(rv$UploadedMetaAnalysisPlan_Int[rv$OutcomeRow, 2],EffectMeasure_Difference_Choice_Converter)]
              )
            )
          }
          
          # Null for the ones that are specific to binary outcomes or continuous outcomes
          output$MA_ContinuityCorrection_UI <- NULL
          output$MA_RareEventsMethod_UI <- NULL
          output$MA_Method_UI <- NULL
          output$MA_Metabias_Rare_UI <- NULL
          output$MA_IMOR1_UI <- NULL
          output$MA_IMOR2_UI <- NULL
        }
        # Now choices for modify, run etc
        output$Reset_MA_UI <- renderUI(
          actionButton("Reset_MA", "Discard unsaved changes to modification plan")
        )
        output$Modify_MA_Row_UI <- renderUI(
          actionButton("Modify_MA_Row", "Modify the plan as above")
        )
        output$Modify_MA_RowsOfSimilarType_UI <- renderUI(
          actionButton("Modify_MA_RowsOfSimilarType", "Modify the plan for all outcomes of similar type")
        )
      }
    }    
  })
  
  observeEvent(input$Reset_MA, {
    # Discard all changes
    # Change rv$ModifyPlan to no and then back to Modify
    rv$ModifyPlan = "No"
    rv$RunAnalysis = "No"
    rv$ResetData = "No"
    rv$ResetPlan = "No"
    rv$AcceptModification = "No"
    rv$RowsForModification <- NULL
    rv$ModifyPlan = "Modify"
  })
  
  observeEvent(input$Run_MetaAnalysisPlan, {
    # Discard all changes
    # Change rv$ModifyPlan to no
    rv$ModifyPlan = "No"
    rv$ResetData = "No"
    rv$ResetPlan = "No"
    rv$AcceptModification = "No"
    rv$RowsForModification <- NULL
    # Change rv$RunAnalysis to "Run"
    rv$RunAnalysis = "Run"
  })
  
  observeEvent(input$Reset_MetaAnalysisPlan_Int, {
    # Discard all changes
    # Change rv$ModifyPlan to no
    rv$ModifyPlan = "No"
    rv$RunAnalysis = "No"
    rv$ResetData = "No"
    rv$AcceptModification = "No"
    rv$RowsForModification <- NULL
    rv$ResetPlan = "Reset"
    
  })
  observeEvent(input$Reset_MetaAnalysisPlan_Int_2, {
    # Change panel to 4
    output$htmlTitle <- renderUI(HTML(MainHeaderSelection[4]))
    panelchoice = "panel4"
    updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
    updateRadioButtons(inputId = "Activity", choices = FirstSelection[1:4], selected = FirstSelection[4])
    # Discard all changes
    # Change rv$ModifyPlan to no
    rv$ModifyPlan = "No"
    rv$RunAnalysis = "No"
    rv$ResetData = "No"
    rv$AcceptModification = "No"
    rv$RowsForModification <- NULL
    rv$ResetPlan = "Reset"
    
  })
  
  # Modify one row or all rows of similar outcome types differs only in the rows selected for implementing changes
  # ModifyPlan variable refers to start of the modification rather than accepting the modification
  observeEvent(input$Modify_MA_Row, {
    rv$ModifyPlan = "No"
    rv$ResetData = "No"
    rv$ResetPlan = "No"
    rv$RunAnalysis = "No"
    rv$RowsForModification <- (row(rv$outcome.summary_Int)[,1] == rv$OutcomeRow)
    rv$AcceptModification = "Yes"
  })
  
  observeEvent(input$Modify_MA_RowsOfSimilarType, {
    rv$ModifyPlan = "No"
    rv$ResetData = "No"
    rv$ResetPlan = "No"
    rv$RunAnalysis = "No"
    rv$RowsForModification <-  (rv$outcome.summary_Int[,2] == rv$outcome.summary_Int[rv$OutcomeRow,2])
    rv$AcceptModification = "Yes"
  })
  
  observeEvent(rv$AcceptModification, {
    # Because of the way the form is designed, it is not possible to have empty fields
    # Some conversions need to be done before values are replaced
    # Results in errors by changing the values by subsetting it: a loop is used therefore
    if (rv$AcceptModification == "Yes") {
      if (tolower(rv$outcome.summary_Int[rv$OutcomeRow,2]) == "binary") {
        for (i in 1:length(rv$RowsForModification)) {
          if (rv$RowsForModification[i] == TRUE) {
            rv$UploadedMetaAnalysisPlan_Int[i,2:15] <- c(
              EffectMeasure_Binary_Choice_Converter[match(input$MA_EffectMeasure,EffectMeasure_Binary_Choice)],
              input$MA_ContinuityCorrection,
              input$MA_RareEventsMethod,
              input$MA_FixedEffect,
              input$MA_PredictionInterval,
              input$MA_HKAdjustment,
              MA_Method_Binary_Choice_Converter[match(input$MA_Method,MA_Method_Binary_Choice)],
              input$MA_Summary,
              as.numeric(input$MA_Minimum_Studies),
              input$MA_Metabias_Any,
              Metabias_Heterogeneity_Choice_Converter[match(input$MA_Metabias_Heterogeneity,Metabias_Heterogeneity_Choice)],
              as.numeric(input$MA_IMOR1),
              as.numeric(input$MA_IMOR2),
              ifelse(all(c(!input$MA_SubgroupSelection != character(0),!is.na(input$MA_SubgroupSelection), length(input$MA_SubgroupSelection)>0)),paste0(input$MA_SubgroupSelection, collapse = ", "),NA)
            )    
          }
        }
      } else if (tolower(rv$outcome.summary_Int[rv$OutcomeRow,2]) == "continuous") {
        for (i in 1:length(rv$RowsForModification)) {
          if (rv$RowsForModification[i] == TRUE) {
            rv$UploadedMetaAnalysisPlan_Int[i,2:15] <- c(
              EffectMeasure_Continuous_Choice_Converter[match(input$MA_EffectMeasure,EffectMeasure_Continuous_Choice)],
              NA,
              NA,
              input$MA_FixedEffect,
              input$MA_PredictionInterval,
              input$MA_HKAdjustment,
              ifelse(input$MA_EffectMeasure == "Standardised mean difference", MA_Method_SMD_Choice_Converter[match(input$MA_Method,MA_Method_SMD_Choice)],NA),
              input$MA_Summary,
              as.numeric(input$MA_Minimum_Studies),
              input$MA_Metabias_Any,
              NA,
              NA,
              NA,
              ifelse(all(c(!input$MA_SubgroupSelection != character(0),!is.na(input$MA_SubgroupSelection), length(input$MA_SubgroupSelection)>0)),paste0(input$MA_SubgroupSelection, collapse = ", "),NA)
            )
          }
        }
      } else {
        for (i in 1:length(rv$RowsForModification)) {
          if (rv$RowsForModification[i] == TRUE) {
            if (tolower(rv$outcome.summary_Int[rv$OutcomeRow,2]) == "summary_ratio") {
              rv$UploadedMetaAnalysisPlan_Int[i,2] <- EffectMeasure_Ratio_Choice_Converter[match(input$MA_EffectMeasure,EffectMeasure_Ratio_Choice)]
            } else {
              EffectMeasure_Difference_Choice_Converter[match(input$MA_EffectMeasure,EffectMeasure_Difference_Choice)]
            }
            rv$UploadedMetaAnalysisPlan_Int[i,3:15] <- c(
              NA,
              NA,
              input$MA_FixedEffect,
              input$MA_PredictionInterval,
              input$MA_HKAdjustment,
              NA,
              input$MA_Summary,
              as.numeric(input$MA_Minimum_Studies),
              input$MA_Metabias_Any,
              NA,
              NA,
              NA,
              ifelse(all(c(!input$MA_SubgroupSelection != character(0),!is.na(input$MA_SubgroupSelection), length(input$MA_SubgroupSelection)>0)),paste0(input$MA_SubgroupSelection, collapse = ", "),NA)
            )    
          }
        }
      }
      rv$UploadedMetaAnalysisPlan_Int[,c(10,13,14)] <- lapply(rv$UploadedMetaAnalysisPlan_Int[,c(10,13,14)],as.numeric)
      output$htmlMA_Modify_Msg <- renderUI(
        HTML(paste0('<h2 style="color:darkgreen; background-color:yellow"><b>Modification successful. Please select what you want to do next.</b></h2><br>'))
      )
      
      # Now add one more plan row
      output$ModifyOneMoreMA_Row_UI <- renderUI(
        actionButton("ModifyOneMoreMA_Row", "Modify one more row")
      )
    }
  })
  
  observeEvent(input$ModifyOneMoreMA_Row, {
    # Discard all changes
    # Change rv$ModifyPlan to no and then back to Modify
    rv$ModifyPlan = "No"
    rv$RunAnalysis = "No"
    rv$ResetData = "No"
    rv$ResetPlan = "No"
    rv$AcceptModification = "No"
    rv$RowsForModification <- NULL
    rv$ModifyPlan = "Modify"
  })
  
  observeEvent(rv$RunAnalysis, {
    if (rv$RunAnalysis == "Run"){
      unlink(paste0(rv$StorageFolder,'/*'), recursive = FALSE, force = TRUE)
      withProgress(message = 'Data analysis', value = 0, {
        rv$outcome.summary_Int <- cbind(rv$outcome.summary_Int,
                                        Effect.Estimates = rep(NA,nrow(rv$outcome.summary_Int)),
                                        I.square = rep(NA,nrow(rv$outcome.summary_Int)),
                                        tau.square = rep(NA,nrow(rv$outcome.summary_Int)),
                                        Funnel.plot.asymmetry.p.value = rep(NA,nrow(rv$outcome.summary_Int)),
                                        Sensitivity.Analysis = rep(NA,nrow(rv$outcome.summary_Int)),
                                        Metaregression = rep(NA,nrow(rv$outcome.summary_Int)),
                                        Subgroup.Analysis = rep("",nrow(rv$outcome.summary_Int))
        )
        colnames(rv$outcome.summary_Int)[8:14] <- c('Effect Estimates', 'I-square', 'tau-square', 
                                                    'Funnel plot asymmetry (p-value)',  'Sensitivity Analysis', 
                                                    'Metaregression', 'Subgroup Analysis') 
        for (i in 1:nrow(rv$outcome.summary_Int)){
          incProgress(1/(2*nrow(rv$outcome.summary_Int)), detail = paste0('Analysing Outcome: ',i,' of ', nrow(rv$outcome.summary_Int), ' outcomes'))
          
          if (rv$outcome.summary_Int[i,5] == 0){
            rv$MA[[i]] <- as.character("No studies with adequate data for this outcome")
            rv$MetaBias[[i]] <- as.character("No studies with adequate data for this outcome")
            rv$SA[[i]] <- as.character("No studies with adequate data for this outcome")
            rv$MetaReg[[i]] <- as.character("No studies with adequate data for this outcome")
            rv$outcome.summary_Int[i,8:13] <- "No studies with adequate data for this outcome"
            
            # Create 10 subgroup lists
            for (j in 29:ncol(rv$InputData)){
              eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("No studies with adequate data for this outcome")')))
            }
            
          } else {
            rv$EffectMeasure <- rv$UploadedMetaAnalysisPlan_Int[i,2]
            rv$Metabias.Min <- rv$UploadedMetaAnalysisPlan_Int[i,10]
            if (tolower(rv$outcome.summary_Int[i,2]) == "binary") {
              # For binary outcome, it is metabin and effect measure is odds ratio as default
              rv$MA[[i]] <- metabin(
                rv$df_Outcome[[i]][,7],
                rv$df_Outcome[[i]][,5],
                rv$df_Outcome[[i]][,8],
                rv$df_Outcome[[i]][,6],
                data = rv$df_Outcome[[i]],
                studlab = rv$df_Outcome[[i]][,4],
                common = (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),
                text.common = "Fixed effect model",
                text.w.common = "fixed",
                sm = rv$EffectMeasure,
                method = rv$UploadedMetaAnalysisPlan_Int[i,8],
                overall = (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),
                method.random.ci = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),
                method.predict = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"),
                prediction = (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),
                outclab = rv$outcome.summary_Int[i,1],
                label.e = rv$InputData[2,28],
                label.c = rv$InputData[4,28],
                label.left = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])),
                label.right = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28]))
              )
              rv$GenerateCode <- rbind(rv$GenerateCode, 
                                       paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- metabin(',
                                              rv$OutcomeNamesForCodes[i],'[,7],',
                                              rv$OutcomeNamesForCodes[i],'[,5],',
                                              rv$OutcomeNamesForCodes[i],'[,8],',
                                              rv$OutcomeNamesForCodes[i],'[,6],',
                                              'data = ', rv$OutcomeNamesForCodes[i],',',
                                              'studlab = ', rv$OutcomeNamesForCodes[i],'[,4],',
                                              'common = ', (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),',',
                                              'text.common = "Fixed effect model", text.w.common = "fixed",',
                                              'sm = "', rv$EffectMeasure, '",',
                                              'method = "', rv$UploadedMetaAnalysisPlan_Int[i,8], '",',
                                              'overall = ', (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),',',
                                              'method.random.ci ="', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"), '",',
                                              'method.predict = "',ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"), '",',
                                              'prediction = ', (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),',',
                                              'outclab = "', rv$outcome.summary_Int[i,1], '",',
                                              'label.e = "', rv$InputData[2,28], '",',
                                              'label.c = "', rv$InputData[4,28], '",',
                                              'label.left = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])), '",',
                                              'label.right = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28])), '"',
                                              ')'
                                       )
              )
              if (rv$EffectMeasure == "RR" | rv$EffectMeasure == "RD"){
                rv$MA[[i]] <- update(
                  rv$MA[[i]],
                  RR.Cochrane = (rv$UploadedMetaAnalysisPlan_Int[i,3] == "Continuity correction with 0.5 for events and no events"),
                  method.random.ci = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),
                  adhoc.hakn.ci = "se",
                  method.predict = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"),
                  adhoc.hakn.pi = "se"
                )
                rv$GenerateCode <- rbind(rv$GenerateCode, 
                                         paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- update(',
                                                'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                'RR.Cochrane = ', (rv$UploadedMetaAnalysisPlan_Int[i,3] == "Continuity correction with 0.5 for events and no events"),',',
                                                'method.random.ci = "', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),'",',
                                                'adhoc.hakn.ci = "se"',',',
                                                'method.predict = "', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"),'",',
                                                'adhoc.hakn.pi = "se"',
                                                ')'
                                         )
                )
              } else {
                # If rare event indicated by rv$MA_1$sparse, then GLMM as default, but user can decide whether to use Peto or perform the meta-analysis with continuity correction
                if (!is.null(rv$MA[[i]]$sparse) & rv$MA[[i]]$sparse == TRUE){
                  if (rv$UploadedMetaAnalysisPlan_Int[i,4] == "Generalised Linear Mixed Model (only for odds ratios)"){
                    # First try GLMM model with exact likelihood
                    suppressWarnings({
                      suppressMessages({
                        rv$MA[[i]] <- 
                          try(
                            update(
                              rv$MA[[i]],
                              method = "GLMM",
                              model.glmm = "CM.EL",
                              method.predict = "HTS"
                            )
                          )
                      })
                    })
                    # If there is no convergence, then approximate likelihood
                    # To find if the model worked, check whether rv$MA[[i]] contains error
                    if (grepl("Error",rv$MA[[i]])[1] == TRUE) {
                      # Use GLMM model with approximate likelihood
                      rv$MA[[i]] <- metabin(
                        rv$df_Outcome[[i]][,7],
                        rv$df_Outcome[[i]][,5],
                        rv$df_Outcome[[i]][,8],
                        rv$df_Outcome[[i]][,6],
                        data = rv$df_Outcome[[i]],
                        studlab = rv$df_Outcome[[i]][,4],
                        common = (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),
                        text.common = "Fixed effect model",
                        text.w.common = "fixed",
                        sm = "OR",
                        method = "GLMM",
                        model.glmm = "CM.AL",
                        overall = (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),
                        method.random.ci = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),
                        method.predict = "HTS",
                        prediction = (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),
                        outclab = rv$outcome.summary_Int[i,1],
                        label.e = rv$InputData[2,28],
                        label.c = rv$InputData[4,28],
                        label.left = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])),
                        label.right = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28]))
                      )
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- metabin(',
                                                      rv$OutcomeNamesForCodes[i],'[,7],',
                                                      rv$OutcomeNamesForCodes[i],'[,5],',
                                                      rv$OutcomeNamesForCodes[i],'[,8],',
                                                      rv$OutcomeNamesForCodes[i],'[,6],',
                                                      'data = ', rv$OutcomeNamesForCodes[i],',',
                                                      'studlab = ', rv$OutcomeNamesForCodes[i],'[,4],',
                                                      'common = ', (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),',',
                                                      'text.common = "Fixed effect model", text.w.common = "fixed",',
                                                      'sm = "OR",',
                                                      'method = "GLMM",',
                                                      'model.glmm = "CM.AL",',
                                                      'overall = ', (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),',',
                                                      'method.random.ci ="', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"), '",',
                                                      'method.predict = "',ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"), '",',
                                                      'prediction = ', (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),',',
                                                      'outclab = "', rv$outcome.summary_Int[i,1], '",',
                                                      'label.e = "', rv$InputData[2,28], '",',
                                                      'label.c = "', rv$InputData[4,28], '",',
                                                      'label.left = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])), '",',
                                                      'label.right = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28])), '"',
                                                      ')'
                                               )
                      )
                    } else {
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- update(',
                                                      'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                      'method = "GLMM"',',',
                                                      'model.glmm = "CM.EL"',',',
                                                      'method.predict = "HTS"',
                                                      ')'
                                               )
                      )
                    }
                  } else {
                    rv$MA[[i]] <- update(
                      rv$MA[[i]],
                      method = "Peto"
                    )
                    
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- update(',
                                                    'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                    'method = "Peto"',
                                                    ')'
                                             )
                    )
                  }
                } else {
                  rv$MA[[i]] <- update(
                    rv$MA[[i]],
                    method.random.ci = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),
                    adhoc.hakn.ci = "se",
                    method.predict = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"),
                    adhoc.hakn.pi = "se"
                  )
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- update(',
                                                  'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                  'method.random.ci = "', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),'",',
                                                  'adhoc.hakn.ci = "se"',',',
                                                  'method.predict = "', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"),'",',
                                                  'adhoc.hakn.pi = "se"',
                                                  ')'
                                           )
                  )
                }
              }
              rv$outcome.summary_Int[i,8] <- paste0(
                ifelse(rv$MA[[i]]$sm %in% c("OR","RR","HR","ROM"), round(exp(rv$MA[[i]]$TE.random),2),round(rv$MA[[i]]$TE.random,2)),
                ' (95% CI ',
                ifelse(rv$MA[[i]]$sm %in% c("OR","RR","HR","ROM"), round(exp(rv$MA[[i]]$lower.random),2),round(rv$MA[[i]]$lower.random,2)),
                ' to ',
                ifelse(rv$MA[[i]]$sm %in% c("OR","RR","HR","ROM"), round(exp(rv$MA[[i]]$upper.random),2),round(rv$MA[[i]]$upper.random,2)),
                ')'
              )
              rv$outcome.summary_Int[i,9] <- rv$MA[[i]]$I2 
              rv$outcome.summary_Int[i,10] <- rv$MA[[i]]$tau2 
              
              # Metabias
              # To perform only if there are 10 or more trials
              if(nrow(rv$df_Outcome[[i]]) >=rv$Metabias.Min){
                # if tau2 < 0.1 then Harbord else perform Thomson test after repeating the meta-analysis
                if(rv$MA[[i]]$tau2 <0.1){
                  rv$MetaBias[[i]] <- metabias(
                    rv$MA[[i]],
                    method.bias = rv$UploadedMetaAnalysisPlan_Int[i,11],
                    k.min = rv$Metabias.Min,
                    plotit = FALSE
                  )
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('Funnel_',rv$OutcomeNamesForCodes[i],' <- metabias(',
                                                  'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                  'method.bias = "', rv$UploadedMetaAnalysisPlan_Int[i,11],'",',
                                                  'k.min = ', rv$Metabias.Min,',',
                                                  'plotit = FALSE',
                                                  ')'
                                           )
                  )
                } else {
                  if(as.character(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,12],"_")[[1]][1]) == "ASD"){
                    if (rv$MA[[i]]$method == "GLMM"){
                      rv$MA_Temp <- metabin(
                        rv$df_Outcome[[i]][,7],
                        rv$df_Outcome[[i]][,5],
                        rv$df_Outcome[[i]][,8],
                        rv$df_Outcome[[i]][,6],
                        data = rv$df_Outcome[[i]],
                        studlab = rv$df_Outcome[[i]][,4],
                        common = (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),
                        text.common = "Fixed effect model",
                        text.w.common = "fixed",
                        sm = "ASD",
                        method = rv$UploadedMetaAnalysisPlan_Int[i,8],
                        overall = (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),
                        method.random.ci = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),
                        adhoc.hakn.ci = "se",
                        method.predict = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"),
                        adhoc.hakn.pi = "se",
                        prediction = (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),
                        outclab = rv$outcome.summary_Int[i,1],
                        label.e = rv$InputData[2,28],
                        label.c = rv$InputData[4,28],
                        label.left = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])),
                        label.right = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28]))
                      )
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],'_Temp',' <- metabin(',
                                                      rv$OutcomeNamesForCodes[i],'[,7],',
                                                      rv$OutcomeNamesForCodes[i],'[,5],',
                                                      rv$OutcomeNamesForCodes[i],'[,8],',
                                                      rv$OutcomeNamesForCodes[i],'[,6],',
                                                      'data = ', rv$OutcomeNamesForCodes[i],',',
                                                      'studlab = ', rv$OutcomeNamesForCodes[i],'[,4],',
                                                      'common = ', (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),',',
                                                      'text.common = "Fixed effect model", text.w.common = "fixed",',
                                                      'sm = "ASD",',
                                                      'method = ', rv$UploadedMetaAnalysisPlan_Int[i,8],',',
                                                      'overall = ', (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),',',
                                                      'method.random.ci ="', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"), '",',
                                                      'adhoc.hakn.ci = "se"',',',
                                                      'method.predict = "',ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"), '",',
                                                      'adhoc.hakn.pi = "se"',',',
                                                      'prediction = ', (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),',',
                                                      'outclab = "', rv$outcome.summary_Int[i,1], '",',
                                                      'label.e = "', rv$InputData[2,28], '",',
                                                      'label.c = "', rv$InputData[4,28], '",',
                                                      'label.left = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])), '",',
                                                      'label.right = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28])), '"',
                                                      ')'
                                               )
                      )
                    } else {
                      rv$MA_Temp <- update(rv$MA[[i]], sm="ASD")
                      
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],'_Temp',' <- update(',
                                                      'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                      'sm="ASD"',
                                                      ')'
                                               )
                      )
                    }
                  } else {
                    rv$MA_Temp <- rv$MA[[i]]
                    
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],'_Temp',' <- ',
                                                    'MetaAnalysis_',rv$OutcomeNamesForCodes[i]
                                             )
                    )
                  }
                  rv$MetaBias[[i]] <- metabias(
                    rv$MA_Temp,
                    method.bias = as.character(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,12],"_")[[1]][2]),
                    k.min = rv$Metabias.Min,
                    plotit = FALSE
                  )
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('Funnel_',rv$OutcomeNamesForCodes[i],' <- metabias(',
                                                  'MetaAnalysis_',rv$OutcomeNamesForCodes[i],'_Temp',',',
                                                  'method.bias = "', as.character(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,12],"_")[[1]][2]),'",',
                                                  'k.min = ', rv$Metabias.Min,',',
                                                  'plotit = FALSE',
                                                  ')'
                                           )
                  )
                }
              } else {
                rv$MetaBias[[i]] <- paste0('Not performed as fewer than ', rv$Metabias.Min ,' trials')
                
                rv$GenerateCode <- rbind(rv$GenerateCode, 
                                         paste0('Funnel_',rv$OutcomeNamesForCodes[i],' <- ',
                                                '"Not performed as fewer than ', rv$Metabias.Min ,' trials"'
                                         )
                )
              }
              
              # Sensitivity analysis for missing data
              rv$SA[[i]] <- f.IMOR(rv$df_Outcome[[i]], rv$MA[[i]], IMOR_E = rv$UploadedMetaAnalysisPlan_Int[i,13], IMOR_C = rv$UploadedMetaAnalysisPlan_Int[i,14])
              
              rv$GenerateCode <- rbind(rv$GenerateCode, 
                                       paste0('SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.IMOR(',
                                              rv$OutcomeNamesForCodes[i],',',
                                              'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                              'IMOR_E = ', rv$UploadedMetaAnalysisPlan_Int[i,13],',',
                                              'IMOR_C = ', rv$UploadedMetaAnalysisPlan_Int[i,14],
                                              ')'
                                       )
              )
              # Until validation of the IMOR function, people may want to use the validated metamiss function - Therefore write codes related to that 
              rv$GenerateCode <- rbind(rv$GenerateCode,
                                       '# Until validation of the IMOR function, people may want to use the validated metamiss function',
                                       paste0(rv$OutcomeNamesForCodes[i],'[,',ncol(rv$InputData)+1,'] <- ',
                                              'suppressWarnings({suppressMessages({rowSums(',
                                              rv$OutcomeNamesForCodes[i],
                                              '[,c(14:19)], na.rm=TRUE) + as.numeric(as.character(',
                                              rv$OutcomeNamesForCodes[i],'[,20]))
                                              })
                                              })'
                                       ),
                                       paste0(rv$OutcomeNamesForCodes[i],'[is.na(',rv$OutcomeNamesForCodes[i],'[,',ncol(rv$InputData)+1,']),',ncol(rv$InputData)+1,'] <- 0'
                                       ),
                                       paste0(rv$OutcomeNamesForCodes[i],'[,',ncol(rv$InputData)+2,'] <- ',
                                              'suppressWarnings({suppressMessages({rowSums(',
                                              rv$OutcomeNamesForCodes[i],
                                              '[,c(21:26)], na.rm=TRUE) + as.numeric(as.character(',
                                              rv$OutcomeNamesForCodes[i],'[,27]))
                                              })
                                              })'
                                       ),
                                       paste0(rv$OutcomeNamesForCodes[i],'[is.na(',rv$OutcomeNamesForCodes[i],'[,',ncol(rv$InputData)+2,']),',ncol(rv$InputData)+2,'] <- 0'
                                       ),
                                       paste0('SensitivityAnalysis_MetaMiss_BestWorst_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'metamiss(MetaAnalysis_',rv$OutcomeNamesForCodes[i],', ',
                                              rv$OutcomeNamesForCodes[i],'[,',ncol(rv$InputData)+1,'],',
                                              rv$OutcomeNamesForCodes[i],'[,',ncol(rv$InputData)+2,'],',
                                              'small.values = ifelse(', rv$OutcomeNamesForCodes[i],'[1,3] == "Better","good","bad"), method.miss = "b")'
                                       ),
                                       paste0('SensitivityAnalysis_MetaMiss_WorstBest_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'metamiss(MetaAnalysis_',rv$OutcomeNamesForCodes[i],', ',
                                              rv$OutcomeNamesForCodes[i],'[,',ncol(rv$InputData)+1,'],',
                                              rv$OutcomeNamesForCodes[i],'[,',ncol(rv$InputData)+2,'],',
                                              'small.values = ifelse(', rv$OutcomeNamesForCodes[i],'[1,3] == "Better","good","bad"), method.miss = "w")'
                                       )
              )
              
              if(! is.character(rv$SA[[i]][[1]])) {
                rv$outcome.summary_Int[i,12] <- paste0(
                  'IMOR: ',
                  round(exp(rv$SA[[i]][[1]]$TE.random),2),
                  ' (95% CI ',
                  round(exp(rv$SA[[i]][[1]]$lower.random),2),
                  ' to ',
                  round(exp(rv$SA[[i]][[1]]$upper.random),2),
                  ')',
                  '\n',
                  'Best-worst: ',
                  round(exp(rv$SA[[i]][[2]]$TE.random),2),
                  ' (95% CI ',
                  round(exp(rv$SA[[i]][[2]]$lower.random),2),
                  ' to ',
                  round(exp(rv$SA[[i]][[2]]$upper.random),2),
                  ')',
                  '\n',
                  'Worst-best: ',
                  round(exp(rv$SA[[i]][[3]]$TE.random),2),
                  ' (95% CI ',
                  round(exp(rv$SA[[i]][[3]]$lower.random),2),
                  ' to ',
                  round(exp(rv$SA[[i]][[3]]$upper.random),2),
                  ')'
                )
              } else {
                rv$outcome.summary_Int[i,12] <- rv$SA[[i]][[1]]
              }
              
              # Metaregression
              if(!is.na(rv$UploadedMetaAnalysisPlan_Int[i,15])) {
                rv$SelectedCovariates <- strsplit(rv$UploadedMetaAnalysisPlan_Int[i,15],", ")
                rv$SelectedCovariatesColumns[[i]] <- as.vector(match(rv$SelectedCovariates[[1]], rv$OldColumnNames))
                if(length(rv$SelectedCovariatesColumns[[i]])>1){
                  rv$SelectedCovariatesColumnsSubgroup[[i]] <- rv$SelectedCovariatesColumns[[i]][!sapply(rv$InputData[,rv$SelectedCovariatesColumns[[i]]],is.numeric)]  
                } else {
                  rv$SelectedCovariatesColumnsSubgroup[[i]] <- ifelse(is.numeric(rv$InputData[,rv$SelectedCovariatesColumns[[i]]]),NA,rv$SelectedCovariatesColumns[[i]])
                }
                rv$MetaRegText[[i]] <- paste0(rv$NewColumnNames[rv$SelectedCovariatesColumns[[i]]],collapse = ' + ')
                rv$MetaReg[[i]] <- 
                  suppressWarnings({
                    suppressMessages({
                      try(
                        metareg(rv$MA[[i]],rv$MetaRegText[[i]], intercept = FALSE)
                      )
                    })
                  })
                if (grepl("Error", rv$MetaReg[[i]][1]) == TRUE) {
                  rv$MetaReg[[i]] <- as.character("Error in metaregression \n(usually due to too many moderators in the model or sparse data)")
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('MetaReg_',rv$OutcomeNamesForCodes[i],' <- ',
                                                  'as.character("Error in metaregression \n(usually due to too many moderators in the model or sparse data)")'
                                           )
                  )
                  rv$outcome.summary_Int[i,13] <- "Error in metaregression (usually due to too many moderators in the model or sparse data)"
                } else {
                  
                  # To ensure that the correct variable values are used for the covariates, store them as global variables again
                  for (j in 29:ncol(rv$df_Outcome[[i]])){
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0(colnames(rv$df_Outcome[[i]])[j], ' <- as.vector(',
                                                    rv$OutcomeNamesForCodes[i],'[,',j,'])'
                                             )
                    )
                  }
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('MetaReg_',rv$OutcomeNamesForCodes[i],' <- suppressWarnings({suppressMessages({',
                                                  'metareg(', 
                                                  'MetaAnalysis_', rv$OutcomeNamesForCodes[i],',',
                                                  rv$MetaRegText[[i]],',',
                                                  'intercept = FALSE',
                                                  ')
                                                  })
                                                  })'
                                           )
                  )
                  rv$outcome.summary_Int[i,13] <- paste0(
                    'Omnibus Test of Moderators (Does adding the moderator(s) improve the model fit?): ',
                    round(rv$MetaReg[[i]]$QMp,4), 
                    '\n',
                    paste0(
                      dimnames(rv$MetaReg[[i]]$b)[[1]],': ',
                      round(rv$MetaReg[[i]]$b,4), 
                      ' (95% CI ',round(rv$MetaReg[[i]]$ci.lb,4),
                      ' to ', round(rv$MetaReg[[i]]$ci.ub,4), 
                      '); p-value: ',
                      round(rv$MetaReg[[i]]$pval,4),
                      collapse = '\n'
                    ),
                    collapse =""
                  )
                  # Now replace the variable names
                  for (j in 29:ncol(rv$InputData)){
                    rv$outcome.summary_Int[i,13] <- str_replace_all(
                      str_replace_all(rv$outcome.summary_Int[i,13], 
                                      str_replace_all(
                                        str_replace_all(rv$NewColumnNames[j],regex('_Level_', ignore_case = FALSE),''),
                                        regex('_per.unit.increase', ignore_case = FALSE),''),
                                      rv$OldColumnNames[j]
                      ),
                      regex('_per.unit.increase', ignore_case = FALSE),
                      '_per unit increase')
                  }
                }
              } else {
                rv$SelectedCovariatesColumns[[i]] <- NA
                rv$SelectedCovariatesColumnsSubgroup[[i]] <- NA
                rv$MetaRegText[[i]] <- NA
                rv$MetaReg[[i]] <- as.character("No variables selected for metaregression")
                rv$GenerateCode <- rbind(rv$GenerateCode, 
                                         paste0('MetaReg_',rv$OutcomeNamesForCodes[i],' <- ',
                                                'as.character("No variables selected for metaregression")'
                                         )
                )
                rv$outcome.summary_Int[i,13] <- "No variables selected for metaregression"
              }
              # Subgroup analysis
              if (ncol(rv$InputData)>28){
                for (j in 29:ncol(rv$InputData)){
                  if (any(c(is.na(rv$SelectedCovariatesColumns[[i]]),!j %in% rv$SelectedCovariatesColumns[[i]]))) {
                    eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("This variable was not selected")')))
                    
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                    'as.character("This variable was not selected")'
                                             )
                    )
                    rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                           rv$OldColumnNames[j], 
                                                           ': This variable was not selected',
                                                           ifelse(j==ncol(rv$InputData),'','\n')
                    )
                    eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                           paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],': This variable was not selected'),'")'
                    )))
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                    'f.PlotText("',
                                                    rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],
                                                    ': This variable was not selected',
                                                    '")'
                                             )
                    )
                  } else {
                    if (any(c(is.na(rv$SelectedCovariatesColumnsSubgroup[[i]]),!j %in% rv$SelectedCovariatesColumnsSubgroup[[i]]))) {
                      eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("This is not a categorical variable")')))
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                      'as.character("This is not a categorical variable")'
                                               )
                      )
                      rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                             rv$OldColumnNames[j], 
                                                             ': This is not a categorical variable',
                                                             ifelse(j==ncol(rv$InputData),'','\n')
                      )
                      eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                             paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],'This is not a categorical variable'),'")'
                      )))
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                      'f.PlotText("',
                                                      rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],
                                                      ': This is not a categorical variable',
                                                      '")'
                                               )
                      )
                    } else {
                      eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- suppressWarnings({suppressMessages({try(
                                             update(rv$MA[[i]],subgroup = rv$df_Outcome[[i]][,',j,'],common=FALSE)
                                             )
                                             })
                                             })'
                      )))
                      if (grepl("Error", eval(parse(text = paste0('rv$Subgroup_',j-28,'[[i]][1]')))) == TRUE) {
                        eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("The data is sparse; therefore, subgroup analysis was not performed")')))
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                        'as.character("The data is sparse; therefore, subgroup analysis was not performed")'
                                                 )
                        )
                        rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                               rv$OldColumnNames[j], 
                                                               ': The data is sparse; therefore, subgroup analysis was not performed',
                                                               ifelse(j==ncol(rv$InputData),'','\n')
                        )
                        eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                               paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],'\nThe data is sparse; therefore, subgroup analysis was not performed'),'")'
                        )))
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                        'f.PlotText("',
                                                        rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],
                                                        '\nThe data is sparse; therefore, subgroup analysis was not performed',
                                                        '")'
                                                 )
                        )
                      } else {
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- update(',
                                                        'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                        'subgroup = ', rv$OutcomeNamesForCodes[i],'[,',j,']',',',
                                                        'common=FALSE',
                                                        ')'
                                                 )
                        )
                        rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                               rv$OldColumnNames[j], 
                                                               ': Test for subgroup differences p-value: ' ,
                                                               ifelse(eval(parse(text = paste0('rv$Subgroup_',j-28,'[[i]]$pval.Q.b.random'))) < 0.0001,
                                                                      '<0.0001',
                                                                      round(eval(parse(text = paste0('rv$Subgroup_',j-28,'[[i]]$pval.Q.b.random'))),4)
                                                               ),
                                                               ifelse(j==ncol(rv$InputData),'','\n')
                        )
                        eval(parse(text=
                                     paste0('rv$plotSubA',j-28,'[[i]] <- f.ForestPlot.SubA(rv$Subgroup_',j-28,'[[i]], rv$outcome.summary_Int[i,2], rv$OldColumnNames[j])')
                        ))
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                        'f.ForestPlot.SubA(',
                                                        'Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],',',
                                                        '"', rv$outcome.summary_Int[i,2],'"',',', 
                                                        '"', rv$OldColumnNames[j], '"',
                                                        ')'
                                                 )
                        )
                        png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_") ,'_Moderator_',j-28,'_ForestPlot.png'), width=960, 
                            height=(20 * (10 + nrow(rv$df_Outcome[[i]]) + 3.3*nlevels(rv$df_Outcome[[i]][,j])+1)), units="px")
                        eval(parse(text=
                                     paste0('f.ForestPlot.SubA(rv$Subgroup_',j-28,'[[i]], 
                                          rv$outcome.summary_Int[i,2],
                                          rv$OldColumnNames[j]
                                          )
                                          ')
                        ))
                        dev.off()
                      } 
                    }
                  }
                }
              }
              
              # Analysis for this outcome type ends here
            } else if (tolower(rv$outcome.summary_Int[i,2]) == "continuous"){
              if (!TRUE %in% sapply(rv$df_Outcome[[i]][,5:10],is.infinite)){
                # For continuous outcomes it is metacont
                rv$MA[[i]] <- metacont(
                  rv$df_Outcome[[i]][,5],
                  rv$df_Outcome[[i]][,7],
                  rv$df_Outcome[[i]][,8],
                  rv$df_Outcome[[i]][,6],
                  rv$df_Outcome[[i]][,9],
                  rv$df_Outcome[[i]][,10],
                  data = rv$df_Outcome[[i]],
                  studlab = rv$df_Outcome[[i]][,4],
                  common = (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),
                  text.common = "Fixed effect model",
                  text.w.common = "fixed",
                  sm = rv$EffectMeasure,
                  method.smd = ifelse(rv$EffectMeasure == "SMD",as.character(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,8],"_")[[1]][1]),"Hedges"),
                  exact.smd = ifelse(rv$EffectMeasure == "SMD",as.logical(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,8],"_")[[1]][2]),FALSE),
                  overall = (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),
                  method.random.ci = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),
                  adhoc.hakn.ci = "se",
                  method.predict = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"),
                  adhoc.hakn.pi = "se",
                  prediction = (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),
                  outclab = rv$outcome.summary_Int[i,1],
                  label.e = rv$InputData[2,28],
                  label.c = rv$InputData[4,28],
                  label.left = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])),
                  label.right = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28]))
                )
                rv$GenerateCode <- rbind(rv$GenerateCode, 
                                         paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- metacont(',
                                                rv$OutcomeNamesForCodes[i],'[,5],',
                                                rv$OutcomeNamesForCodes[i],'[,7],',
                                                rv$OutcomeNamesForCodes[i],'[,8],',
                                                rv$OutcomeNamesForCodes[i],'[,6],',
                                                rv$OutcomeNamesForCodes[i],'[,9],',
                                                rv$OutcomeNamesForCodes[i],'[,10],',
                                                'data = ', rv$OutcomeNamesForCodes[i],',',
                                                'studlab = ', rv$OutcomeNamesForCodes[i],'[,4],',
                                                'common = ', (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),',',
                                                'text.common = "Fixed effect model", text.w.common = "fixed",',
                                                'sm = "', rv$EffectMeasure, '",',
                                                'method.smd = "', ifelse(rv$EffectMeasure == "SMD",as.character(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,8],"_")[[1]][1]),"Hedges"), '",',
                                                'exact.smd = "', ifelse(rv$EffectMeasure == "SMD",as.logical(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,8],"_")[[1]][2]),FALSE), '",',
                                                'overall = ', (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),',',
                                                'method.random.ci ="', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"), '",',
                                                'adhoc.hakn.ci ="se",',
                                                'method.predict ="', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"), '",',
                                                'adhoc.hakn.pi ="se",',
                                                'prediction = ', (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),',',
                                                'outclab = "', rv$outcome.summary_Int[i,1], '",',
                                                'label.e = "', rv$InputData[2,28], '",',
                                                'label.c = "', rv$InputData[4,28], '",',
                                                'label.left = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])), '",',
                                                'label.right = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28])), '"',
                                                ')'
                                         )
                )
                rv$outcome.summary_Int[i,8] <- paste0(
                  ifelse(rv$MA[[i]]$sm %in% c("OR","RR","HR","ROM"), round(exp(rv$MA[[i]]$TE.random),2),round(rv$MA[[i]]$TE.random,2)),
                  ' (95% CI ',
                  ifelse(rv$MA[[i]]$sm %in% c("OR","RR","HR","ROM"), round(exp(rv$MA[[i]]$lower.random),2),round(rv$MA[[i]]$lower.random,2)),
                  ' to ',
                  ifelse(rv$MA[[i]]$sm %in% c("OR","RR","HR","ROM"), round(exp(rv$MA[[i]]$upper.random),2),round(rv$MA[[i]]$upper.random,2)),
                  ')'
                )
                
                rv$outcome.summary_Int[i,9] <- rv$MA[[i]]$I2 
                rv$outcome.summary_Int[i,10] <- rv$MA[[i]]$tau2 
                
                # Metabias
                if(nrow(rv$df_Outcome[[i]]) >=rv$Metabias.Min){
                  rv$MetaBias[[i]] <- metabias(
                    rv$MA[[i]],
                    method.bias = rv$UploadedMetaAnalysisPlan_Int[i,11],
                    k.min = rv$Metabias.Min,
                    plotit = FALSE
                  )
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('Funnel_',rv$OutcomeNamesForCodes[i],' <- metabias(',
                                                  'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                  'method.bias = "', rv$UploadedMetaAnalysisPlan_Int[i,11],'",',
                                                  'k.min = ', rv$Metabias.Min,',',
                                                  'plotit = FALSE',
                                                  ')'
                                           )
                  )
                  rv$outcome.summary_Int[i,11] <- round(rv$MetaBias[[i]]$pval,4) 
                } else {
                  rv$MetaBias[[i]] <- paste0('Not performed as fewer than ', rv$Metabias.Min ,' trials')
                  
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('Funnel_',rv$OutcomeNamesForCodes[i],' <- ',
                                                  '"Not performed as fewer than ', rv$Metabias.Min ,' trials"'
                                           )
                  )
                  
                  rv$outcome.summary_Int[i,11] <- paste0('Not performed as fewer than ', rv$Metabias.Min ,' trials')
                }
                
                # If Mean or SD has been imputed
                if (nlevels(rv$df_Outcome[[i]][,13])>0) {
                  rv$SA[[i]] <- metacont(
                    rv$df_Outcome[[i]][,5],
                    rv$df_Outcome[[i]][,7],
                    rv$df_Outcome[[i]][,8],
                    rv$df_Outcome[[i]][,6],
                    rv$df_Outcome[[i]][,9],
                    rv$df_Outcome[[i]][,10],
                    data = rv$df_Outcome[[i]],
                    subset = which(is.na(rv$df_Outcome[[i]][,13])),
                    studlab = rv$df_Outcome[[i]][,4],
                    common = (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),
                    text.common = "Fixed effect model",
                    text.w.common = "fixed",
                    sm = rv$EffectMeasure,
                    method.smd = ifelse(rv$EffectMeasure == "SMD",as.character(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,8],"_")[[1]][1]),"Hedges"),
                    exact.smd = ifelse(rv$EffectMeasure == "SMD",as.logical(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,8],"_")[[1]][2]),FALSE),
                    overall = (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),
                    method.random.ci = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),
                    adhoc.hakn.ci = "se",
                    method.predict = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"),
                    adhoc.hakn.pi = "se",
                    prediction = (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),
                    outclab = rv$outcome.summary_Int[i,1],
                    label.e = rv$InputData[2,28],
                    label.c = rv$InputData[4,28],
                    label.left = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])),
                    label.right = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28]))
                  )
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],' <- metacont(',
                                                  rv$OutcomeNamesForCodes[i],'[,5],',
                                                  rv$OutcomeNamesForCodes[i],'[,7],',
                                                  rv$OutcomeNamesForCodes[i],'[,8],',
                                                  rv$OutcomeNamesForCodes[i],'[,6],',
                                                  rv$OutcomeNamesForCodes[i],'[,9],',
                                                  rv$OutcomeNamesForCodes[i],'[,10],',
                                                  'data = ', rv$OutcomeNamesForCodes[i],',',
                                                  'subset = which(is.na(', rv$OutcomeNamesForCodes[i],'[,13]))',',',
                                                  'studlab = ', rv$OutcomeNamesForCodes[i],'[,4],',
                                                  'common = ', (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),',',
                                                  'text.common = "Fixed effect model", text.w.common = "fixed",',
                                                  'sm = "', rv$EffectMeasure, '",',
                                                  'method.smd = "', ifelse(rv$EffectMeasure == "SMD",as.character(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,8],"_")[[1]][1]),"Hedges"), '",',
                                                  'exact.smd = "', ifelse(rv$EffectMeasure == "SMD",as.logical(strsplit(rv$UploadedMetaAnalysisPlan_Int[i,8],"_")[[1]][2]),FALSE), '",',
                                                  'overall = ', (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),',',
                                                  'method.random.ci ="', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"), '",',
                                                  'adhoc.hakn.ci ="se",',
                                                  'method.predict ="', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"), '",',
                                                  'adhoc.hakn.pi ="se",',
                                                  'prediction = ', (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),',',
                                                  'outclab = "', rv$outcome.summary_Int[i,1], '",',
                                                  'label.e = "', rv$InputData[2,28], '",',
                                                  'label.c = "', rv$InputData[4,28], '",',
                                                  'label.left = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])), '",',
                                                  'label.right = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28])), '"',
                                                  ')'
                                           )
                  )
                  rv$outcome.summary_Int[i,12] <- paste0(
                    round(rv$SA[[i]]$TE.random,2),
                    ' (95% CI ',
                    round(rv$SA[[i]]$lower.random,2),
                    ' to ',
                    round(rv$SA[[i]]$upper.random,2),
                    ')'
                  )
                } else {
                  rv$SA[[i]] <- as.character("No imputation of either mean or SD")
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],' <- as.character("No imputation of either mean or SD")'
                                           )
                  )
                  rv$outcome.summary_Int[i,12] <- "No imputation of either mean or SD"
                }
                
                # Metaregression
                if(!is.na(rv$UploadedMetaAnalysisPlan_Int[i,15])) {
                  rv$SelectedCovariates <- strsplit(rv$UploadedMetaAnalysisPlan_Int[i,15],", ")
                  rv$SelectedCovariatesColumns[[i]] <- as.vector(match(rv$SelectedCovariates[[1]], rv$OldColumnNames))
                  if(length(rv$SelectedCovariatesColumns[[i]])>1){
                    rv$SelectedCovariatesColumnsSubgroup[[i]] <- rv$SelectedCovariatesColumns[[i]][!sapply(rv$InputData[,rv$SelectedCovariatesColumns[[i]]],is.numeric)]  
                  } else {
                    rv$SelectedCovariatesColumnsSubgroup[[i]] <- ifelse(is.numeric(rv$InputData[,rv$SelectedCovariatesColumns[[i]]]),NA,rv$SelectedCovariatesColumns[[i]])
                  }
                  rv$MetaRegText[[i]] <- paste0(rv$NewColumnNames[rv$SelectedCovariatesColumns[[i]]],collapse = ' + ')
                  rv$MetaReg[[i]] <- 
                    suppressWarnings({
                      suppressMessages({
                        try(
                          metareg(rv$MA[[i]],rv$MetaRegText[[i]], intercept = FALSE)
                        )
                      })
                    })
                  if (grepl("Error", rv$MetaReg[[i]][1]) == TRUE) {
                    rv$MetaReg[[i]] <- as.character("Error in metaregression \n(usually due to too many moderators in the model or sparse data)")
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0('MetaReg_',rv$OutcomeNamesForCodes[i],' <- ',
                                                    'as.character("Error in metaregression \n(usually due to too many moderators in the model or sparse data)")'
                                             )
                    )
                    rv$outcome.summary_Int[i,13] <- "Error in metaregression (usually due to too many moderators in the model or sparse data)"
                  } else {
                    
                    # To ensure that the correct variable values are used for the covariates, store them as global variables again
                    for (j in 29:ncol(rv$df_Outcome[[i]])){
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0(colnames(rv$df_Outcome[[i]])[j], ' <- as.vector(',
                                                      rv$OutcomeNamesForCodes[i],'[,',j,'])'
                                               )
                      )
                    }
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0('MetaReg_',rv$OutcomeNamesForCodes[i],' <- suppressWarnings({suppressMessages({',
                                                    'metareg(', 
                                                    'MetaAnalysis_', rv$OutcomeNamesForCodes[i],',',
                                                    rv$MetaRegText[[i]],',',
                                                    'intercept = FALSE',
                                                    ')
                                                    })
                                                    })'
                                             )
                    )
                    rv$outcome.summary_Int[i,13] <- paste0(
                      'Omnibus Test of Moderators (Does adding the moderator(s) improve the model fit?): ',
                      round(rv$MetaReg[[i]]$QMp,4), 
                      '\n',
                      paste0(
                        dimnames(rv$MetaReg[[i]]$b)[[1]],': ',
                        round(rv$MetaReg[[i]]$b,4), 
                        ' (95% CI ',round(rv$MetaReg[[i]]$ci.lb,4),
                        ' to ', round(rv$MetaReg[[i]]$ci.ub,4), 
                        '); p-value: ',
                        round(rv$MetaReg[[i]]$pval,4),
                        collapse = '\n'
                      ),
                      collapse =""
                    )
                    # Now replace the variable names
                    for (j in 29:ncol(rv$InputData)){
                      rv$outcome.summary_Int[i,13] <- str_replace_all(
                        str_replace_all(rv$outcome.summary_Int[i,13], 
                                        str_replace_all(
                                          str_replace_all(rv$NewColumnNames[j],regex('_Level_', ignore_case = FALSE),''),
                                          regex('_per.unit.increase', ignore_case = FALSE),''),
                                        rv$OldColumnNames[j]
                        ),
                        regex('_per.unit.increase', ignore_case = FALSE),
                        '_per unit increase')
                    }
                  }
                } else {
                  rv$SelectedCovariatesColumns[[i]] <- NA
                  rv$SelectedCovariatesColumnsSubgroup[[i]] <- NA
                  rv$MetaRegText[[i]] <- NA
                  rv$MetaReg[[i]] <- as.character("No variables selected for metaregression")
                  rv$outcome.summary_Int[i,13] <- "No variables selected for metaregression"
                }
                
                # Subgroup analysis
                if (ncol(rv$InputData)>28){
                  for (j in 29:ncol(rv$InputData)){
                    if (any(c(is.na(rv$SelectedCovariatesColumns[[i]]),!j %in% rv$SelectedCovariatesColumns[[i]]))) {
                      eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("This variable was not selected")')))
                      
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                      'as.character("This variable was not selected")'
                                               )
                      )
                      
                      rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                             rv$OldColumnNames[j], 
                                                             ': This variable was not selected',
                                                             ifelse(j==ncol(rv$InputData),'','\n')
                      )
                      eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                             paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],': This variable was not selected'),'")'
                      )))
                      
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                      'f.PlotText("',
                                                      rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],
                                                      ': This variable was not selected',
                                                      '")'
                                               )
                      )
                    } else {
                      if (any(c(is.na(rv$SelectedCovariatesColumnsSubgroup[[i]]),!j %in% rv$SelectedCovariatesColumnsSubgroup[[i]]))) {
                        eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("This is not a categorical variable")')))
                        
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                        'as.character("This is not a categorical variable")'
                                                 )
                        )
                        
                        rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                               rv$OldColumnNames[j], 
                                                               ': This is not a categorical variable',
                                                               ifelse(j==ncol(rv$InputData),'','\n')
                        )
                        eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                               paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],'This is not a categorical variable'),'")'
                        )))
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                        'f.PlotText("',
                                                        rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],
                                                        ': This is not a categorical variable',
                                                        '")'
                                                 )
                        )
                      } else {
                        eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- suppressWarnings({suppressMessages({try(
                                             update(rv$MA[[i]],subgroup = rv$df_Outcome[[i]][,',j,'],common=FALSE)
                                             )
                                               })
                                               })'
                        )))
                        if (grepl("Error", eval(parse(text = paste0('rv$Subgroup_',j-28,'[[i]][1]')))) == TRUE) {
                          eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("The data is sparse; therefore, subgroup analysis was not performed")')))
                          
                          rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                   paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                          'as.character("The data is sparse; therefore, subgroup analysis was not performed")'
                                                   )
                          )
                          
                          rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                                 rv$OldColumnNames[j], 
                                                                 ': The data is sparse; therefore, subgroup analysis was not performed',
                                                                 ifelse(j==ncol(rv$InputData),'','\n')
                          )
                          eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                                 paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],'\nThe data is sparse; therefore, subgroup analysis was not performed'),'")'
                          )))
                          rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                   paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                          'f.PlotText("',
                                                          rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],
                                                          '\nThe data is sparse; therefore, subgroup analysis was not performed',
                                                          '")'
                                                   )
                          )
                        } else {
                          rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                   paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- update(',
                                                          'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                          'subgroup = ', rv$OutcomeNamesForCodes[i],'[,',j,']',',',
                                                          'common=FALSE',
                                                          ')'
                                                   )
                          )
                          rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                                 rv$OldColumnNames[j], 
                                                                 ': Test for subgroup differences p-value: ' ,
                                                                 ifelse(eval(parse(text = paste0('rv$Subgroup_',j-28,'[[i]]$pval.Q.b.random'))) < 0.0001,
                                                                        '<0.0001',
                                                                        round(eval(parse(text = paste0('rv$Subgroup_',j-28,'[[i]]$pval.Q.b.random'))),4)
                                                                 ),
                                                                 ifelse(j==ncol(rv$InputData),'','\n')
                          )
                          eval(parse(text=
                                       paste0('rv$plotSubA',j-28,'[[i]] <- f.ForestPlot.SubA(rv$Subgroup_',j-28,'[[i]], rv$outcome.summary_Int[i,2], rv$OldColumnNames[j])')
                          ))
                          rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                   paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                          'f.ForestPlot.SubA(',
                                                          'Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],',',
                                                          '"', rv$outcome.summary_Int[i,2],'"',',', 
                                                          '"', rv$OldColumnNames[j], '"',
                                                          ')'
                                                   )
                          )
                          png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_"),'_Moderator_',j-28,'_ForestPlot.png'), width=960, 
                              height=(20 * (10 + nrow(rv$df_Outcome[[i]]) + 3.3*nlevels(rv$df_Outcome[[i]][,j])+1)), units="px")
                          eval(parse(text=
                                       paste0('f.ForestPlot.SubA(rv$Subgroup_',j-28,'[[i]], 
                                          rv$outcome.summary_Int[i,2],
                                          rv$OldColumnNames[j]
                                          )
                                          ')
                          ))
                          dev.off()
                        } 
                      }
                    }
                  }
                }
              } else {
                rv$MA[[i]] <- as.character('Meta-analysis was not performed because minimum information required for analysis was missing')
                rv$outcome.summary_Int[i,8] <- 'Meta-analysis was not performed because minimum information required for analysis was missing'
                rv$outcome.summary_Int[i,9] <- 'Not applicable' 
                rv$outcome.summary_Int[i,10] <- 'Not applicable'
                rv$MetaBias[[i]] <- as.character('Not applicable')
                rv$outcome.summary_Int[i,11] <- 'Not applicable'
                rv$SA[[i]] <- as.character('Not applicable')
                rv$outcome.summary_Int[i,12] <- 'Not applicable'
                rv$MetaReg[[i]] <- as.character('Not applicable')
                rv$outcome.summary_Int[i,13] <- 'Not applicable'
                rv$outcome.summary_Int[i,14] <- 'Not applicable'
                if (ncol(rv$InputData)>28){
                  for (j in 29:ncol(rv$InputData)){
                    eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("Meta-analysis was not performed")')))
                    eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                           paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],': Meta-analysis was not performed'),'")'
                    )))
                    
                  }
                }
              }
              # Analysis for this outcome type ends here
            } else {
              # For count, time, summary_difference, and summary_ratio
              rv$MA[[i]] <- metagen(
                rv$df_Outcome[[i]][,7],
                rv$df_Outcome[[i]][,8],
                n.e = rv$df_Outcome[[i]][,5],
                n.c = rv$df_Outcome[[i]][,6],
                data = rv$df_Outcome[[i]],
                studlab = rv$df_Outcome[[i]][,4],
                common = (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),
                text.common = "Fixed effect model",
                text.w.common = "fixed",
                sm = rv$EffectMeasure,
                overall = (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),
                method.random.ci = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"),
                method.predict = ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"),
                prediction = (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),
                outclab = rv$outcome.summary_Int[i,1],
                label.e = rv$InputData[2,28],
                label.c = rv$InputData[4,28],
                label.left = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])),
                label.right = ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28]))
              )
              rv$GenerateCode <- rbind(rv$GenerateCode, 
                                       paste0('MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- metagen(',
                                              rv$OutcomeNamesForCodes[i],'[,7],',
                                              rv$OutcomeNamesForCodes[i],'[,8],',
                                              'n.e = ', rv$OutcomeNamesForCodes[i],'[,5],',
                                              'n.c = ', rv$OutcomeNamesForCodes[i],'[,6],',
                                              'data = ', rv$OutcomeNamesForCodes[i],',',
                                              'studlab = ', rv$OutcomeNamesForCodes[i],'[,4],',
                                              'common = ', (rv$UploadedMetaAnalysisPlan_Int[i,5] != "No"),',',
                                              'text.common = "Fixed effect model", text.w.common = "fixed",',
                                              'sm = "', rv$EffectMeasure, '",',
                                              'overall = ', (rv$UploadedMetaAnalysisPlan_Int[i,9]!= "No"),',',
                                              'method.random.ci ="', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","classic"), '",',
                                              'method.predict ="', ifelse(rv$UploadedMetaAnalysisPlan_Int[i,7] != "No","HK","HTS"), '",',
                                              'prediction = ', (rv$UploadedMetaAnalysisPlan_Int[i,6] != "No"),',',
                                              'outclab = "', rv$outcome.summary_Int[i,1], '",',
                                              'label.e = "', rv$InputData[2,28], '",',
                                              'label.c = "', rv$InputData[4,28], '",',
                                              'label.left = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[2,28]),paste0("Favours ", rv$InputData[4,28])), '",',
                                              'label.right = "', ifelse(tolower(rv$df_Outcome[[i]][1,3]) == "worse", paste0("Favours ",rv$InputData[4,28]),paste0("Favours ", rv$InputData[2,28])), '"',
                                              ')'
                                       )
              )
              rv$outcome.summary_Int[i,8] <- paste0(
                ifelse(rv$MA[[i]]$sm %in% c("OR","RR","HR","ROM"), round(exp(rv$MA[[i]]$TE.random),2),round(rv$MA[[i]]$TE.random,2)),
                ' (95% CI ',
                ifelse(rv$MA[[i]]$sm %in% c("OR","RR","HR","ROM"), round(exp(rv$MA[[i]]$lower.random),2),round(rv$MA[[i]]$lower.random,2)),
                ' to ',
                ifelse(rv$MA[[i]]$sm %in% c("OR","RR","HR","ROM"), round(exp(rv$MA[[i]]$upper.random),2),round(rv$MA[[i]]$upper.random,2)),
                ')'
              )
              rv$outcome.summary_Int[i,9] <- rv$MA[[i]]$I2 
              rv$outcome.summary_Int[i,10] <- rv$MA[[i]]$tau2 
              
              # Metabias
              if(nrow(rv$df_Outcome[[i]]) >=rv$Metabias.Min){
                rv$MetaBias[[i]] <- metabias(
                  rv$MA[[i]],
                  method.bias = rv$UploadedMetaAnalysisPlan_Int[i,11],
                  k.min = rv$Metabias.Min,
                  plotit = FALSE
                )
                rv$GenerateCode <- rbind(rv$GenerateCode, 
                                         paste0('Funnel_',rv$OutcomeNamesForCodes[i],' <- metabias(',
                                                'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                'method.bias = "', rv$UploadedMetaAnalysisPlan_Int[i,11],'",',
                                                'k.min = ', rv$Metabias.Min,',',
                                                'plotit = FALSE',
                                                ')'
                                         )
                )
                rv$outcome.summary_Int[i,11] <- round(rv$MetaBias[[i]]$pval,4) 
              } else {
                rv$MetaBias[[i]] <- paste0('Not performed as fewer than ', rv$Metabias.Min ,' trials')
                
                rv$GenerateCode <- rbind(rv$GenerateCode, 
                                         paste0('Funnel_',rv$OutcomeNamesForCodes[i],' <- ',
                                                '"Not performed as fewer than ', rv$Metabias.Min ,' trials"'
                                         )
                )
                rv$outcome.summary_Int[i,11] <- paste0('Not performed as fewer than ', rv$Metabias.Min ,' trials')
              }
              
              # Sensitivity analysis for missing data
              rv$SA[[i]] <- as.character("Not performed as only summary measures were provided")
              rv$outcome.summary_Int[i,12] <- "Not performed as only summary measures were provided"
              
              # Metaregression
              if(!is.na(rv$UploadedMetaAnalysisPlan_Int[i,15])) {
                rv$SelectedCovariates <- strsplit(rv$UploadedMetaAnalysisPlan_Int[i,15],", ")
                rv$SelectedCovariatesColumns[[i]] <- as.vector(match(rv$SelectedCovariates[[1]], rv$OldColumnNames))
                if(length(rv$SelectedCovariatesColumns[[i]])>1){
                  rv$SelectedCovariatesColumnsSubgroup[[i]] <- rv$SelectedCovariatesColumns[[i]][!sapply(rv$InputData[,rv$SelectedCovariatesColumns[[i]]],is.numeric)]  
                } else {
                  rv$SelectedCovariatesColumnsSubgroup[[i]] <- ifelse(is.numeric(rv$InputData[,rv$SelectedCovariatesColumns[[i]]]),NA,rv$SelectedCovariatesColumns[[i]])
                }
                rv$MetaRegText[[i]] <- paste0(rv$NewColumnNames[rv$SelectedCovariatesColumns[[i]]],collapse = ' + ')
                rv$MetaReg[[i]] <- 
                  suppressWarnings({
                    suppressMessages({
                      try(
                        metareg(rv$MA[[i]],rv$MetaRegText[[i]], intercept = FALSE)
                      )
                    })
                  })
                if (grepl("Error", rv$MetaReg[[i]][1]) == TRUE) {
                  rv$MetaReg[[i]] <- as.character("Error in metaregression \n(usually due to too many moderators in the model or sparse data)")
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('MetaReg_',rv$OutcomeNamesForCodes[i],' <- ',
                                                  'as.character("Error in metaregression \n(usually due to too many moderators in the model or sparse data)")'
                                           )
                  )
                  rv$outcome.summary_Int[i,13] <- "Error in metaregression (usually due to too many moderators in the model or sparse data)"
                } else {
                  # To ensure that the correct variable values are used for the covariates, store them as global variables again
                  for (j in 29:ncol(rv$df_Outcome[[i]])){
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0(colnames(rv$df_Outcome[[i]])[j], ' <- as.vector(',
                                                    rv$OutcomeNamesForCodes[i],'[,',j,'])'
                                             )
                    )
                  }
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('MetaReg_',rv$OutcomeNamesForCodes[i],' <- suppressWarnings({suppressMessages({',
                                                  'metareg(', 
                                                  'MetaAnalysis_', rv$OutcomeNamesForCodes[i],',',
                                                  rv$MetaRegText[[i]],',',
                                                  'intercept = FALSE',
                                                  ')
                                                  })
                                                  })'
                                           )
                  )
                  rv$outcome.summary_Int[i,13] <- paste0(
                    'Omnibus Test of Moderators (Does adding the moderator(s) improve the model fit?) p-value: ',
                    ifelse(rv$MetaReg[[i]]$QMp <0.0001,'<0.001',round(rv$MetaReg[[i]]$QMp,4)),
                    '\n',
                    paste0(
                      dimnames(rv$MetaReg[[i]]$b)[[1]],': ',
                      round(rv$MetaReg[[i]]$b,4), 
                      ' (95% CI ',round(rv$MetaReg[[i]]$ci.lb,4),
                      ' to ', round(rv$MetaReg[[i]]$ci.ub,4), 
                      '); p-value: ',
                      ifelse(rv$MetaReg[[i]]$pval <0.0001,'<0.001',round(rv$MetaReg[[i]]$pval,4)),
                      collapse = '\n'
                    ),
                    collapse =""
                  )
                  # Now replace the variable names
                  for (j in 29:ncol(rv$InputData)){
                    rv$outcome.summary_Int[i,13] <- str_replace_all(
                      str_replace_all(rv$outcome.summary_Int[i,13], 
                                      str_replace_all(
                                        str_replace_all(rv$NewColumnNames[j],regex('_Level_', ignore_case = FALSE),''),
                                        regex('_per.unit.increase', ignore_case = FALSE),''),
                                      rv$OldColumnNames[j]
                      ),
                      regex('_per.unit.increase', ignore_case = FALSE),
                      '_per unit increase')
                  }
                }
              } else {
                rv$SelectedCovariatesColumns[[i]] <- NA
                rv$SelectedCovariatesColumnsSubgroup[[i]] <- NA
                rv$MetaRegText[[i]] <- NA
                rv$MetaReg[[i]] <- as.character("No variables selected for metaregression")
                rv$outcome.summary_Int[i,13] <- "No variables selected for metaregression"
              }
              # Subgroup analysis
              if (ncol(rv$InputData)>28){
                for (j in 29:ncol(rv$InputData)){
                  if (any(c(is.na(rv$SelectedCovariatesColumns[[i]]),!j %in% rv$SelectedCovariatesColumns[[i]]))) {
                    eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("This variable was not selected")')))
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                    'as.character("This variable was not selected")'
                                             )
                    )
                    rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                           rv$OldColumnNames[j], 
                                                           ': This variable was not selected',
                                                           ifelse(j==ncol(rv$InputData),'','\n')
                    )
                    eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                           paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],': This variable was not selected'),'")'
                    )))
                    rv$GenerateCode <- rbind(rv$GenerateCode, 
                                             paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                    'f.PlotText("',
                                                    rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],
                                                    ': This variable was not selected',
                                                    '")'
                                             )
                    )
                  } else {
                    if (any(c(is.na(rv$SelectedCovariatesColumnsSubgroup[[i]]),!j %in% rv$SelectedCovariatesColumnsSubgroup[[i]]))) {
                      eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("This is not a categorical variable")')))
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                      'as.character("This is not a categorical variable")'
                                               )
                      )
                      rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                             rv$OldColumnNames[j], 
                                                             ': This is not a categorical variable',
                                                             ifelse(j==ncol(rv$InputData),'','\n')
                      )
                      eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                             paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],'This is not a categorical variable'),'")'
                      )))
                      rv$GenerateCode <- rbind(rv$GenerateCode, 
                                               paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                      'f.PlotText("',
                                                      rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],
                                                      ': This is not a categorical variable',
                                                      '")'
                                               )
                      )
                    } else {
                      eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- suppressWarnings({suppressMessages({try(
                                             update(rv$MA[[i]],subgroup = rv$df_Outcome[[i]][,',j,'],common=FALSE)
                                             )
                                             })
                                             })'
                      )))
                      if (grepl("Error", eval(parse(text = paste0('rv$Subgroup_',j-28,'[[i]][1]')))) == TRUE) {
                        eval(parse(text=paste0('rv$Subgroup_',j-28,'[[i]] <- as.character("The data is sparse; therefore, subgroup analysis was not performed")')))
                        
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                        'as.character("The data is sparse; therefore, subgroup analysis was not performed")'
                                                 )
                        )
                        
                        rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                               rv$OldColumnNames[j], 
                                                               ': The data is sparse; therefore, subgroup analysis was not performed',
                                                               ifelse(j==ncol(rv$InputData),'','\n')
                        )
                        eval(parse(text=paste0('rv$plotSubA',j-28,'[[i]] <- f.PlotText("',
                                               paste0(rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],'\nThe data is sparse; therefore, subgroup analysis was not performed'),'")'
                        )))
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                        'f.PlotText("',
                                                        rv$outcome.summary_Int[i,1],'\n',rv$OldColumnNames[j],
                                                        '\nThe data is sparse; therefore, subgroup analysis was not performed',
                                                        '")'
                                                 )
                        )
                      } else {
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- update(',
                                                        'MetaAnalysis_',rv$OutcomeNamesForCodes[i],',',
                                                        'subgroup = ', rv$OutcomeNamesForCodes[i],'[,',j,']',',',
                                                        'common=FALSE',
                                                        ')'
                                                 )
                        )
                        rv$outcome.summary_Int[i,14] <- paste0(rv$outcome.summary_Int[i,14],
                                                               rv$OldColumnNames[j], 
                                                               ': Test for subgroup differences p-value: ' ,
                                                               ifelse(eval(parse(text = paste0('rv$Subgroup_',j-28,'[[i]]$pval.Q.b.random'))) < 0.0001,
                                                                      '<0.0001',
                                                                      round(eval(parse(text = paste0('rv$Subgroup_',j-28,'[[i]]$pval.Q.b.random'))),4)
                                                               ),
                                                               ifelse(j==ncol(rv$InputData),'','\n')
                        )
                        eval(parse(text=
                                     paste0('rv$plotSubA',j-28,'[[i]] <- f.ForestPlot.SubA(rv$Subgroup_',j-28,'[[i]], rv$outcome.summary_Int[i,2], rv$OldColumnNames[j])')
                        ))
                        rv$GenerateCode <- rbind(rv$GenerateCode, 
                                                 paste0('Plot_Subgroup_',str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],' <- ',
                                                        'f.ForestPlot.SubA(',
                                                        'Subgroup_', str_replace_all(str_replace_all(rv$NewColumnNames[j],'_Level_',''),'_per.unit.increase',''),'_',rv$OutcomeNamesForCodes[i],',',
                                                        '"', rv$outcome.summary_Int[i,2],'"',',', 
                                                        '"', rv$OldColumnNames[j], '"',
                                                        ')'
                                                 )
                        )
                        png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_"),'_Moderator_',j-28,'_ForestPlot.png'), width=960, 
                            height=(20 * (10 + nrow(rv$df_Outcome[[i]]) + 3.3*nlevels(rv$df_Outcome[[i]][,j])+1)), units="px")
                        eval(parse(text=
                                     paste0('f.ForestPlot.SubA(rv$Subgroup_',j-28,'[[i]], 
                                          rv$outcome.summary_Int[i,2],
                                          rv$OldColumnNames[j]
                                          )
                                          ')
                        ))
                        dev.off()
                      } 
                    }
                  }
                }
              }
              # Analysis for this outcome type ends here
            }
          }
        }
        # Now create the plots and store this in a temporary location
        for (i in 1:nrow(rv$outcome.summary_Int)){
          incProgress(1/(2*nrow(rv$outcome.summary_Int)), detail = paste0('Creating plots of Outcome: ',i,' of ', nrow(rv$outcome.summary_Int), ' outcomes'))
          if (grepl("Error",
                    suppressWarnings({suppressMessages({
                      try(
                        funnel(rv$MA[[i]])[[1]][1]
                      )
                    })
                    })
          ) == TRUE){
            # Forest and funnel plots
            # If data is insufficient, then indicate this
            rv$plot1[[i]] <- f.PlotText('Because of sparse data, the plot was not created')
            rv$GenerateCode <- rbind(rv$GenerateCode, 
                                     paste0('Plot_MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- ',
                                            'f.PlotText("Because of sparse data, the plot was not created")'
                                     )
            )
            rv$plot2[[i]] <- f.PlotText('Because of sparse data, the plot was not created')
            rv$GenerateCode <- rbind(rv$GenerateCode, 
                                     paste0('Plot_Funnel_',rv$OutcomeNamesForCodes[i],' <- ',
                                            'f.PlotText("Because of sparse data, the plot was not created")'
                                     )
            )
            if (tolower(rv$outcome.summary_Int[i,2]) == "binary") {
              rv$plotSA1[[i]] <- f.PlotText('Because of sparse data, the plot was not created')
              rv$plotSA2[[i]] <- f.PlotText('Because of sparse data, the plot was not created')
              rv$plotSA3[[i]] <- f.PlotText('Because of sparse data, the plot was not created')
              rv$GenerateCode <- rbind(rv$GenerateCode, 
                                       paste0('Plot_SensitivityAnalysis_IMOR_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.PlotText("Because of sparse data, the plot was not created")'
                                       ),
                                       paste0('Plot_SensitivityAnalysis_BestWorst_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.PlotText("Because of sparse data, the plot was not created")'
                                       ),
                                       paste0('Plot_SensitivityAnalysis_WorstBest_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.PlotText("Because of sparse data, the plot was not created")'
                                       ),
                                       paste0('Plot_SensitivityAnalysis_MetaMiss_WorstBest_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.PlotText("Because of sparse data, the plot was not created")'
                                       ),
                                       paste0('Plot_SensitivityAnalysis_MetaMiss_Best_Worst',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.PlotText("Because of sparse data, the plot was not created")'
                                       )
              )
            } else if (tolower(rv$outcome.summary_Int[i,2]) == "continuous") {
              rv$plotSA1[[i]] <- f.PlotText('Because of sparse data, the plot was not created')
              rv$GenerateCode <- rbind(rv$GenerateCode, 
                                       paste0('Plot_SensitivityAnalysis_SD_Imputation_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.PlotText("Because of sparse data, the plot was not created")'
                                       )
              )
            }
            rv$plot3[[i]] <- f.PlotText('Because of sparse data, the plot was not created')
            rv$GenerateCode <- rbind(rv$GenerateCode, 
                                     paste0('Plot_Metaregression_',rv$OutcomeNamesForCodes[i],' <- ',
                                            'f.PlotText("Because of sparse data, the plot was not created")'
                                     )
            )
          } else{
            rv$plot1[[i]] <- f.ForestPlot(rv$MA[[i]], rv$outcome.summary_Int[i,2])
            rv$GenerateCode <- rbind(rv$GenerateCode, 
                                     paste0('Plot_MetaAnalysis_',rv$OutcomeNamesForCodes[i],' <- ',
                                            'f.ForestPlot(MetaAnalysis_',rv$OutcomeNamesForCodes[i],', "',rv$outcome.summary_Int[i,2],'")'
                                     )
            )
            png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_"),'_ForestPlot.png'), width=960, 
                height=(20 * (10 + nrow(rv$df_Outcome[[i]]))), units="px")
            f.ForestPlot(rv$MA[[i]], rv$outcome.summary_Int[i,2])
            dev.off()
            rv$plot2[[i]] <- f.FunnelPlot(rv$MA[[i]])
            rv$GenerateCode <- rbind(rv$GenerateCode, 
                                     paste0('Plot_Funnel_',rv$OutcomeNamesForCodes[i],' <- ',
                                            'f.FunnelPlot(MetaAnalysis_',rv$OutcomeNamesForCodes[i],')'
                                     )
            )
            png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_"),'_FunnelPlot.png'), width=600, 
                height=600, units="px")
            f.FunnelPlot(rv$MA[[i]])
            dev.off()
            # Sensitivity analysis
            if (tolower(rv$outcome.summary_Int[i,2]) == "binary") {
              rv$plotSA1[[i]] <- f.ForestPlot.SA(rv$SA[[i]][[1]],rv$outcome.summary_Int[i,2],1)
              rv$plotSA2[[i]] <- f.ForestPlot.SA(rv$SA[[i]][[2]],rv$outcome.summary_Int[i,2],2)
              rv$plotSA3[[i]] <- f.ForestPlot.SA(rv$SA[[i]][[3]],rv$outcome.summary_Int[i,2],3)
              rv$GenerateCode <- rbind(rv$GenerateCode, 
                                       paste0('Plot_SensitivityAnalysis_IMOR_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.ForestPlot.SA(SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],'[[1]],"',rv$outcome.summary_Int[i,2],'",1)'
                                       ),
                                       paste0('Plot_SensitivityAnalysis_BestWorst_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.ForestPlot.SA(SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],'[[2]],"',rv$outcome.summary_Int[i,2],'",2)'
                                       ),
                                       paste0('Plot_SensitivityAnalysis_WorstBest_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.ForestPlot.SA(SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],'[[3]],"',rv$outcome.summary_Int[i,2],'",3)'
                                       ),
                                       paste0('Plot_SensitivityAnalysis_MetaMiss_BestWorst_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.ForestPlot(SensitivityAnalysis_MetaMiss_BestWorst_',rv$OutcomeNamesForCodes[i],', "',rv$outcome.summary_Int[i,2],'")'
                                       ),
                                       paste0('Plot_SensitivityAnalysis_MetaMiss_WorstBest_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.ForestPlot(SensitivityAnalysis_MetaMiss_WorstBest_',rv$OutcomeNamesForCodes[i],', "',rv$outcome.summary_Int[i,2],'")'
                                       )
              )
              png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_"),'_IMOR_SA.png'), width=960, 
                  height=(20 * (10 + nrow(rv$df_Outcome[[i]]))), units="px")
              f.ForestPlot.SA(rv$SA[[i]][[1]],rv$outcome.summary_Int[i,2],1)
              dev.off()
              png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_"),'_BestWorst_SA.png'), width=960, 
                  height=(20 * (10 + nrow(rv$df_Outcome[[i]]))), units="px")
              f.ForestPlot.SA(rv$SA[[i]][[2]],rv$outcome.summary_Int[i,2],2)
              dev.off()
              png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_"),'_WorstBest_SA.png'), width=960, 
                  height=(20 * (10 + nrow(rv$df_Outcome[[i]]))), units="px")
              f.ForestPlot.SA(rv$SA[[i]][[3]],rv$outcome.summary_Int[i,2],3)
              dev.off()
            } else if (tolower(rv$outcome.summary_Int[i,2]) == "continuous") {
              if(is.character(rv$SA[[i]])){
                rv$plotSA1[[i]] <- f.PlotText(rv$SA[[i]])
                rv$GenerateCode <- rbind(rv$GenerateCode, 
                                         paste0('Plot_SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],' <- ',
                                                'f.PlotText(SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],')'
                                         )
                )
              } else {
                rv$plotSA1[[i]] <- f.ForestPlot.SA(rv$SA[[i]],rv$outcome.summary_Int[i,2],4)
                rv$GenerateCode <- rbind(rv$GenerateCode, 
                                         paste0('Plot_SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],' <- ',
                                                'f.ForestPlot.SA(SensitivityAnalysis_',rv$OutcomeNamesForCodes[i],',"',rv$outcome.summary_Int[i,2],'",4)'
                                         )
                )
                png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_"),'_SA.png'), width=960, 
                    height=(20 * (10 + nrow(rv$df_Outcome[[i]]))), units="px")
                f.ForestPlot.SA(rv$SA[[i]],rv$outcome.summary_Int[i,2],4)
                dev.off()
              }
            }
            # Bubble plot
            if (!is.na(rv$MetaRegText[[i]])) {
              if(is.character(rv$MetaReg[[i]][1])){
                rv$plot3[[i]] <- f.PlotText(rv$MetaReg[[i]][1])
                rv$GenerateCode <- rbind(rv$GenerateCode, 
                                         paste0('Plot_Metaregression_',rv$OutcomeNamesForCodes[i],' <- ',
                                                'f.PlotText(MetaReg_',rv$OutcomeNamesForCodes[i],'[1])'
                                         )
                )
              } else {
                if (rv$MetaReg[[i]]$int.only == TRUE){
                  rv$plot3[[i]] <- f.PlotText('No covariate in the model')
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('Plot_Metaregression_',rv$OutcomeNamesForCodes[i],' <- ',
                                                  'f.PlotText("No covariate in the model")'
                                           )
                  )
                } else {
                  rv$plot3[[i]] <- f.BubblePlot(rv$MetaReg[[i]], rv$MA[[i]])
                  rv$GenerateCode <- rbind(rv$GenerateCode, 
                                           paste0('Plot_Metaregression_',rv$OutcomeNamesForCodes[i],' <- ',
                                                  'f.BubblePlot(MetaReg_',rv$OutcomeNamesForCodes[i],',MetaAnalysis_',rv$OutcomeNamesForCodes[i],')'
                                           )
                  )
                  png(paste0(rv$StorageFolder,'/',path_sanitize(rv$outcome.summary_Int[i,1], replacement = "_"),'_BubblePlot.png'), width=600, 
                      height=600, units="px")
                  f.BubblePlot(rv$MetaReg[[i]], rv$MA[[i]])
                  dev.off()
                }
              }
            } else {
              rv$plot3[[i]] <- f.PlotText("No variables included for metaregression")
              rv$GenerateCode <- rbind(rv$GenerateCode, 
                                       paste0('Plot_Metaregression_',rv$OutcomeNamesForCodes[i],' <- ',
                                              'f.PlotText("No variables included for metaregression")'
                                       )
              )
            }
            # Subgroup analysis
            # This has been done within the outcome
          }
        }
        
        # The activity selector choices should increase and the choice should move to 5
        output$htmlTitle <- renderUI(HTML(MainHeaderSelection[5]))
        panelchoice = "panel5"
        updateTabsetPanel(inputId = "ActivitySelector", selected = panelchoice)
        updateRadioButtons(inputId = "Activity", choices = FirstSelection[1:5], selected = FirstSelection[5])
        
        output$Reset_MetaAnalysisPlan_Int_UI_2 <- renderUI(
          actionButton("Reset_MetaAnalysisPlan_Int_2", "Change option for meta-analysis plan (intervention review)")          
        )
        
        output$Header_ResultsTable_Int_UI <- renderUI(HTML('<h3 style = "font-size:24px; color:purple;"><b>Results</b></h3>'))
        output$OutcomeSummary_Int_UI <- renderUI(
          tableOutput("OutcomeSummary_Int")
        )
        output$ResultsTableDownload_Int_UI <- renderUI(downloadButton("outcome.summary_Int", HTML("Download the results table (intervention review)")))
        output$ResultsTable_Int_UI <- renderUI(
          tableOutput("ResultsTable_Int")
        )
        output$AllPlots_Download_Int_UI <- renderUI(downloadButton("AllPlots_Int", HTML("Download all the plots (intervention review)")))
      }) 
    }
  })
  
  observeEvent(input$Upload_RevMan5, {
    # Check if the file is txt, csv and import it
    # if the extension is not txt or csv do nothing more than a warning
    if ((!is.na(input$Upload_RevMan5$name)) & (input$Upload_RevMan5$name !="")){
      if (! any(c(file_ext(input$Upload_RevMan5$datapath)=="txt",file_ext(input$Upload_RevMan5$datapath)=="csv"))){
        output$htmlMsg1_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>Please upload
             a csv file or tab delimited file</b></h2>')
        )
        # If the file is empty, just say that it is empty
      } else if (file.size(input$Upload_RevMan5$datapath)<8){
        output$htmlMsg1_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>Please upload a file that contains data</b></h2>')
        )
      } else {
        # To avoid change in column names, use check.names=FALSE
        if (file_ext(input$Upload_RevMan5$datapath)=="txt"){
          rv$RevManData <-read.delim(input$Upload_RevMan5$datapath,header=TRUE, stringsAsFactors=FALSE, sep = '\t', check.names=FALSE)        
        } else if (file_ext(input$Upload_RevMan5$datapath)=="csv"){
          rv$RevManData <-read.csv(input$Upload_RevMan5$datapath, header=TRUE, stringsAsFactors=FALSE, sep = ',', check.names=FALSE)
        }
        # Now check whether column names match
        if (all(c(ncol(rv$RevManData) == 32,
                  any(c(
                    (!FALSE %in% (colnames(rv$RevManData)[1:32] == 
                                  c("Comparison Number", "Outcome Number", "Subgroup Number", 
                                    "Name", "Data Type", "Statistical Method", "Effect Measure", "Analysis Model", 
                                    "Events 1", "Mean 1", "SD 1", "Total 1", 
                                    "Events 2", "Mean 2", "SD 2", "Total 2", 
                                    "Effect Estimate", "SE", "CI Start", "CI End", "Weight", 
                                    "Q", "P(Q)", "I²(Q)", "Tau²", "Z", "P(Z)", 
                                    "Qint", "P(Qint)", "I²(Qint)", "df", "Year of study")
                                  
                    )),
                    (!FALSE %in% (colnames(rv$RevManData)[1:32] == 
                                  c("Comparison Number", "Outcome Number", "Subgroup Number", 
                                    "Name", "Data Type", "Statistical Method", "Effect Measure", "Analysis Model", 
                                    "Events 1", "Mean 1", "SD 1", "Total 1", 
                                    "Events 2", "Mean 2", "SD 2", "Total 2", 
                                    "Effect Estimate", "SE", "CI Start", "CI End", "Weight", 
                                    "Q", "P(Q)", "I-Sqr(Q)", "Tau-Sqr", "Z", "P(Z)", 
                                    "Qint", "P(Qint)", "I-Sqr(Qint)", "df", "Year of study")
                                  
                    ))
                  ))))) {
          # Replace "" and " " with NA
          rv$RevManData[rv$RevManData == ""] <- NA
          rv$RevManData[rv$RevManData == " "] <- NA
          rv$RevManData$ComparisonNumber_OutcomeNumber_SubgroupNumber <- paste0(rv$RevManData[,1],"_",rv$RevManData[,2], "_",rv$RevManData[,3])
          rv$RevManData$UniqueComparison <- paste0(rv$RevManData[,1],"_",rv$RevManData[,2], "_")
          rv$RevManData$StudyRow <- ((is.na(rv$RevManData[,5])) & (!is.na(rv$RevManData[,9])))
          
          rv$Comparisons1 <- rv$RevManData[rv$RevManData[,2] == 0,4]
          rv$Comparisons1 <- gsub("\\.","_",path_sanitize(rv$Comparisons1, replacement = "_"))
          rv$Comparisons2 <- data.frame(ComparisonsNumber = rv$RevManData[!is.na(rv$RevManData[,5]),1])
          rv$Comparisons2$ComparisonsName <- rv$Comparisons1[rv$Comparisons2$ComparisonsNumber]
          rv$Comparisons2$Outcome <- gsub("\\.","_",path_sanitize(rv$RevManData[!is.na(rv$RevManData[,5]),4], replacement = "_"))
          rv$Comparisons2$Comparisons_Outcome <- paste0(rv$Comparisons2$ComparisonsName, '_',rv$Comparisons2$Outcome)
          rv$Comparisons2$EffectMeasure <- rv$RevManData[!is.na(rv$RevManData[,5]),7]
          rv$Comparisons2$EffectMeasure_Processed <- rv$RevManData[!is.na(rv$RevManData[,5]),7]
          rv$Comparisons2$EffectMeasure_Processed[rv$Comparisons2$EffectMeasure_Processed == 'Odds Ratio'] <- 'OR'
          rv$Comparisons2$EffectMeasure_Processed[rv$Comparisons2$EffectMeasure_Processed == 'Risk Ratio'] <- 'RR'
          rv$Comparisons2$EffectMeasure_Processed[rv$Comparisons2$EffectMeasure_Processed == 'Rate Ratio'] <- 'RR'
          rv$Comparisons2$EffectMeasure_Processed[rv$Comparisons2$EffectMeasure_Processed == 'Risk Difference'] <- 'RD'
          rv$Comparisons2$EffectMeasure_Processed[rv$Comparisons2$EffectMeasure_Processed == 'Mean Difference'] <- 'MD'
          rv$Comparisons2$EffectMeasure_Processed[rv$Comparisons2$EffectMeasure_Processed == 'Std. Mean Difference'] <- 'SMD'
          rv$Comparisons2$EffectMeasure_Processed[rv$Comparisons2$EffectMeasure_Processed == 'Hazard Ratio'] <- 'HR'
          rv$Comparisons2$OutcomeType_Unprocessed<- rv$RevManData[!is.na(rv$RevManData[,5]),5]
          rv$Comparisons2$OutcomeType_Processed<- rv$RevManData[!is.na(rv$RevManData[,5]),5]
          rv$Comparisons2$OutcomeType_Processed[rv$Comparisons2$OutcomeType_Processed == 'DIC'] <- 'Binary'
          rv$Comparisons2$OutcomeType_Processed[rv$Comparisons2$OutcomeType_Processed == 'CON'] <- 'Continuous'
          rv$Comparisons2$OutcomeType_Processed[(rv$Comparisons2$OutcomeType_Processed == 'INV') & (str_detect(rv$Comparisons2$EffectMeasure, regex('Ratio')))] <- 'Summary_Ratio'
          rv$Comparisons2$OutcomeType_Processed[(rv$Comparisons2$OutcomeType_Processed == 'INV') & (str_detect(rv$Comparisons2$EffectMeasure, regex('Difference')))] <- 'Summary_Difference'
          rv$Comparisons2$Code <- rv$RevManData[!is.na(rv$RevManData[,5]),33]
          rv$Comparisons2$Unique <- rv$RevManData[!is.na(rv$RevManData[,5]),34]
          rv$Comparisons3 <- data.frame(SubgroupNumber = rv$RevManData[(!is.na(rv$RevManData[,5]) & (rv$RevManData[,3] > 0)),4])
          rv$Comparisons3$Code <- rv$RevManData[(!is.na(rv$RevManData[,5]) & (rv$RevManData[,3] > 0)),33]
          rv$Comparisons3$Unique <- rv$RevManData[(!is.na(rv$RevManData[,5]) & (rv$RevManData[,3] > 0)),34]
          
          rv$RevManProcessed <- data.frame(matrix(NA, nrow = nrow(rv$RevManData), ncol=29))
          colnames(rv$RevManProcessed) <- c("Outcome name", "Type of outcome", "Are more events or higher value better or worse for participants?", "Study", 
                                            "Intervention (total number of participants)", "Control (total number of participants)", 
                                            "Parameter1", "Parameter2", "Parameter3", "Parameter4", 
                                            "Units (Continuous outcomes)", "Scale (Continuous outcomes)", 
                                            "Mean or standard deviation imputed (Continuous outcomes)", 
                                            "Missing failure (Intervention)", "Missing success (Intervention)", "Missing unrelated (Intervention)", 
                                            "Missing protocol violation (Intervention)", "Missing other (Intervention)", "Missing reasons not stated (Intervention)", 
                                            "Missing not stated (Intervention)", 
                                            "Missing failure (Control)", "Missing success (Control)", "Missing unrelated (Control)", 
                                            "Missing protocol violation (Control)", "Missing other (Control)", "Missing reasons not stated (Control)", 
                                            "Missing not stated (Control)", 
                                            "Intervention and control details for graphs", 
                                            "Subgroup1")
          
          rv$RevManProcessed[rv$RevManData[,35] == TRUE,1] <- rv$Comparisons2[match(rv$RevManData[rv$RevManData[,35] == TRUE,34],rv$Comparisons2[,10]),4]
          rv$RevManProcessed[rv$RevManData[,35] == TRUE,2] <- rv$Comparisons2[match(rv$RevManData[rv$RevManData[,35] == TRUE,34],rv$Comparisons2[,10]),8]
          rv$RevManProcessed[rv$RevManData[,35] == TRUE,3] <- 'Worse'
          rv$RevManProcessed[rv$RevManData[,35] == TRUE,4] <- rv$RevManData[rv$RevManData[,35] == TRUE,4]
          rv$RevManProcessed[,4] <- str_replace_all(rv$RevManProcessed[,4],"‐","-")
          rv$RevManProcessed[rv$RevManData[,35] == TRUE,5] <- rv$RevManData[rv$RevManData[,35] == TRUE,12]
          rv$RevManProcessed[rv$RevManData[,35] == TRUE,6] <- rv$RevManData[rv$RevManData[,35] == TRUE,16]
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Binary') & (!is.na(rv$RevManData[,9]))),7] <- rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Binary') & (!is.na(rv$RevManData[,9]))),9]
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Continuous') & (!is.na(rv$RevManData[,10]))),7] <- rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Continuous') & (!is.na(rv$RevManData[,10]))),10]
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Summary_Ratio') & (!is.na(rv$RevManData[,17]))),7] <- log(rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Summary_Ratio') & (!is.na(rv$RevManData[,17]))),17])
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Summary_Difference') & (!is.na(rv$RevManData[,17]))),7] <- rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Summary_Difference') & (!is.na(rv$RevManData[,17]))),17]
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Binary') & (!is.na(rv$RevManData[,13]))),8] <- rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Binary') & (!is.na(rv$RevManData[,13]))),13]
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Continuous') & (!is.na(rv$RevManData[,11]))),8] <- rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Continuous') & (!is.na(rv$RevManData[,11]))),11]
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Summary_Ratio') & (!is.na(rv$RevManData[,18]))),8] <- rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Summary_Ratio') & (!is.na(rv$RevManData[,18]))),18]
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Summary_Difference') & (!is.na(rv$RevManData[,18]))),8] <- rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Summary_Difference') & (!is.na(rv$RevManData[,18]))),18]
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Continuous') & (!is.na(rv$RevManData[,14]))),9] <- rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Continuous') & (!is.na(rv$RevManData[,14]))),14]
          rv$RevManProcessed[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Continuous') & (!is.na(rv$RevManData[,15]))),10] <- rv$RevManData[((rv$RevManData[,35] == TRUE) & (rv$RevManProcessed[,2] == 'Continuous') & (!is.na(rv$RevManData[,15]))),15]
          rv$RevManProcessed[rv$RevManData[,35] == TRUE,29] <- rv$Comparisons3[match(rv$RevManData[rv$RevManData[,35] == TRUE,33],rv$Comparisons3[,2]),1]
          
          # Some processing to ensure that errors are captured
          rv$RevManProcessed[(
            (is.na(rv$RevManProcessed[,1])) | 
              ((rv$RevManProcessed[,2] == 'Continuous') & 
                 ((rv$RevManProcessed[,5] <= 0) | (rv$RevManProcessed[,6] <= 0))) |
              ((rv$RevManProcessed[,2] == 'Binary') & 
                 ((rv$RevManProcessed[,5] <= 0) | (rv$RevManProcessed[,6] <= 0))) |
              ((rv$RevManProcessed[,2] == 'Continuous') & 
                 (rv$RevManProcessed[,7] == 0) & 
                 (rv$RevManProcessed[,8] == 0) & 
                 (rv$RevManProcessed[,9] == 0) & 
                 (rv$RevManProcessed[,10] == 0) 
              )
          ),] <- NA
          rv$RevManProcessed[
            ((!is.na(rv$RevManProcessed[,8])) & (rv$RevManProcessed[,2] != 'Binary') & (rv$RevManProcessed[,8] == 0))
            , 8] <- NA
          rv$RevManProcessed[
            ((!is.na(rv$RevManProcessed[,10])) & (rv$RevManProcessed[,2] == 'Continuous') & (rv$RevManProcessed[,10] == 0))
            , 10] <- NA
          rv$RevManProcessed <- rv$RevManProcessed[!is.na(rv$RevManProcessed[,1]),]
          if (nrow(rv$RevManProcessed) < 4) {
            for (i in 1:(4-nrow(rv$RevManProcessed))){
              rv$RevManProcessed <- rbind(rv$RevManProcessed, rep(NA,29))
            }
          }
          
          # Add the intervention and details
          rv$RevManProcessed[1:4,28] <- c("Intervention", "Intervention", "Control", "Control") 
          
          output$htmlMsg1_Int <- renderUI(
            HTML('<h2 style="color:green; background-color:yellow"><b>The processed RevMan file is available for download</b></h2>')
          )
        } else {
          output$htmlMsg1_Int <- renderUI(
            HTML(paste0('<h2 style="color:red; background-color:yellow"><b>The column headings in the RevMan data that you uploaded do not match.\n
          The column headings in the uploaded file are: \n',
                        paste0('"',colnames(rv$RevManData), '"', collapse = ', '), '\n',
                        'Please upload a file prepared as per the instructions</b></h2>')
            )
          )
        }
      }
    }
  })
  
  observeEvent(input$Upload_RevManWeb, {
    # Check if the file is txt, csv and import it
    # if the extension is not txt or csv do nothing more than a warning
    if ((!is.na(input$Upload_RevManWeb$name)) & (input$Upload_RevManWeb$name !="")){
      if (! any(c(file_ext(input$Upload_RevManWeb$datapath)=="txt",file_ext(input$Upload_RevManWeb$datapath)=="csv"))){
        output$htmlMsg1_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>Please upload
             a csv file or tab delimited file</b></h2>')
        )
        # If the file is empty, just say that it is empty
      } else if (file.size(input$Upload_RevManWeb$datapath)<8){
        output$htmlMsg1_Int <- renderUI(
          HTML('<h2 style="color:red; background-color:yellow"><b>Please upload a file that contains data</b></h2>')
        )
      } else {
        # To avoid change in column names, use check.names=FALSE
        if (file_ext(input$Upload_RevManWeb$datapath)=="txt"){
          rv$RevManData <-read.delim(input$Upload_RevManWeb$datapath,header=TRUE, stringsAsFactors=FALSE, sep = '\t', check.names=FALSE)        
        } else if (file_ext(input$Upload_RevManWeb$datapath)=="csv"){
          rv$RevManData <-read.csv(input$Upload_RevManWeb$datapath, header=TRUE, stringsAsFactors=FALSE, sep = ',', check.names=FALSE)
        }
        # Now check whether column names match
        if (all(c(ncol(rv$RevManData) == 23,
                  !FALSE %in% (colnames(rv$RevManData)[1:23] == 
                               c("Analysis group","Analysis number","Analysis name","Subgroup",
                                 "Study","Study year","GIV Mean","GIV SE",
                                 "Experimental mean","Experimental SD",
                                 "Experimental cases","Experimental N",
                                 "Control mean","Control SD",
                                 "Control cases","Control N",
                                 "O-E","Variance","Weight",
                                 "Mean","CI start","CI end","Footnotes")
                  )
        ))) {
          # Replace "" and " " with NA
          rv$RevManData[rv$RevManData == ""] <- NA
          rv$RevManData[rv$RevManData == " "] <- NA
          rv$RevManData$ComparisonNumber_OutcomeNumber_SubgroupNumber <- paste0(rv$RevManData[,1],"_",rv$RevManData[,2], "_",rv$RevManData[,4])
          rv$RevManData$UniqueComparison <- paste0(rv$RevManData[,1],"_",rv$RevManData[,2], "_")
          rv$RevManData$StudyRow <- TRUE
          
          rv$RevManProcessed <- data.frame(matrix(NA, nrow = nrow(rv$RevManData), ncol=29))
          colnames(rv$RevManProcessed) <- c("Outcome name", "Type of outcome", "Are more events or higher value better or worse for participants?", "Study", 
                                            "Intervention (total number of participants)", "Control (total number of participants)", 
                                            "Parameter1", "Parameter2", "Parameter3", "Parameter4", 
                                            "Units (Continuous outcomes)", "Scale (Continuous outcomes)", 
                                            "Mean or standard deviation imputed (Continuous outcomes)", 
                                            "Missing failure (Intervention)", "Missing success (Intervention)", "Missing unrelated (Intervention)", 
                                            "Missing protocol violation (Intervention)", "Missing other (Intervention)", "Missing reasons not stated (Intervention)", 
                                            "Missing not stated (Intervention)", 
                                            "Missing failure (Control)", "Missing success (Control)", "Missing unrelated (Control)", 
                                            "Missing protocol violation (Control)", "Missing other (Control)", "Missing reasons not stated (Control)", 
                                            "Missing not stated (Control)", 
                                            "Intervention and control details for graphs", 
                                            "Subgroup1")
          rv$RevManProcessed[,1] <- gsub("\\.","_",path_sanitize(paste0(rv$RevManData[,1],'_',rv$RevManData[,3]), replacement = "_"))
          rv$RevManProcessed[((rv$RevManData[,8] == 0) & ((rv$RevManData[,12] != 0) & (rv$RevManData[,16] != 0)) &
                                ((rv$RevManData[,9] == 0) & (rv$RevManData[,10] == 0) & (rv$RevManData[,13] == 0) & (rv$RevManData[,14] == 0))
          ),2] <- 'Binary'
          rv$RevManProcessed[((rv$RevManData[,8] == 0) & ((rv$RevManData[,12] != 0) & (rv$RevManData[,16] != 0)) &
                                !((rv$RevManData[,9] == 0) & (rv$RevManData[,10] == 0) & (rv$RevManData[,13] == 0) & (rv$RevManData[,14] == 0))
          ),2] <- 'Continuous'
          rv$RevManProcessed[((rv$RevManData[,8] != 0) & (rv$RevManData[,7] != rv$RevManData[,20])),2] <- 'Summary_Ratio'
          rv$RevManProcessed[((rv$RevManData[,8] != 0) & (rv$RevManData[,7] == rv$RevManData[,20])),2] <- 'Summary_Difference'
          
          # Now check that an outcome is not of two types because of errors in data entry
          rv$Comparisons2 <- rv$RevManProcessed[,1:2]
          colnames(rv$Comparisons2) <- c("OutcomeName","OutcomeType")
          rv$Comparisons2$OutcomeName_Type <- paste0(rv$Comparisons2$OutcomeName, '_', rv$Comparisons2$OutcomeType)
          rv$Comparisons1 <- data.frame(cbind(unlist(dimnames(
            table(aggregate(. ~ rv$Comparisons2$OutcomeName_Type + rv$Comparisons2$OutcomeName, data = rv$Comparisons2, FUN = frequency)[[2]]))),
            unlist(table(aggregate(. ~ rv$Comparisons2$OutcomeName_Type + rv$Comparisons2$OutcomeName, data = rv$Comparisons2, FUN = frequency)[[2]]))))
          colnames(rv$Comparisons1) <- c("Outcome name","Number of types of outcomes")          
          rv$RevManProcessed[,3] <- 'Worse'
          rv$RevManProcessed[,4] <- rv$RevManData[,5]
          rv$RevManProcessed[,4] <- str_replace_all(rv$RevManProcessed[,4],"‐","-")
          rv$RevManProcessed[,5] <- rv$RevManData[,12]
          rv$RevManProcessed[,6] <- rv$RevManData[,16]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Binary'),7] <- rv$RevManData[
            ((rv$RevManData[,8] == 0) & ((rv$RevManData[,12] != 0) & (rv$RevManData[,16] != 0)) &
               ((rv$RevManData[,9] == 0) & (rv$RevManData[,10] == 0) & (rv$RevManData[,13] == 0) & (rv$RevManData[,14] == 0))
            ),11]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Continuous'),7] <- rv$RevManData[
            ((rv$RevManData[,8] == 0) & ((rv$RevManData[,12] != 0) & (rv$RevManData[,16] != 0)) &
               !((rv$RevManData[,9] == 0) & (rv$RevManData[,10] == 0) & (rv$RevManData[,13] == 0) & (rv$RevManData[,14] == 0))
            ),9]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Summary_Ratio'),7] <- rv$RevManData[
            ((rv$RevManData[,8] != 0) & (rv$RevManData[,7] != rv$RevManData[,20])),7]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Summary_Difference'),7] <- rv$RevManData[
            ((rv$RevManData[,8] != 0) & (rv$RevManData[,7] == rv$RevManData[,20])),7]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Binary'),8] <- rv$RevManData[
            ((rv$RevManData[,8] == 0) & ((rv$RevManData[,12] != 0) & (rv$RevManData[,16] != 0)) &
               ((rv$RevManData[,9] == 0) & (rv$RevManData[,10] == 0) & (rv$RevManData[,13] == 0) & (rv$RevManData[,14] == 0))
            ),15]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Continuous'),8] <- rv$RevManData[
            ((rv$RevManData[,8] == 0) & ((rv$RevManData[,12] != 0) & (rv$RevManData[,16] != 0)) &
               !((rv$RevManData[,9] == 0) & (rv$RevManData[,10] == 0) & (rv$RevManData[,13] == 0) & (rv$RevManData[,14] == 0))
            ),10]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Summary_Ratio'),8] <- rv$RevManData[
            ((rv$RevManData[,8] != 0) & (rv$RevManData[,7] != rv$RevManData[,20])),8]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Summary_Difference'),8] <- rv$RevManData[
            ((rv$RevManData[,8] != 0) & (rv$RevManData[,7] == rv$RevManData[,20])),8]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Continuous'),9] <- rv$RevManData[
            ((rv$RevManData[,8] == 0) & ((rv$RevManData[,12] != 0) & (rv$RevManData[,16] != 0)) &
               !((rv$RevManData[,9] == 0) & (rv$RevManData[,10] == 0) & (rv$RevManData[,13] == 0) & (rv$RevManData[,14] == 0))
            ),13]
          rv$RevManProcessed[(rv$RevManProcessed[,2] == 'Continuous'),10] <- rv$RevManData[
            ((rv$RevManData[,8] == 0) & ((rv$RevManData[,12] != 0) & (rv$RevManData[,16] != 0)) &
               !((rv$RevManData[,9] == 0) & (rv$RevManData[,10] == 0) & (rv$RevManData[,13] == 0) & (rv$RevManData[,14] == 0))
            ),14]
          rv$RevManProcessed[,29] <- rv$RevManData[,4]
          
          # Some processing to ensure that errors are captured
          # If there are multiple outcome types for the same outcome, this should be removed
          rv$RevManProcessed[rv$Comparisons1[match(rv$RevManProcessed[,1], rv$Comparisons1[,1]),2] > 1,1] <- NA
          
          rv$RevManProcessed[(
            (is.na(rv$RevManProcessed[,1])) | 
              ((rv$RevManProcessed[,2] == 'Continuous') & 
                 ((rv$RevManProcessed[,5] <= 0) | (rv$RevManProcessed[,6] <= 0))) |
              ((rv$RevManProcessed[,2] == 'Binary') & 
                 ((rv$RevManProcessed[,5] <= 0) | (rv$RevManProcessed[,6] <= 0))) |
              ((rv$RevManProcessed[,2] == 'Continuous') & 
                 (rv$RevManProcessed[,7] == 0) & 
                 (rv$RevManProcessed[,8] == 0) & 
                 (rv$RevManProcessed[,9] == 0) & 
                 (rv$RevManProcessed[,10] == 0) 
              )
          ),] <- NA
          rv$RevManProcessed[
            ((!is.na(rv$RevManProcessed[,8])) & (rv$RevManProcessed[,2] != 'Binary') & (rv$RevManProcessed[,8] == 0))
            , 8] <- NA
          rv$RevManProcessed[
            ((!is.na(rv$RevManProcessed[,10])) & (rv$RevManProcessed[,2] == 'Continuous') & (rv$RevManProcessed[,10] == 0))
            , 10] <- NA
          rv$RevManProcessed <- rv$RevManProcessed[!is.na(rv$RevManProcessed[,1]),]
          if (nrow(rv$RevManProcessed) < 4) {
            for (i in 1:(4-nrow(rv$RevManProcessed))){
              rv$RevManProcessed <- rbind(rv$RevManProcessed, rep(NA,29))
            }
          }
          
          # Add the intervention and details
          rv$RevManProcessed[1:4,28] <- c("Intervention", "Intervention", "Control", "Control") 
          
          output$htmlMsg1_Int <- renderUI(
            HTML('<h2 style="color:green; background-color:yellow"><b>The processed RevMan file is available for download</b></h2>')
          )
        } else {
          output$htmlMsg1_Int <- renderUI(
            HTML(paste0('<h2 style="color:red; background-color:yellow"><b>The column headings in the RevMan data that you uploaded do not match.\n
          The column headings in the uploaded file are: \n',
                        paste0('"',colnames(rv$RevManData), '"', collapse = ', '), '\n',
                        'Please upload a file prepared as per the instructions</b></h2>')
            )
          )
        }
      }
    }
  })
  output$SelectedMetaAnalysisPlan_Int <- renderTable({rv$UploadedMetaAnalysisPlan_Int})
  output$DefaultMetaAnalysisPlan_Int <- renderTable({rv$DefaultMetaAnalysisPlan_Int})
  output$RevManMetaAnalysisPlan_Int <- renderTable({rv$RevManMetaAnalysisPlan_Int})
  output$OutcomeSummary_Int <- renderTable({rv$outcome.summary_Int[,1:7]})
  output$ResultsTable_Int <- renderTable({rv$outcome.summary_Int[,c(1,8:14)]})
  output$ForestPlot <- renderPlot({rv$FinalPlot1})
  output$FunnelPlot <- renderPlot({rv$FinalPlot2})
  output$SA_ForestPlot1 <-renderPlot({rv$FinalPlotSA1}) 
  output$SA_ForestPlot2 <-renderPlot({rv$FinalPlotSA2}) 
  output$SA_ForestPlot3 <-renderPlot({rv$FinalPlotSA3}) 
  output$BubblePlot <- renderPlot({rv$FinalPlot3})
  output$SubA1_ForestPlot <- renderPlot({rv$FinalPlotSubA1})
  output$SubA2_ForestPlot <- renderPlot({rv$FinalPlotSubA2})
  output$SubA3_ForestPlot <- renderPlot({rv$FinalPlotSubA3})
  output$SubA4_ForestPlot <- renderPlot({rv$FinalPlotSubA4})
  output$SubA5_ForestPlot <- renderPlot({rv$FinalPlotSubA5})
  output$SubA6_ForestPlot <- renderPlot({rv$FinalPlotSubA6})
  output$SubA7_ForestPlot <- renderPlot({rv$FinalPlotSubA7})
  output$SubA8_ForestPlot <- renderPlot({rv$FinalPlotSubA8})
  output$SubA9_ForestPlot <- renderPlot({rv$FinalPlotSubA9})
  output$SubA10_ForestPlot <- renderPlot({rv$FinalPlotSubA10})
  
  # Downloads
  output$Selected.ma.plan_Int <- downloadHandler( 
    filename = "SelectedMetaAnalysisPlan_Intervention.csv", 
    content = function(file) {
      write.csv(rv$UploadedMetaAnalysisPlan_Int, file, 
                row.names=FALSE,
                na="")
    } 
  )
  output$default.ma.plan_Int <- downloadHandler( 
    filename = "DefaultMetaAnalysisPlan_Intervention.csv", 
    content = function(file) {
      write.csv(rv$DefaultMetaAnalysisPlan_Int, file, 
                row.names=FALSE,
                na="")
    } 
  )
  output$revman.ma.plan_Int <- downloadHandler( 
    filename = "RevManMetaAnalysisPlan_Intervention.csv", 
    content = function(file) {
      write.csv(rv$RevManMetaAnalysisPlan_Int, file, 
                row.names=FALSE,
                na="")
    } 
  )
  output$outcome.summary_Int <- downloadHandler( 
    filename = "OutcomeSummary_Intervention.csv", 
    content = function(file) {
      write.csv(rv$outcome.summary_Int, file, 
                row.names=FALSE,
                na="")
    } 
  )
  output$AllPlots_Int <- downloadHandler( 
    filename = "AllPlots_Intervention.zip", 
    content = function(file) {
      zip::zipr(zipfile = file, files = list.files(path = rv$StorageFolder, pattern = ".png$", full.names=TRUE))
    },
    contentType = "application/zip" 
  )
  
  # Downloads in left side panel ####
  output$SampleData_Int <- downloadHandler( 
    filename = "SampleData_Intervention.csv", 
    content = function(file) {
      file.copy("SampleData_Intervention.csv", file)
    } 
  )
  output$SampleMetaAnalysisPlan_Int <- downloadHandler( 
    filename = "SampleMetaAnalysisPlan_Intervention.csv", 
    content = function(file) {
      file.copy("SampleMetaAnalysisPlan_Intervention.csv", file)
    } 
  )
  output$SampleIndex_references <- downloadHandler( 
    filename = "SampleIndex_references.csv", 
    content = function(file) {
      file.copy("SampleIndex_references.csv", file)
    } 
  )
  output$SampleKeywords_references <- downloadHandler( 
    filename = "SampleKeywords_references.csv", 
    content = function(file) {
      file.copy("SampleKeywords_references.csv", file)
    } 
  )
  output$SampleCriteria_DEF <- downloadHandler( 
    filename = "SampleCriteria_DEF.csv", 
    content = function(file) {
      file.copy("SampleCriteria_DEF.csv", file)
    } 
  )
  output$SampleOther_characteristics_DEF <- downloadHandler( 
    filename = "SampleOther_characteristics_DEF.csv", 
    content = function(file) {
      file.copy("SampleOther_characteristics_DEF.csv", file)
    }
  )
  output$SampleOutcomes_DEF_Int <- downloadHandler( 
    filename = "SampleOutcomes_DEF_Int.csv", 
    content = function(file) {
      file.copy("SampleOutcomes_DEF_Int.csv", file)
    } 
  )
  output$SampleDEF_Plan <- downloadHandler( 
    filename = "SampleDEF_Plan.csv", 
    content = function(file) {
      file.copy("SampleDEF_Plan.csv", file)
    } 
  )
  output$SampleKM_Plot <- downloadHandler( 
    filename = "SampleKaplanMeier_Plot.png", 
    content = function(file) {
      file.copy("SampleKaplanMeier_Plot.png", file)
    } 
  )
  output$SampleBox_Plot <- downloadHandler( 
    filename = "SampleBox_Plot.png", 
    content = function(file) {
      file.copy("SampleBox_Plot.png", file)
    } 
  )
  output$SampleBar_Plot <- downloadHandler( 
    filename = "SampleBar_Plot.png", 
    content = function(file) {
      file.copy("SampleBar_Plot.png", file)
    } 
  )
  output$SampleLine_Plot <- downloadHandler( 
    filename = "SampleLine_Plot.png", 
    content = function(file) {
      file.copy("SampleLine_Plot.png", file)
    } 
  )
  
  output$ProcessedRevManData_Int <- downloadHandler( 
    filename = "RevManProcessed_Intervention.csv", 
    content = function(file) {
      write.csv(rv$RevManProcessed, file, 
                row.names=FALSE,
                na="")
    } 
  )
  output$Code_Int <- downloadHandler( 
    filename = "R_Code_Intervention.txt", 
    content = function(file) {
      write.table(rv$GenerateCode, file, 
                  row.names = FALSE, col.names = FALSE,
                  quote = FALSE
      )
    } 
  )
  output$ProgrammeCode <- downloadHandler( 
    filename = "ProgrammeCode.txt", 
    content = function(file) {
      write.table(ProgrammeCode, file, 
                  row.names = FALSE, col.names = FALSE,
                  quote = FALSE
      )
    } 
  )
}

shinyApp(ui = ui, server = server)