inst/Kronos_pre_processing/app.R

#options
options(stringsAsFactors = FALSE,
        dplyr.summarise.inform=FALSE,
        warn = 1,
        scipen = 999)
#load operator
`%>%` = tidyr::`%>%`
#set ggplot theme
ggplot2::theme_set(new = ggplot2::theme_bw())
#Java function to close this app
jscode <- "shinyjs.closeWindow = function() { window.close(); }"
#find max number of cores
maxCores = parallel::detectCores()

# Define UI
ui <- shinydashboard::dashboardPage(
  title = 'Kronos scRT',
  skin = 'red',
  shinydashboard::dashboardHeader(title = shiny::span(
    shiny::img(src = 'KronosLogo.png', width = '100%')
  )),
  shinydashboard::dashboardSidebar(
    shinydashboard::sidebarMenu(
      id = 'Sidebar',
      shinydashboard::menuItem(text = "FastqToBam",
                               tabName = "Home"),
      shinydashboard::menuItem(text = "FastqToBam Metrics",
                               tabName = "Metrics"),
      shinydashboard::menuItem(text = "Binning",
                               tabName = "Binning"),
      shinydashboard::menuItem(text = "Copy Number Calling",
                               tabName = "CN"),
      shinydashboard::menuItem(text = "10XGenomics data conversion",
                               tabName = "10X"),
      shinydashboard::menuItem(text = "Exit",
                               tabName = "Exit")
    )
  ),
  shinydashboard::dashboardBody(
    #use shinyjs
    shinyjs::useShinyjs(),

    #to close window
    shinyjs::extendShinyjs(text = jscode, functions = c("closeWindow")),

    #use CSS
    shiny::tags$head(
      shiny::tags$link(rel = "stylesheet",
                       type = "text/css",
                       href = "custom.css")
    ),

    #setting spinner
    shinybusy::add_busy_spinner(
      spin = "fading-circle",
      position = 'bottom-right',
      color = 'red',
      height = '200px',
      width = '200px'
    ),

    shinydashboard::tabItems(#####home
      {
        shinydashboard::tabItem(tabName = "Home",
                                shiny::fluidPage(
                                  shiny::fluidRow(
                                    shiny::fluidRow(
                                      shiny::column(
                                        width = 3,

                                        shinyFiles::shinyDirButton(
                                          id = 'Fastq',
                                          label = 'Fastq files folder',
                                          title = 'Fastq files folder',
                                          style = 'width:100%;'
                                        )
                                      ),
                                      shiny::column(width = 9, shiny::htmlOutput('Fastq_out'))
                                    ),
                                    shiny::fluidRow(
                                      shiny::column(
                                        width = 3,
                                        shinyFiles::shinyFilesButton(
                                          id = 'index',
                                          label = shiny::div(
                                            'Bowtie2 index',
                                            bsplus::shiny_iconlink() %>%
                                              bsplus::bs_embed_popover(title = "Select one of the index files. If you don't have a compiled index, you can download one from http://bowtie-bio.sourceforge.net/bowtie2."  , placement = 'right')
                                          ),
                                          title = 'Bowtie2 index',
                                          style = 'width:100%;',
                                          multiple = F
                                        )
                                      ),
                                      shiny::column(width = 9, shiny::htmlOutput('index_out'))
                                    ),
                                    shiny::fluidRow(
                                      shiny::column(
                                        width = 3,
                                        shinyFiles::shinyFilesButton(
                                          id = 'Adapters',
                                          label = shiny::div(
                                            'Adapters list',
                                            bsplus::shiny_iconlink() %>%
                                              bsplus::bs_embed_popover(title = 'A text files with one adapter per line with no header. If not provided Kronos will look for standard illumina adapters' , placement = 'right')
                                          ),
                                          title = 'Adapters list',
                                          style = 'width:100%;',
                                          multiple = F
                                        )
                                      ),
                                      shiny::column(width = 9, shiny::htmlOutput('Adapters_out'))
                                    ),
                                    shiny::fluidRow(
                                      shiny::column(
                                        width = 3,
                                        shinyFiles::shinyDirButton(
                                          id = 'out',
                                          label = 'Output files folder',
                                          title = 'Output files folder',
                                          style = 'width:100%;'
                                        )
                                      ),
                                      shiny::column(width = 9, shiny::htmlOutput('Output_out'))
                                    ),
                                    shiny::fluidRow(
                                      shiny::column(
                                        width = 3,
                                        shiny::radioButtons(
                                          inputId = 'reads_type',
                                          label = 'Sequencing',
                                          choices = c('PE', 'SE', 'PE to treat as SE'),
                                          inline = T,
                                          selected = 'PE',
                                          width = '100%'
                                        )
                                      ),
                                      shiny::column(
                                        width = 3,
                                        shiny::numericInput(
                                          inputId = 'min_size',
                                          label = 'Read min size after trimming',
                                          value = 25,
                                          min = 15,
                                          step = 1,
                                          width = '100%'
                                        )
                                      ),
                                      shiny::column(
                                        width = 3,
                                        shiny::radioButtons(
                                          inputId = 'phred33',
                                          label = 'Quality score',
                                          choiceValues = c(T, F) ,
                                          choiceNames = c('phred33', 'phred64'),
                                          selected = T,
                                          inline = T,
                                          width = '100%'
                                        )
                                      )
                                    ),
                                    shiny::uiOutput('patter_sample'),
                                    shiny::fluidRow(shiny::column(
                                      width = 3,
                                      shiny::sliderInput(
                                        inputId = 'cores',
                                        label = 'Cores to use',
                                        min = 1,
                                        max = maxCores,
                                        value = trunc(maxCores / 2),
                                        step = 1
                                      )
                                    )),
                                    shiny::fluidRow(shiny::column(
                                      width = 3,
                                      shinyjs::disabled(
                                        shiny::actionButton(
                                          inputId = 'run',
                                          label = 'Run',
                                          width = '100%'
                                        )
                                      )
                                    )),
                                    shiny::fluidRow(shiny::column(width = 12,
                                                                  shiny::htmlOutput('final')))
                                  )
                                ))
      },
      ######metrics
      {
        shinydashboard::tabItem(
          tabName = "Metrics",
          shiny::fluidRow(
            shiny::column(
              width = 4,
              align = 'center',
              shinyFiles::shinyFilesButton(
                id = 'Load_metrics',
                label = 'Load old Metrics',
                title = 'Load old Metrics',
                multiple = F,
                style = 'width:75%;'
              )
            ),
            shiny::column(
              width = 4,
              align = 'center',
              shinyjs::disabled(
                shinyFiles::shinySaveButton(
                  id = 'Save_plots',
                  label = 'Save diagnostic plot',
                  title = 'Save diagnostic plot',
                  filetype = '.pdf',
                  style = 'width:75%;'
                )
              )
            ),
            shiny::column(
              width = 4,
              align = 'center',
              shinyjs::disabled(
                shinyFiles::shinySaveButton(
                  id = 'Save_table',
                  label = 'Save table',
                  title = 'Save table',
                  filetype = '.tsv',
                  style = 'width:75%;'
                )
              )
            )
          ),
          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::plotOutput(
              'final_plot1',
              # click = shiny::clickOpts(id = 'final_plot_click1'),
              brush = shiny::brushOpts(id = 'final_plot_brush1',
                                       resetOnNew = T),
              dblclick = shiny::dblclickOpts(id = 'final_plot_dclick1', clip = T, delay = 200)
            )
          )),

          shiny::fluidRow(shiny::column(
            width = 12,
            shinyjs::hidden(
              shiny::radioButtons(
                inputId = 'final_table_selector',
                label = 'Parameter',
                choices = '',
                inline = F,
                width = '100%'
              )
            )
          )),
          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::tableOutput('final_table')
          ))
        )
      },
      #####binning
      {
        shinydashboard::tabItem(
          tabName = "Binning",
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shinyFiles::shinyFilesButton(
                id = 'RefGenome_binning',
                label = shiny::div(
                  'Reference genome fasta file',
                  bsplus::shiny_iconlink() %>%
                    bsplus::bs_embed_popover(title = "For most genomes, fasta file can be downloaded from UCSC Genome Browser. N.B. you need to download the file containing all chromosomes." , placement = 'right')
                ),
                title = 'Reference genome fasta file',
                multiple = F,
                style = 'width:100%;'
              )
            ),
            shiny::column(width = 9,
                          shiny::htmlOutput('RefGenome_binning_out'))
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shinyFiles::shinyFilesButton(
                id = 'index_binning',
                label = shiny::div(
                  'Bowtie2 index',
                  bsplus::shiny_iconlink() %>%
                    bsplus::bs_embed_popover(title = "Select one of the index files. If you don't have a compiled index, you can download one from http://bowtie-bio.sourceforge.net/bowtie2." , placement = 'right')
                ),
                title = 'Bowtie2 index',
                style = 'width:100%;',
                multiple = F
              )
            ),
            shiny::column(width = 9, shiny::htmlOutput('index_binning_out'))
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shinyFiles::shinyDirButton(
                id = 'out_binning',
                label = 'Output files folder',
                title = 'Output files folder',
                style = 'width:100%;'
              )
            ),
            shiny::column(width = 9, shiny::htmlOutput('Output_binning_out'))
          ),
          shiny::fluidRow(
            shiny::column(
            width = 3,
            shiny::radioButtons(
              inputId = 'Param_binning',
              label = 'Parameters estimation',
              choices = c('Auto', 'Manual'),
              selected = 'Auto',
              inline = T,
              width = '100%'
            )
          )),
          shiny::uiOutput('Paramui_binning_out1'),
          shiny::uiOutput('Paramui_binning_out2'),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shiny::sliderInput(
                inputId = 'Coverage_binning',
                label = shiny::div(
                  'Coverage',
                  bsplus::shiny_iconlink() %>%
                    bsplus::bs_embed_popover(title = 'Simulated dept of sequencing to calculate bin mappability.' , placement = 'right')
                ),
                min = 1,
                max = 10,
                value = 1,
                step = 1,
                post = 'X',
                width = '100%'
              )
            ),
            shiny::column(
              width = 3,
              shiny::sliderInput(
                inputId = 'BinSize_binning',
                label = shiny::div(
                  'BinSize',
                  bsplus::shiny_iconlink() %>%
                    bsplus::bs_embed_popover(title = 'Bin size that will be used to call CNV. This size does not correspond to the final scRT resolution. The bin size should increased if the average cell coverage is very low.' , placement = 'right')
                ),
                min = 5,
                max = 100,
                value = 20,
                step = 1,
                post = 'kb',
                width = '100%'
              )
            ),
            shiny::column(
              width = 3,
              shiny::sliderInput(
                inputId = 'Cores_binning',
                label = 'Cores',
                min = 1,
                max = maxCores,
                value = trunc(maxCores / 2),
                step = 1,
                width = '100%'
              )
            )
          ),
          shinydashboard::box(
            title = 'Advanced options',
            status = 'primary',
            solidHeader = T,
            width = '100%',
            collapsible = T,
            collapsed = T,
            shiny::fluidRow(
              shiny::column(
                width = 3,
                shiny::sliderInput(
                  inputId = 'Mappability_binning',
                  label = shiny::div(
                    'Acceptable mappability range',
                    bsplus::shiny_iconlink() %>%
                      bsplus::bs_embed_popover(title = 'Bins with mappability higher or lower than the acceptable mappability range will be excluded from the analysis.' , placement = 'right')
                  ),
                  min = 0.5,
                  max = 3,
                  value = c(0.8, 1.5),
                  step = 0.1,
                  width = '100%'
                )
              ),
              shiny::column(
                width = 3,
                shiny::sliderInput(
                  inputId = 'ErrorRate_binning',
                  label = shiny::div(
                    'Sequencer Error Rate',
                    bsplus::shiny_iconlink() %>%
                      bsplus::bs_embed_popover(title = 'Is the error rate of the sequencer you used to sequence your data. This parameter is used to simulates reads and calculate the bin mappability.' , placement = 'right')
                  ),
                  min = 0,
                  max = 0.3,
                  value = 0.1,
                  post = '%',
                  step = 0.001,
                  width = '100%'
                )
              )
            ),
            shiny::fluidRow(
              shiny::column(
                width = 3,
                shinyFiles::shinyFilesButton(
                  id = 'Blacklist_binning',
                  label = shiny::div(
                    'Blacklist',
                    bsplus::shiny_iconlink() %>%
                      bsplus::bs_embed_popover(title = 'Because of their repetitive nature, some regions of the genome are difficult to map. The user can hide these regions form the analysis providing a blacklist file. Such lists are available in literature. Some useful ones can be found at https://github.com/Boyle-Lab/Blacklist' , placement = 'right')
                  ),
                  title = 'Blacklist',
                  multiple = F
                )
              ),
              shiny::column(width = 9,
                            shiny::htmlOutput('Blacklist_binning_out'))

            )
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shiny::textInput(
                inputId = 'chr_prefix_binning',
                label = shiny::div(
                  'Chromosome prefix',
                  bsplus::shiny_iconlink() %>%
                    bsplus::bs_embed_popover(title = 'Depending on your reference genome, chromosomes or scaffolds could be named differently. Please, provide the prefix that precedes the chromosome or scaffold number. If no prefix is present this box has to be emptied.' , placement = 'right')),
                  value = 'chr',
                  width = '100%'
                )
              ),
              shiny::column(
                width = 3,
                shiny::textInput(
                  inputId = 'chr_range_binning',
                  label = shiny::div(
                    'Chromosomes to consider',
                    bsplus::shiny_iconlink() %>%
                      bsplus::bs_embed_popover(title = 'Chromosome to include in the analysis. You can define ranges using ":" and individual chromosomes using ",". Don\'t include the chr prefix!' , placement = 'right')
                  ),
                  value = '1:22',
                  width = '100%'
                )
              )
            ),
            shiny::fluidRow(shiny::column(
              width = 3,
              shinyjs::disabled(
                shiny::actionButton(
                  inputId = 'run_binning',
                  label = 'Run',
                  width = '100%'
                )
              )
            ))
          )
      },
      #####CN
      {
        shinydashboard::tabItem(
          tabName = "CN",
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shinyFiles::shinyFilesButton(
                id = 'Bins_CN',
                label = div('Bins file',
                            bsplus::shiny_iconlink() %>%
                              bsplus::bs_embed_popover(title = 'Bins file created during the binning step.' , placement = 'right')),
                title = 'Bins file',
                style = 'width:100%;',
                multiple = F
              )
            ),
            shiny::column(width = 9,
                          shiny::htmlOutput('Bins_CN'))
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shinyFiles::shinyFilesButton(
                id = 'ChrSize_CN',
                label = shiny::div(
                  'Chrom size file',
                  bsplus::shiny_iconlink() %>%
                    bsplus::bs_embed_popover(title = 'For most genome assemblies this file can be downloaded from UCSC Genome Browser website.' , placement = 'right')),
                title = 'Chrom size file',
                style = 'width:100%;',
                multiple = F
              )
            ),
            shiny::column(width = 9,
                          shiny::htmlOutput('ChrSize_CN'))
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shinyFiles::shinyDirButton(
                id = 'Output_CN',
                label = 'Results folder',
                title = 'Results folder',
                style = 'width:100%;'
              )
            ),
            shiny::column(width = 9,
                          shiny::htmlOutput('Output_CN'))
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shiny::textInput(
                inputId = 'CHR_CN',
                label = shiny::div('Chromosome prefix',
                                   bsplus::shiny_iconlink() %>%
                                     bsplus::bs_embed_popover(title = 'Depending on your reference genome, chromosomes or scaffolds could be named differently. Please, provide the prefix that precedes the chromosome or scaffold number. If no prefix is present this box has to be emptied.' , placement = 'right')
                ),
                value = 'chr',
                width = '100%'
              )
            ),
            shiny::column(
              width = 3,
              shiny::textInput(
                inputId = 'CHR_RANGE_CN',
                label = shiny::div(
                  'Chromosomes to consider',
                  bsplus::shiny_iconlink() %>%
                    bsplus::bs_embed_popover(title = 'Chromosome to include in the analysis. You can define ranges using ":" and individual chromosomes using ",". Don\'t include the chr prefix!' , placement = 'right')
                ),
                value = '1:22',
                width = '100%'
              )
            ),
            shiny::column(
              width = 3,
              shiny::sliderInput(
                inputId = 'Cores_CN',
                label = 'Number of cores',
                min = 1,
                max = maxCores,
                value = trunc(maxCores / 2),
                step = 1
              )
            )
          ),
          shinydashboard::box(
            title = 'Advanced options',
            status = 'primary',
            solidHeader = T,
            width = 12,
            collapsible = T,
            collapsed = T,
            shiny::fluidRow(shiny::column(
              width = 3,
              shiny::numericInput(
                inputId = 'min_reads_CN',
                label = shiny::div('Min number of reads per cell',
                                   bsplus::shiny_iconlink() %>%
                                     bsplus::bs_embed_popover(title = 'This threshold depends on the genome size of your cells and on the chromosomes you want to keep in the analysis.' , placement = 'right')
                ),
                value = 2 * 10 ^ 5,
                step = 10 ^ 4,
                width = '100%'
              )
            )),
            shiny::fluidRow(shiny::column(
              width = 12,
              shiny::radioButtons(
                inputId = 'Ploidy_Restrictions_CN',
                label = div('Ploidy restrictions',
                            bsplus::shiny_iconlink() %>%
                              bsplus::bs_embed_popover(title = 'If Fix Ploidy Range is selected, the software selects the most appropriated ploidy in the range and calculates the associated confidence. If Fix Average Ploidy is selected, cells are imposed the closest possible ploidy to the average one and does not calculate the confidence of this calling.' , placement = 'right')
                ),
                choices = c('Fix Average Ploidy', 'Fix Ploidy Range'),
                inline = T,
                selected = 'Fix Ploidy Range',
                width = '100%'
              )
            )),
            shiny::uiOutput('FixAveragePloidy'),
            shiny::uiOutput('FixPloidyRange')
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shinyFiles::shinyDirButton(
                id = 'Bamdir_CN',
                label = 'Bam files folder',
                title = 'Bam files folder',
                style = 'width:100%;'
              )
            ),
            column(width = 9,
                   shiny::htmlOutput('Bamdir_CN'))
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shiny::textInput(
                inputId = 'basename_CN',
                label = shiny::div('Sample basename',
                                   bsplus::shiny_iconlink() %>%
                                     bsplus::bs_embed_popover(title = 'This Name identifies each individual experiment. It can be modified later on in the analysis.' , placement = 'right')),
                value = 'Exp',
                width = '100%'
              )
            ),
            shiny::column(
              width = 3,
              shiny::textInput(
                inputId = 'group_CN',
                label = shiny::div('Sample group',
                                   bsplus::shiny_iconlink() %>%
                                     bsplus::bs_embed_popover(title = 'If cells have been sequenced in different experiments, providing the same group name allows to merge them after normalization. It can be modified later on in the analysis.' , placement = 'right')),
                value = 'Exp',
                width = '100%'
              )
            )
          ),
          shiny::fluidRow(shiny::column(
            width = 3,
            shinyjs::disabled(
              shiny::actionButton(
                inputId = 'AddSample_CN',
                label = 'Add Sample',
                width = '100%'
              )
            )
          )),
          shiny::fluidRow(shiny::column(
            width = 9,
            shiny::tableOutput('Samples_CN')
          )),
          shiny::fluidRow(shiny::column(
            width = 3,
            shinyjs::disabled(
              shiny::actionButton(
                inputId = 'Run_CN',
                label = 'Run',
                width = '100%'
              )
            )
          ))
        )

      },
      #####10X
      {
        shinydashboard::tabItem(
          tabName = "10X",
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shinyFiles::shinyFilesButton(
                id = 'PerCell_10X',
                label = div('PerCell',
                            bsplus::shiny_iconlink() %>%
                              bsplus::bs_embed_popover(title = '10XGenomics per_cell_summary_metrics.csv' , placement = 'right')),
                title = 'PerCell file',
                style = 'width:100%;',
                multiple = F
              )
            ),
            shiny::column(width = 9,
                          shiny::htmlOutput('PerCell_10X'))
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shinyFiles::shinyFilesButton(
                id = 'CNV_10X',
                label = shiny::div(
                  'CNV',
                  bsplus::shiny_iconlink() %>%
                    bsplus::bs_embed_popover(title = '10XGenomics node_cnv_calls.bed' , placement = 'right')),
                title = 'CNV_10X',
                style = 'width:100%;',
                multiple = F
              )
            ),
            shiny::column(width = 9,
                          shiny::htmlOutput('CNV_10X'))
          ),
          shiny::fluidRow(
            shiny::column(
              width = 3,
              shiny::textInput(
                inputId = 'Basename_10X',
                label = 'Basename',
                value = 'Exp',
                width = '100%'
              )
            ),
            shiny::column(
              width = 3,
              shiny::textInput(
                inputId = 'Group_10X',
                label = 'Group',
                value = 'Exp',
                width = '100%'
              )
            )),
            shiny::fluidRow(
              shiny::column(
                width = 3,
                shinyFiles::shinyDirButton(
                  id = 'Output_10X',
                  label = 'Results folder',
                  title = 'Results folder',
                  style = 'width:100%;'
                )
              ),
              shiny::column(width = 9,
                            shiny::htmlOutput('Output_10X'))
            ),
            shiny::fluidRow(
              shiny::column(
                width = 3,
                shinyjs::disabled(
                shiny::actionButton(inputId = 'Run_10X',label = 'Run',width = '100%'))
              )
            )
            )


      })
    )
  )

  server <- function(input, output, session) {
    #define operators
    `%>%` = tidyr::`%>%`
    `%do%` = foreach::`%do%`
    `%dopar%` = foreach::`%dopar%`

    #find max number of cores
    maxCores = parallel::detectCores()

    #set roots
    roots = c(shinyFiles::getVolumes()(),
              Home = Sys.getenv("HOME"))

    #set shinyFiles buttons
    shinyFiles::shinyDirChoose(
      input = input,
      id = 'Fastq',
      session = session,
      roots = roots,
      defaultRoot = 'Home'
    )

    shinyFiles::shinyDirChoose(
      input = input,
      id = 'out',
      session = session,
      roots = roots,
      defaultRoot = 'Home'
    )
    shinyFiles::shinyFileChoose(
      input = input,
      id = 'index',
      session = session,
      roots = roots,
      defaultRoot = 'Home'
    )
    shinyFiles::shinyFileChoose(
      input = input,
      id = 'Adapters',
      session = session,
      roots = roots,
      defaultRoot = 'Home'
    )
    shinyFiles::shinyFileChoose(
      input = input,
      id = 'fasta',
      session = session,
      roots = roots,
      defaultRoot = 'Home'
    )
    shinyFiles::shinyDirChoose(
      input = input,
      id = 'Output_10X',
      session = session,
      roots = roots,
      defaultRoot = 'Home'
    )
    shinyFiles::shinyFileChoose(
      input = input,
      id = 'CNV_10X',
      session = session,
      roots = roots,
      defaultRoot = 'Home'
    )
    shinyFiles::shinyFileChoose(
      input = input,
      id = 'PerCell_10X',
      session = session,
      roots = roots,
      defaultRoot = 'Home'
    )
    #define variables
    variables = reactiveValues(
      File1 = NULL,
      File2 = NULL,
      Adapters = NULL,
      out = NULL,
      fastq_dir = NULL,
      index = NULL,
      activate_start1 = F,
      activate_start2 = F,
      activate_start3 = F,
      proceed_run = F,
      info = dplyr::tibble()
    )

    variables_binning = reactiveValues(
      fasta = NULL,
      index = NULL,
      out = NULL,
      Bam_dir = NULL,
      blacklist = NULL,
      activate_start1 = F,
      activate_start2 = F,
      activate_start3 = F,
      activate_start4 = F,
      activate_start5 = T,
      read_size = 40,
      frag_size = 200,
      read_type = 'PE'
    )

    variables_10X = reactiveValues(
      Output_10X=NULL,
      PerCell_10X=NULL,
      CNV_10X=NULL,
    )

    ###10X to Kronos

    {
      #set output folder
      shiny::observeEvent(input$Output_10X, {
        if (!is.numeric(input$Output_10X)) {
          variables_10X$Output_10X = shinyFiles::parseDirPath(roots = roots, selection = input$Output_10X)
        } else{
          variables_10X$Output_10X = NULL
        }
        output$Output_10X = shiny::renderText(variables_10X$Output_10X)

      })

      #set PerCell_10X
      shiny::observeEvent(input$PerCell_10X, {
        if (!is.numeric(input$PerCell_10X)) {
          variables_10X$PerCell_10X = shinyFiles::parseFilePaths(roots = roots, selection = input$PerCell_10X)
          variables_10X$PerCell_10X = variables_10X$PerCell_10X$datapath
          variables_10X$PerCell_10X = Kronos.scRT::right_format(
            file_path = variables_10X$PerCell_10X,
            delim = ',',
            columns_to_check = c(
              "barcode",
              "cell_id",
              "total_num_reads",
              "num_unmapped_reads" ,
              "num_lowmapq_reads",
              "num_duplicate_reads" ,
              "num_mapped_dedup_reads",
              "frac_mapped_duplicates",
              "effective_depth_of_coverage",
              "effective_reads_per_1Mbp"  ,
              "raw_mapd",
              "normalized_mapd" ,
              "raw_dimapd",
              "normalized_dimapd" ,
              "mean_ploidy",
              "ploidy_confidence" ,
              "is_high_dimapd",
              "is_noisy"
            ),
            wrong_message = paste(
              '<b><p  style="color:#FF0000";>',
              variables_10X$PerCell_10X,
              'does not have the right format!</p></b>'
            ),
            rigth_message = variables_10X$PerCell_10X
          )
        } else{
          variables_10X$PerCell_10X = NULL
        }
        output$PerCell_10X = shiny::renderText(variables_10X$PerCell_10X)

      })

      #set CN_10X
      shiny::observeEvent(input$CNV_10X, {
        if (!is.numeric(input$CNV_10X)) {
          variables_10X$CNV_10X = shinyFiles::parseFilePaths(roots = roots, selection = input$CNV_10X)
          variables_10X$CNV_10X = variables_10X$CNV_10X$datapath
          variables_10X$CNV_10X = Kronos.scRT::right_format(
            file_path = variables_10X$CNV_10X,
            delim = '\t',skip = 2,
            columns_to_check = c(
              "#chrom",
              "start",
              "end",
              "id",
              "copy_number",
              "event_confidence"
            ),
            wrong_message = paste(
              '<b><p  style="color:#FF0000";>',
              variables_10X$CNV_10X,
              'does not have the right format!</p></b>'
            ),
            rigth_message = variables_10X$CNV_10X
          )
        } else{
          variables_10X$CNV_10X = NULL
        }
        output$CNV_10X = shiny::renderText(variables_10X$CNV_10X)

      })


      #basename and group
      shiny::observeEvent(input$Group_10X, {
        shiny::updateTextInput(inputId = 'Group_10X',value = stringr::str_replace(string = input$Group_10X,pattern = ' ',replacement = '_'))
          })

      shiny::observeEvent(input$Basename_10X, {
        shiny::updateTextInput(inputId = 'Basename_10X',value = stringr::str_replace(string = input$Basename_10X,pattern = ' ',replacement = '_'))
      })

      #allow to run if files are selected

      shiny::observeEvent(c(
        variables_10X$Output_10X,
        variables_10X$PerCell_10X,
        variables_10X$CNV_10X
      ),
      {
        if(!is.null(variables_10X$Output_10X) &
           !is.null(variables_10X$PerCell_10X)&
           !is.null(variables_10X$CNV_10X)){
          shinyjs::enable('Run_10X')
        }else{
          shinyjs::disable('Run_10X')
        }
      })

      #run conversion

      shiny::observeEvent(input$Run_10X,{

        results=Kronos.scRT::TenXtoKronos(PerCell = variables_10X$PerCell_10X,CNV =variables_10X$CNV_10X,basename = input$Basename_10X, input$Group_10X)
        results$PerCell%>%
          readr::write_csv(paste0(file.path(variables_10X$Output_10X, 'Kronos_format_'), basename(variables_10X$PerCell_10X)))

        results$CNV%>%
          readr::write_tsv(paste0(file.path(variables_10X$Output_10X, 'Kronos_format_'), stringr::str_replace(string = basename(variables_10X$CNV_10X),pattern = '.bed',replacement = '.tsv')))

        shiny::updateTextInput(inputId = 'Group_10X',value = 'Exp')
        shiny::updateTextInput(inputId = 'Basename_10X',value = 'Exp')

        variables_10X$PerCell_10X=NULL
        variables_10X$CNV_10X=NULL
        output$CNV_10X = shiny::renderText(variables_10X$CNV_10X)
        output$PerCell_10X = shiny::renderText(variables_10X$PerCell_10X)

      })


    }

    ##fastqToBam
    {
      #stop app when the session ends
      session$onSessionEnded(function() {
        shiny::stopApp()
      })

      #load tex input if PE format
      shiny::observeEvent(input$reads_type, {
        if (input$reads_type != 'SE') {
          output$patter_sample = shiny::renderUI({
            shiny::fluidRow(column(
              width = 3,
              shiny::textInput(
                inputId = 'R1',
                label = 'Pattern to identify R1 fastq',
                value = '_R1'
              )
            ),
            column(
              width = 3,
              shiny::textInput(
                inputId = 'R2',
                label = 'Pattern to identify R2 fastq',
                value = '_R2'
              )
            ))
          })
        } else{
          output$patter_sample = shiny::renderUI({
            NULL
          })
        }
      })


      ###select fastq folder
      shiny::observeEvent(input$Fastq, {
        output$final <- shiny::renderText(NULL)

        if (!is.numeric(input$Fastq)) {
          #recover fastq directory
          variables$fastq_dir = shinyFiles::parseDirPath(selection = input$Fastq, roots = roots)

          #check for fastq files
          if (length(list.files(path =  variables$fastq_dir, pattern = 'fastq|fq')) >
              0) {
            output$Fastq_out <- shiny::renderText(variables$fastq_dir)
            variables$activate_start1 = T
          } else{
            output$Fastq_out <-
              shiny::renderText(
                paste(
                  '<b><p style="color:#FF0000";> selected directory does not contain fastq files</b></p>'
                )
              )
            variables$activate_start1 = F
          }


        } else{
          variables$activate_start1 = F
          output$Fastq_out <- shiny::renderText(NULL)
        }
      })

      ###select index
      shiny::observeEvent(input$index, {
        output$final <- shiny::renderText(NULL)

        if (!is.numeric(input$index)) {
          #recover index directory
          variables$index = shinyFiles::parseFilePaths(selection = input$index, roots = roots)
          variables$index = variables$index$datapath

          #check that the selected file is actually part of an index
          if (stringr::str_detect(string = variables$index, pattern = '.bt2')) {
            variables$index = stringr::str_remove(variables$index, pattern = '.[0-9]{1,2}.bt2|.rev.[0-9]{1,2}.bt2')

            output$index_out <- shiny::renderText(variables$index)
            variables$activate_start3 = T
          } else{
            output$index_out <-
              shiny::renderText(
                paste(
                  '<b><p style="color:#FF0000";> selected file does not belong to a bowtie2 index.</b></p>'
                )
              )
            variables$activate_start3 = F
          }
        } else{
          variables$activate_start3 = F
          output$index_out <-
            shiny::renderText(NULL)
        }
      })

      ###select adapter
      shiny::observeEvent(input$Adapters,
                          {
                            if (!is.numeric(input$Adapters))
                            {
                              #recover index directory
                              variables$Adapters = shinyFiles::parseFilePaths(selection = input$Adapters, roots = roots)
                              variables$Adapters = variables$Adapters$datapath

                              #check that the selected file is actually part of an index
                              if (Kronos.scRT::right_format(
                                file_path = variables$Adapters,
                                columns_to_check = 1,
                                logical = T
                              )) {
                                variables$Adapters = readr::read_lines(variables$Adapters)

                                output$Adapters_out <-
                                  shiny::renderText(variables$Adapters)
                              } else
                              {
                                output$Adapters_out <-
                                  shiny::renderText(
                                    paste(
                                      '<b><p style="color:#FF0000";> Adapters file has to be a text file with one adapter per line, No header!</b></p>'
                                    )
                                  )
                              }
                            }
                          })

      ###select out folder
      shiny::observeEvent(input$out,
                          {
                            output$final <- shiny::renderText(NULL)
                            if (!is.numeric(input$out))
                            {
                              #recover fastq directory
                              variables$out = shinyFiles::parseDirPath(selection = input$out, roots = roots)

                              #check for fastq files
                              if (length(list.files(path =  variables$out)) == 0)
                              {
                                output$Output_out <- shiny::renderText(variables$out)
                                variables$activate_start2 = T
                              } else{
                                output$Output_out <-
                                  shiny::renderText(
                                    paste(
                                      '<b><p style="color:#FF0000";> selected directory is not empty</b></p>'
                                    )
                                  )
                                variables$activate_start2 = F
                              }
                            } else{
                              variables$activate_start2 = F
                              output$Output_out <-
                                shiny::renderText(NULL)
                            }
                          })

      ##activate start
      shiny::observeEvent(
        c(
          variables$activate_start1,
          variables$activate_start2,
          variables$activate_start3
        ),
        {
          if (variables$activate_start1 &
              variables$activate_start2 &
              variables$activate_start3)
          {
            shinyjs::enable('run')
          } else
          {
            shinyjs::disable('run')

          }

        }
      )

      ###start
      shiny::observeEvent(input$run,
                          {
                            if (input$run > 0)
                            {
                              #disable all buttons till the end of the run
                              shinyjs::disable('run')
                              shinyjs::disable('Fastq')
                              shinyjs::disable('out')
                              shinyjs::disable('reads_type')
                              shinyjs::disable('cores')
                              shinyjs::disable('Adapters')
                              shinyjs::disable('index')

                              all_files = list.files(
                                path = variables$fastq_dir,
                                pattern = 'fastq|fq',
                                ignore.case = T,
                                full.names = T
                              )
                              if (input$reads_type == 'PE')
                              {
                                R1 = stringr::str_detect(string = basename(all_files),
                                                         pattern = input$R1)
                                R2 = stringr::str_detect(string = basename(all_files),
                                                         pattern = input$R2)

                                variables$File1 = all_files[R1]
                                variables$File2 = all_files[R2]
                                #check if file names order is matching
                                if (all(
                                  stringr::str_split(
                                    string = variables$File1,
                                    pattern = input$R1,
                                    simplify = T
                                  )
                                  [, 1] == stringr::str_split(
                                    string = variables$File2,
                                    pattern = input$R2,
                                    simplify = T
                                  )[, 1]
                                )) {
                                  variables$proceed_run = T
                                } else
                                {
                                  variables$proceed_run = F

                                }

                              } else
                                if (input$reads_type == 'SE')
                                {
                                  variables$File1 = all_files
                                  variables$proceed_run = T

                                } else
                                {
                                  R1 = stringr::str_detect(string = all_files, pattern = input$R1)
                                  R2 = stringr::str_detect(string = all_files, pattern = input$R2)

                                  variables$File1 = all_files[R1]
                                  variables$File2 = all_files[R2]

                                  #check if file names order is matching
                                  if (all(
                                    stringr::str_split(
                                      string = variables$File1,
                                      pattern = input$R1,
                                      simplify = T
                                    )
                                    [, 1] == stringr::str_split(
                                      string = variables$File2,
                                      pattern = input$R2,
                                      simplify = T
                                    )[, 1]
                                  )) {
                                    variables$proceed_run = T

                                    cl = snow::makeCluster(input$cores)
                                    doSNOW::registerDoSNOW(cl)
                                    shiny::isolate({
                                      file1 = variables$File1
                                      file2 = variables$File2
                                      out = variables$out
                                    })
                                    variables$File1 = foreach::foreach(i = 1:length(variables$File1)) %dopar%
                                    {
                                      Kronos.scRT::mergefastq(
                                        FileList = c(file1[i], file2[i]),
                                        output = file.path(out, 'MergedFastq')
                                      )
                                    }
                                    snow::stopCluster(cl)
                                    variables$File2 = NULL
                                    variables$File1 = unlist(variables$File1)
                                    variables$proceed_run = T
                                  } else{
                                    variables$proceed_run = F
                                  }
                                }

                              if (variables$proceed_run) {
                                if (input$reads_type == 'PE') {
                                  variables$info = Kronos.scRT::FastqToBam(
                                    bowtie2_index = variables$index,
                                    File1 = variables$File1,
                                    File2 = variables$File2,
                                    outputdir = variables$out,
                                    adapters_list = variables$Adapters,
                                    cores = input$cores,
                                    Read_min_size_after_trimming = input$min_size,
                                    phred33 = input$phred33
                                  )
                                } else{
                                  variables$info = Kronos.scRT::FastqToBam(
                                    bowtie2_index = variables$index,
                                    File1 = variables$File1,
                                    outputdir = variables$out,
                                    adapters_list = variables$Adapters,
                                    cores = input$cores,
                                    Read_min_size_after_trimming = input$min_size,
                                    phred33 = input$phred33
                                  )
                                }

                                #save info
                                variables$info %>% readr::write_tsv(file = file.path(variables$out, 'FastqToBamMetrics.tsv'))

                                shinydashboard::updateTabItems(session = session,
                                                               inputId = 'Sidebar',
                                                               selected = 'Metrics')

                              } else {
                                output$final_plot1 <-
                                  shiny::renderPlot({
                                    NULL
                                  })
                                output$final_table <-
                                  shiny::renderTable({
                                    NULL
                                  })
                                output$final <-
                                  shiny::renderText(
                                    '<b><p style="color:#FF0000";> files do not match, check your fastq folder.</b></p>'
                                  )
                              }

                              #enable all buttons but run at the end of the run
                              shinyjs::enable('Fastq')
                              shinyjs::enable('out')
                              shinyjs::enable('reads_type')
                              shinyjs::enable('cores')
                              shinyjs::enable('Adapters')
                              shinyjs::enable('index')
                            }

                          })

      ####exit
      {
        shiny::observeEvent(input$Sidebar,
                            {
                              if (input$Sidebar == 'Exit') {
                                shinyjs::js$closeWindow()
                                shiny::stopApp()
                              }
                            })
      }

    }

    ####metrics
    {
      #shinyFiles buttons
      shinyFiles::shinyFileSave(
        input = input,
        id = 'Save_plots',
        session = session,
        defaultRoot = 'Home',
        roots = roots
      )
      shinyFiles::shinyFileSave(
        input = input,
        id = 'Save_table',
        session = session,
        defaultRoot = 'Home',
        roots = roots
      )
      shinyFiles::shinyFileChoose(
        input = input,
        id = 'Load_metrics',
        session = session,
        defaultRoot = 'Home',
        roots = roots
      )


      #upload data
      shiny::observeEvent(input$Load_metrics, {
        if (!is.numeric(input$Load_metrics)) {
          #recover path and upload data
          path = shinyFiles::parseFilePaths(roots = roots, selection = input$Load_metrics)

          #check type
          if (Kronos.scRT::right_format(
            file_path = path$datapath,
            columns_to_check = c('File', 'Parameter', 'Values', 'Category'),
            logical = T
          )) {
            variables$Metrics = readr::read_tsv(path$datapath) %>%
              dplyr::mutate(
                Parameter = factor(Parameter, levels = unique(Parameter)),
                Category = factor(Category, levels = unique(Category)),
                x = ifelse(
                  Category %in% c('Total Reads', 'Unmapped Fraction', 'Proper Pair'),
                  1,
                  as.numeric(Category)
                ) + sample(
                  seq(-0.2, 0.2, 0.001),
                  size = dplyr::n(),
                  replace = T
                )
              ) %>%
              dplyr::ungroup()
            #initialize Plot_selection
            variables$Metrics$Color = 'red'
            #active buttons
            shinyjs::enable('Save_plots')
            shinyjs::enable('Save_table')

            #update select parameters
            shiny::updateRadioButtons(
              session = session,
              inputId = 'final_table_selector',
              choices = unique(variables$Metrics$Parameter),
              inline = T
            )
            shinyjs::show('final_table_selector')

          } else{
            output$final_plot1 <- shiny::renderPlot(NULL)
            output$final_table <- shiny::renderText('Wrong File!')
            shinyjs::disable('Save_plots')
            shinyjs::disable('Save_table')
            shinyjs::hide('final_table_selector')

          }
        }
      })


      shiny::observeEvent(variables$info, {
        if (nrow(variables$info) > 0) {
          #add x variability for plotting
          variables$Metrics = variables$info %>%
            dplyr::mutate(
              Category = factor(Category, levels = unique(Category)),
              x = ifelse(
                Category %in% c('Total Reads', 'Unmapped Fraction', 'Proper Pair'),
                1,
                as.numeric(Category)
              ) + sample(
                seq(-0.2, 0.2, 0.001),
                size = dplyr::n(),
                replace = T
              )
            ) %>%
            dplyr::ungroup()
          #initialise Plot_selection
          variables$Metrics$Color = 'red'
          #active buttons
          shinyjs::enable('Save_plots')
          shinyjs::enable('Save_table')
          shiny::updateRadioButtons(
            session = session,
            inputId = 'final_table_selector',
            choices = unique(variables$info$Parameter),
            inline = T
          )
          shinyjs::show('final_table_selector')
        }
      })

      #brush plot 1
      shiny::observeEvent(input$final_plot_brush1, {
        if (!is.null(input$final_plot_brush1)) {
          #selected files
          Files = variables$Metrics %>%
            dplyr::filter(
              Parameter == input$final_plot_brush1$panelvar1,
              Values >= input$final_plot_brush1$ymin,
              Values <= input$final_plot_brush1$ymax,
              x >= input$final_plot_brush1$xmin,
              x <= input$final_plot_brush1$xmax
            ) %>% dplyr::pull(File)

          variables$Metrics = variables$Metrics %>%
            dplyr::mutate(Color = ifelse(File %in%  Files, 'red', 'black'))
        }
      })


      #reset with dbclick
      shiny::observeEvent(input$final_plot_dclick1,
                          {
                            #initialize reset
                            variables$Metrics = variables$Metrics %>%
                              dplyr::mutate(Color = 'red')
                          })

      #if something has been selected
      shiny::observeEvent(variables$Metrics, {
        variables$plot1 = variables$Metrics %>%
          dplyr::arrange(Color) %>%
          ggplot2::ggplot() +
          ggplot2::geom_boxplot(
            ggplot2::aes(Category, Values),
            outlier.size =  0,
            outlier.colour = NA,
            width = 0.8
          ) +
          ggplot2::geom_point(ggplot2::aes(x, Values, color = Color), alpha =
                                0.5) +
          ggplot2::theme_bw() +
          ggplot2::labs(x = '', y = '')  +
          ggplot2::theme(
            legend.position = 'none',
            axis.text.x = ggplot2::element_text(
              angle = 45,
              hjust = 1,
              vjust = 1
            )
          ) +
          ggplot2::scale_y_continuous(
           labels = function(x)
              sprintf(fmt = '%.1f', x)
          ) +
          ggforce::facet_row(
            ~ Parameter,
            scales = 'free',
            space = 'free',
            strip.position = 'right'
          ) +
          ggplot2::scale_color_manual(values = c('red' = 'red', 'black', 'black'))

        output$final_plot1 <-
          shiny::renderPlot({
            variables$plot1
          })
      })


      shiny::observeEvent(c(variables$Metrics, input$final_table_selector), {
        if (input$final_table_selector != '') {
          output$final_table <-
            shiny::renderTable(
              variables$Metrics %>%
                dplyr::filter(Parameter == input$final_table_selector,
                              Color == 'red') %>%
                dplyr::select(-x, -Color) %>%

                tidyr::spread(Category, Values)
            )
        }
      })

      ##save
      shiny::observeEvent(input$Save_plots, {
        if (!is.numeric(input$Save_plots)) {
          path = shinyFiles::parseSavePath(roots = roots, selection = input$Save_plots)

          ggplot2::ggsave(
            filename = path$datapath,
            plot = variables$plot1,
            device = grDevices::cairo_pdf,
            width = 12,
            height = 5
          )

        }
      })
      shiny::observeEvent(input$Save_table, {
        if (!is.numeric(input$Save_table)) {
          path = shinyFiles::parseSavePath(roots = roots, selection = input$Save_table)

          variables$Metrics %>%
            dplyr::select(-x, -Color) %>%
            readr::write_tsv(file = path$datapath)

        }
      })

    }
    ### Binning
    {
      #ui for auto selection of parameters
      output$Paramui_binning_out1 = shiny::renderUI({
        shiny::req(input$Param_binning == 'Auto')

        shiny::fluidRow(
          shiny::column(
            width = 3,
            shinyFiles::shinyDirButton(
              id = 'Bam_binning',
              label = 'Bam Files directory',
              title = 'Bam Files directory',
              style = 'width:100%;'
            )
          ),
          shiny::column(width = 6,
                        shiny::htmlOutput('Bam_binning_out'))
        )

      })

      #ui for auto selection of parameters

      output$Paramui_binning_out2 = shiny::renderUI({
        shiny::req(input$Param_binning == 'Manual')


        shiny::fluidRow(
          shiny::column(
            width = 3,
            shiny::radioButtons(
              inputId = 'Reads_type_binning',
              label = 'Reads type',
              choices = c('PE', 'SE'),
              selected = variables_binning$read_type,
              inline = T,
              width = '100%'
            )
          ),
          shiny::column(
            width = 3,
            shiny::sliderInput(
              inputId = 'Read_size_binning',
              label = 'Read size',
              min = 20,
              max = 300,
              value = variables_binning$read_size,
              step = 1,
              width = '100%'
            )
          ),
          shiny::column(width = 3,
                        shiny::uiOutput('Reads_type_binning'))
        )

      })

      output$Reads_type_binning = shiny::renderUI({
        shiny::req(input$Reads_type_binning == 'PE')


        shiny::sliderInput(
          inputId = 'Fragment_size_binning',
          label = 'Fragment size',
          min = 0,
          max = 1000,
          value = variables_binning$frag_size,
          step = 1,
          width = '100%'
        )
      })

      #set shinyfiles
      shinyFiles::shinyDirChoose(
        input = input,
        id = 'Bam_binning',
        session = session,
        roots = roots,
        defaultRoot = 'Home'
      )
      shinyFiles::shinyFileChoose(
        input = input,
        id = 'RefGenome_binning',
        session = session,
        roots = roots,
        defaultRoot = 'Home'
      )
      shinyFiles::shinyFileChoose(
        input = input,
        id = 'index_binning',
        session = session,
        roots = roots,
        defaultRoot = 'Home'
      )
      shinyFiles::shinyDirChoose(
        input = input,
        id = 'out_binning',
        session = session,
        roots = roots,
        defaultRoot = 'Home'
      )
      shinyFiles::shinyFileChoose(
        input = input,
        id = 'Blacklist_binning',
        session = session,
        roots = roots,
        defaultRoot = 'Home'
      )

      # if manual setting is put on SE hide fragment size
      shiny::observeEvent(input$Reads_type_binning, {
        if (input$Reads_type_binning == 'SE') {
          shinyjs::hide('Fragment_size_binning')
        } else{
          shinyjs::show('Fragment_size_binning')

        }
      })

      #select fasta file
      shiny::observeEvent(input$RefGenome_binning, {
        if (!is.numeric(input$RefGenome_binning)) {
          #recover path
          variables_binning$fasta = shinyFiles::parseFilePaths(roots = roots,
                                                               selection = input$RefGenome_binning)
          variables_binning$fasta = variables_binning$fasta$datapath
          output$RefGenome_binning_out = shiny::renderText({
            variables_binning$fasta
          })
          # first step to activate run
          variables_binning$activate_start1 = T
        } else{
          variables_binning$fasta = NULL
          output$RefGenome_binning_out = shiny::renderText({
            variables_binning$fasta
          })
          variables_binning$activate_start1 = F
        }
      })



      ###select index
      shiny::observeEvent(input$index_binning, {
        if (!is.numeric(input$index_binning)) {
          #recover index directory
          variables_binning$index = shinyFiles::parseFilePaths(selection = input$index_binning,
                                                               roots = roots)
          variables_binning$index = variables_binning$index$datapath

          #check that the selected file is actually part of an index
          if (stringr::str_detect(string = variables_binning$index, pattern = '.bt2')) {
            variables_binning$index = stringr::str_remove(variables_binning$index, pattern = '.[0-9]{1,2}.bt2|.rev.[0-9]{1,2}.bt2')

            output$index_binning_out <-
              shiny::renderText(variables_binning$index)
            variables_binning$activate_start2 = T
          } else{
            output$index_binning_out <-
              shiny::renderText(
                paste(
                  '<b><p style="color:#FF0000";> selected file does not belong to a bowtie2 index.</b></p>'
                )
              )
            variables$activate_start2 = F
          }
        } else{
          variables$activate_start2 = F
          output$index_binning_out <-
            shiny::renderText(NULL)
        }
      })

      ###select out folder
      shiny::observeEvent(input$out_binning,
                          {
                            if (!is.numeric(input$out_binning)) {
                              #recover out directory
                              variables_binning$out = shinyFiles::parseDirPath(selection = input$out_binning, roots = roots)

                              #render out dir
                              output$Output_binning_out <-
                                shiny::renderText(variables_binning$out)

                              variables_binning$activate_start3 = T
                            } else{
                              variables_binning$activate_start3 = F
                              output$Output_binning_out <-
                                shiny::renderText(NULL)

                            }
                          })

      #select bamfile folder
      shiny::observeEvent(input$Bam_binning, {
        if (!is.numeric(input$Bam_binning)) {
          #recover fastq directory
          variables_binning$Bam_dir = shinyFiles::parseDirPath(selection = input$Bam_binning, roots = roots)

          #check for fastq files
          if (length(list.files(path =  variables_binning$Bam_dir, pattern = '.bam')) >
              0) {
            output$Bam_binning_out <-
              shiny::renderText(variables_binning$Bam_dir)
            variables_binning$activate_start4 = T
          } else{
            output$Bam_binning_out <-
              shiny::renderText(
                paste(
                  '<b><p style="color:#FF0000";> selected directory does not contain fastq files</b></p>'
                )
              )
            variables_binning$activate_start4 = F
          }
        } else{
          variables_binning$activate_start4 = F
          output$Bam_binning_out <-
            shiny::renderText(NULL)
          variables_binning$Bam_dir = NULL
        }
      })

      #activate start4 if Manual parameters are selected
      shiny::observeEvent(input$Param_binning, {
        if (input$Param_binning == 'Auto') {
          variables_binning$activate_start4 = F
        } else{
          variables_binning$activate_start4 = T
        }
      })


      #select blacklist
      shiny::observeEvent(input$Blacklist_binning, {
        if (!is.numeric(input$Blacklist_binning)) {
          #recover index directory
          variables_binning$blacklist = shinyFiles::parseFilePaths(selection = input$Blacklist_binning,
                                                                   roots = roots)
          variables_binning$blacklist = variables_binning$blacklist$datapath

          #check that the selected file is actually part of an index
          if (Kronos.scRT::right_format(
            file_path = variables_binning$blacklist,
            columns_to_check = 3,
            logical = T
          )) {
            output$Blacklist_binning_out <-
              shiny::renderText(variables_binning$blacklist)
            variables_binning$activate_start5 = T
          } else{
            output$Blacklist_binning_out <-
              shiny::renderText(
                paste(
                  '<b><p style="color:#FF0000";> selected file does not have the required format.</b></p>'
                )
              )
            variables_binning$activate_start5 = F
          }
        } else{
          output$Blacklist_binning_out <-
            shiny::renderText(NULL)
          variables_binning$activate_start5 = T
          variables_binning$blacklist = NULL
        }

      })

      ##activate start
      shiny::observeEvent(
        c(
          variables_binning$activate_start1,
          variables_binning$activate_start2,
          variables_binning$activate_start3,
          variables_binning$activate_start4,
          variables_binning$activate_start5
        ),
        {
          if (variables_binning$activate_start1 &
              variables_binning$activate_start2 &
              variables_binning$activate_start3 &
              variables_binning$activate_start4 &
              variables_binning$activate_start5)
          {
            shinyjs::enable('run_binning')
          } else
          {
            shinyjs::disable('run_binning')

          }

        }
      )

      #manual parameters change
      shiny::observeEvent(input$Reads_type_binning, {
        variables_binning$read_type = input$Reads_type_binning
      })
      shiny::observeEvent(input$Read_size_binning, {
        variables_binning$read_size = input$Read_size_binning
      })
      shiny::observeEvent(input$Fragment_size_binning, {
        variables_binning$frag_size = input$Fragment_size_binning
      })

      #run
      shiny::observeEvent(input$run_binning, {
        if (input$run_binning > 0) {
          #disable buttons
          shinyjs::disable('RefGenome_binning')
          shinyjs::disable('index_binning')
          shinyjs::disable('out_binning')
          shinyjs::disable('Param_binning')
          shinyjs::disable('Bam_binning')
          shinyjs::disable('Coverage_binning')
          shinyjs::disable('Reads_type_binning')
          shinyjs::disable('Read_size_binning')
          shinyjs::disable('Fragment_size_binning')
          shinyjs::disable('Cores_binning')
          shinyjs::disable('Mappability_binning')
          shinyjs::disable('ErrorRate_binning')
          shinyjs::disable('Blacklist_binning')
          shinyjs::disable('chr_prefix_binning')
          shinyjs::disable('chr_range_binning')
          shinyjs::disable('BinSize_binning')
          shinyjs::disable('run_binning')

          #start binning
          bins = Kronos.scRT::binning(
            RefGenome = variables_binning$fasta,
            bowtie2_index =  variables_binning$index,
            bin_size =  input$BinSize_binning * 1000,
            read_size = variables_binning$read_size,
            fragment_size = variables_binning$frag_size,
            paired_ends = variables_binning$read_type == 'PE',
            directory_to_bamfiles = variables_binning$Bam_dir,
            tmp_dir = file.path(variables_binning$out, 'tmp'),
            upper_mappability_th = max(input$Mappability_binning),
            lower_mappability_th = min(input$Mappability_binning),
            black_list = variables_binning$blacklist,
            coverage = input$Coverage_binning,
            errorRate = input$ErrorRate_binning / 100,
            cores = input$Cores_binning,
            chr_prefix = ifelse(
              input$chr_prefix_binning == '',
              NULL,
              input$chr_prefix_binning
            ),
            chr_range = input$chr_range_binning,
            return_estimated_param = T
          )

          #if directory_to_bamfiles is given return parameters
          param = bins$param
          bins = bins$bins

          #write file
          readr::write_tsv(bins, file.path(
            variables_binning$out,
            paste0(
              basename(variables_binning$index),
              '_',
              input$BinSize_binning,
              'kb_bins_coverage_',
              input$Coverage_binning,
              'X_',
              paste0(
                'reads_',
                param$read_size,
                'bp_',
                ifelse(
                  param$paired_ends,
                  paste0('PE_fragmentSize_', param$fragment_size, 'bp_')
                  ,
                  'SE_'
                )
              ),
              ifelse(
                !is.null(variables_binning$blacklist),
                'blacklisted_',
                ''
              ),
              paste0(
                'error_rate_',
                input$ErrorRate_binning,
                '_min_mappability_',
                min(input$Mappability_binning),
                '_max_mappability_',
                max(input$Mappability_binning)
              ),
              '.tsv'
            )
          ))
          #enable
          shinyjs::enable('RefGenome_binning')
          shinyjs::enable('index_binning')
          shinyjs::enable('out_binning')
          shinyjs::enable('Param_binning')
          shinyjs::enable('Bam_binning')
          shinyjs::enable('Coverage_binning')
          shinyjs::enable('Reads_type_binning')
          shinyjs::enable('Read_size_binning')
          shinyjs::enable('Fragment_size_binning')
          shinyjs::enable('Cores_binning')
          shinyjs::enable('Mappability_binning')
          shinyjs::enable('ErrorRate_binning')
          shinyjs::enable('Blacklist_binning')
          shinyjs::enable('chr_prefix_binning')
          shinyjs::enable('chr_range_binning')
          shinyjs::enable('run_binning')
          shinyjs::enable('BinSize_binning')
        }
      })
    }
    #### CN
    {
      #set shiny Files buttons
      shinyFiles::shinyDirChoose(
        input = input,
        id = 'Bamdir_CN',
        session = session,
        roots = roots,
        defaultRoot =  'Home'
      )
      shinyFiles::shinyDirChoose(
        input = input,
        id = 'Output_CN',
        session = session,
        roots = roots,
        defaultRoot =  'Home'
      )
      shinyFiles::shinyFileChoose(
        input = input,
        id = 'Bins_CN',
        session = session,
        roots = roots,
        defaultRoot =  'Home'
      )
      shinyFiles::shinyFileChoose(
        input = input,
        id = 'ChrSize_CN',
        session = session,
        roots = roots,
        defaultRoot =  'Home'
      )

      #set variables
      variables_cn = reactiveValues(
        Bamdir_CN = NULL,
        Output_CN = NULL,
        Bins_CN = NULL,
        ChrSize_CN = NULL,
        Samples = dplyr::tibble(),
        run_ok1 = F,
        run_ok2 = F,
        sample_counter = 0,
        group_counter = 0
      )

      # ui if user wants fix ploidy average
      output$FixAveragePloidy = shiny::renderUI({
        shiny::req(input$Ploidy_Restrictions_CN == 'Fix Average Ploidy')
        shiny::fluidRow(shiny::column(
          width = 3,
          shiny::numericInput(
            inputId = 'meanPloidy_CN',
            label = 'Average ploidy',
            value = 2,
            min = 1,
            step = 0.1,
            width = '100%'
          )
        ))

      })

      # ui if user wants fix ploidy average
      output$FixPloidyRange = shiny::renderUI({
        shiny::req(input$Ploidy_Restrictions_CN == 'Fix Ploidy Range')
        shiny::fluidRow(
          shiny::column(
            width = 3,
            shiny::numericInput(
              inputId = 'minPloidy_CN',
              label = 'Min accepted ploidy',
              value = 2,
              min = 0,
              step = 0.1,
              width = '100%'
            )
          ),
          shiny::column(
            width = 3,
            shiny::numericInput(
              inputId = 'maxPloidy_CN',
              label = 'Max accepted ploidy',
              value = 8,
              min = 0,
              step = 0.1,
              width = '100%'
            )
          )
        )

      })

      #set output folder
      shiny::observeEvent(input$Output_CN, {
        if (!is.numeric(input$Output_CN)) {
          variables_cn$Output_CN = shinyFiles::parseDirPath(roots = roots, selection = input$Output_CN)
        } else{
          variables_cn$Output_CN = NULL
        }
        output$Output_CN = shiny::renderText(variables_cn$Output_CN)

      })

      #set BinsFile
      shiny::observeEvent(input$Bins_CN, {
        if (!is.numeric(input$Bins_CN)) {
          variables_cn$Bins_CN = shinyFiles::parseFilePaths(roots = roots, selection = input$Bins_CN)
          variables_cn$Bins_CN = variables_cn$Bins_CN$datapath
          variables_cn$Bins_CN = Kronos.scRT::right_format(
            file_path = variables_cn$Bins_CN,
            columns_to_check = c(
              'chr',
              'start',
              'end',
              'mappability',
              'mappability_th',
              'gc_frequency',
              'type'
            ),
            wrong_message = paste(
              '<b><p  style="color:#FF0000";>',
              variables_cn$Bins_CN,
              'does not have the right format!</p></b>'
            ),
            rigth_message = variables_cn$Bins_CN
          )
        } else{
          variables_cn$Bins_CN = NULL
        }
        output$Bins_CN = shiny::renderText(variables_cn$Bins_CN)

      })

      #authorize run if binsfile is good
      shiny::observeEvent(variables_cn$Bins_CN, {
        if (!is.null(variables_cn$Bins_CN) &
            stringr::str_detect(string = variables_cn$Bins_CN,
                                pattern = 'does not have the right format!</p></b>',
                                negate = T)) {
          variables_cn$run_ok1 = T
        } else{
          variables_cn$run_ok1 = F
        }
      })

      #set Chrsize
      shiny::observeEvent(input$ChrSize_CN, {
        if (!is.numeric(input$ChrSize_CN)) {
          variables_cn$ChrSize_CN = shinyFiles::parseFilePaths(roots = roots, selection = input$ChrSize_CN)
          variables_cn$ChrSize_CN = variables_cn$ChrSize_CN$datapath
          variables_cn$ChrSize_CN = Kronos.scRT::right_format(
            file_path = variables_cn$ChrSize_CN,
            columns_to_check = c('chr',
                                 'size'),
            wrong_message = paste(
              '<b><p  style="color:#FF0000";>',
              variables_cn$ChrSize_CN,
              'does not have the right format!</p></b>'
            ),
            rigth_message = variables_cn$ChrSize_CN
          )
        } else{
          variables_cn$ChrSize_CN = NULL
        }
        output$ChrSize_CN = shiny::renderText(variables_cn$ChrSize_CN)

      })

      #authorize run if Chrsize is good
      shiny::observeEvent(variables_cn$ChrSize_CN, {
        if (!is.null(variables_cn$ChrSize_CN) &
            stringr::str_detect(
              string = variables_cn$ChrSize_CN,
              pattern = 'does not have the right format!</p></b>',
              negate = T
            )) {
          variables_cn$run_ok2 = T
        } else{
          variables_cn$run_ok2 = F
        }
      })

      #set BAM folder
      shiny::observeEvent(input$Bamdir_CN, {
        if (!is.numeric(input$Bamdir_CN)) {
          variables_cn$Bamdir_CN = shinyFiles::parseDirPath(roots = roots, selection = input$Bamdir_CN)
          #check if file contains BAMS
          if (!any(stringr::str_detect(
            string = list.files(variables_cn$Bamdir_CN),
            pattern = '.bam$'
          ))) {
            variables_cn$Bamdir_CN = paste(
              '<b><p  style="color:#FF0000";>',
              variables_cn$Bamdir_CN,
              'does not contain bam files</p></b>'
            )
            shinyjs::disable('AddSample_CN')
          } else{
            shinyjs::enable('AddSample_CN')
          }
        } else{
          variables_cn$Bamdir_CN = NULL
          shinyjs::disable('AddSample_CN')
        }
        output$Bamdir_CN = shiny::renderText(variables_cn$Bamdir_CN)

      })

      #add samples
      shiny::observeEvent(input$AddSample_CN, {
        if (input$AddSample_CN > 0) {
          shinyjs::disable('AddSample_CN')
          variables_cn$Samples = rbind(
            variables_cn$Samples,
            dplyr::tibble(
              Basename = input$basename_CN,
              Group = input$group_CN,
              Bamfiles = variables_cn$Bamdir_CN
            )
          )

          output$Samples_CN = shiny::renderTable(variables_cn$Samples)

          #reset interface
          if (any(
            stringr::str_detect(
              string = variables_cn$Samples$Basename,
              pattern = '^Exp_{0,1}[0-9]{0,3}$'
            )
          )) {
            variables_cn$sample_counter = variables_cn$sample_counter + 1
            shiny::updateTextInput(
              inputId = 'basename_CN',
              value = paste0('Exp_', variables_cn$sample_counter)
            )
          } else{
            shinyjs::reset(input$basename_CN)
          }
          if (any(
            stringr::str_detect(string = variables_cn$Samples$Group, pattern = '^Exp_{0,1}[0-9]{0,3}$')
          )) {
            variables_cn$group_counter = variables_cn$group_counter + 1
            shiny::updateTextInput(
              inputId = 'group_CN',
              value = paste0('Exp_', variables_cn$group_counter)
            )
          } else{
            shinyjs::reset(input$group_CN)
          }

        }
      })

      #activate run
      shiny::observeEvent(
        c(
          variables_cn$Samples,
          variables_cn$run_ok1,
          variables_cn$run_ok2,
          variables_cn$Output_CN
        ),
        {
          if (variables_cn$run_ok1 &
              variables_cn$run_ok2 &
              nrow(variables_cn$Samples) > 0 &
              !is.null(variables_cn$Output_CN)) {
            shinyjs::enable('Run_CN')
          } else{
            shinyjs::disable('Run_CN')
          }
        }
      )

      shiny::observeEvent(input$Run_CN, {
        if (input$Run_CN > 0) {
          #load df
          Bins_CN = readr::read_tsv(variables_cn$Bins_CN)
          ChrSize_CN = readr::read_tsv(variables_cn$ChrSize_CN)
          shinyjs::disable('Run_CN')
          for (i in 1:nrow(variables_cn$Samples)) {
            if (input$Ploidy_Restrictions_CN != 'Fix Average Ploidy') {
              results = Kronos.scRT::CallCNV(
                directory = variables_cn$Samples$Bamfiles[i],
                bins = Bins_CN,
                chrom_size =  ChrSize_CN,
                basename = variables_cn$Samples$Basename[i],
                group = variables_cn$Samples$Group[i],
                tmp_dir = file.path(variables_cn$Output_CN, 'tmp'),
                min_n_reads = input$min_reads_CN,
                mim_mean_CN_accepted = ifelse(
                  is.null(input$minPloidy_CN),
                  2,
                  input$minPloidy_CN
                ),
                max_mean_CN_accepted = ifelse(
                  is.null(input$maxPloidy_CN),
                  8,
                  input$maxPloidy_CN
                ),
                chr_prefix = input$CHR_CN,
                chr_range = input$CHR_RANGE_CN,
                cores = input$Cores_CN
              )
            } else{
              results = Kronos.scRT::CallCNV(
                directory = variables_cn$Samples$Bamfiles[i],
                bins = Bins_CN,
                chrom_size =  ChrSize_CN,
                basename = variables_cn$Samples$Basename[i],
                group = variables_cn$Samples$Group[i],
                tmp_dir = file.path(variables_cn$Output_CN, 'tmp'),
                min_n_reads = input$min_reads_CN,
                ploidy = ifelse(
                  is.null(input$meanPloidy_CN),
                  2,
                  input$meanPloidy_CN
                ),
                chr_prefix = input$CHR_CN,
                chr_range = input$CHR_RANGE_CN,
                cores = input$Cores_CN
              )
            }
            dir = file.path(variables_cn$Output_CN,
                            variables_cn$Samples$Basename[i])
            if (!dir.exists(dir)) {
              dir.create(dir)
            }
            results$PerCell %>%
              readr::write_csv(file = file.path(
                dir,
                paste0(variables_cn$Samples$Basename[i], '_PerCell.csv')
              ))
            results$CNV %>%
              readr::write_tsv(file = file.path(
                dir,
                paste0(variables_cn$Samples$Basename[i], '_scCNV.tsv')
              ))
          }
        }
      })

    }


  }

  # Run the application
  shiny::shinyApp(ui = ui,
                  server = server)
CL-CHEN-Lab/User_interface_for_Kronos_scRT documentation built on Aug. 1, 2022, 2:08 p.m.