R/sc_deTab.R

Defines functions genePlot getClusterHeatmap sc_de sc_deUI

Documented in genePlot getClusterHeatmap sc_de sc_deUI

#' Single Cell Differential Expession Tab UI
#'
#' @export
#' @return None
sc_deUI <- function(id) {
  ns <- NS(id)
  tagList(# Sidebar panel for inputs ----
          sidebarPanel(tabsetPanel(
            id = ns("goSideTabSet"),
            tabPanel(
              title = "DGE test",

              h4("Generate DE Data"),

              selectInput(
                ns("dgeTestCombo"),
                label = "Select Test Type",
                choices = list(
                  "MAST" = "MAST",
                  "Wilcoxon Rank Sum test" = "wilcox",
                  "Student's T-test" = "t",
                  "DESeq2" = "DESeq2",
                  "Logistic Regression" = "LR"
                )
              ),

              numericInput(
                ns("logFCdgeInput"),
                label = "Fold-Change Threshold >",
                min = 0,
                max = 10,
                value = 2
              ),

              numericInput(
                ns("adjPdgeInput"),
                label = "Adjusted P-value Threshold <",
                min = 0,
                max = 1,
                value = 0.05
              ),

              numericInput(
                ns("pctdgeInput"),
                label = "Minimum Cell Fraction of Genes",
                min = 0,
                max = 0.5,
                value = 0.25
              ),

              actionButton(ns("dgeButton"), label = "Get Gene Markers"),


              conditionalPanel(
                condition = "input.dgeButton > 0",
                ns = ns,

                checkboxInput(ns("dgeClusterCheck"), h4("Show All Clusters"), TRUE),

                conditionalPanel(
                  condition = "!input.dgeClusterCheck",
                  ns = ns,

                  numericInput(
                    ns("dgeClustInput"),
                    label = "Cluster to Display",
                    min = 1,
                    max = 8,
                    value = 0
                  )
                )
              )
            ),

            tabPanel(
              title = "Plots",

              h4("Cluster Heatmap"),

              numericInput(
                ns("clustHeatInput"),
                label = "Genes to display",
                min = 1,
                value = 10
              ),

              actionButton(ns("dgeHeatButton"), label = "Generate Heatmap"),

              tags$hr(),

              h4("Choose Gene and Plot"),

              textInput(ns("geneNameInput"), "Enter Gene Name"),

              radioButtons(
                ns("dgePlotType"),
                label = "Plot Type",
                c(
                  "Violin Plot" = 1,
                  "Feature Plot" = 2,
                  "RidgePlot" = 3
                )
              ),

              actionButton(ns("dgePlotButton"), label = "Generate Plot")
            )
          )),

          # Main panel for displaying outputs ----
          mainPanel(tabsetPanel(
            id = ns("deMainTabSet"),
            tabPanel(title = "Table",
                     htmlOutput(ns("helpDEInfo")),
                     DT::dataTableOutput(ns("dgeTable")),
                     conditionalPanel(condition = "input.dgeButton > 0",
                                      ns = ns,

                                      downloadButton(ns("deDownload"), "Download Table")

                     )

                     ),
            tabPanel(
              title = "Plot",
              value = "dePlotTab",

              plotOutput(ns("dgePlot"), width = "1280px", height = "720px"),
              downloadButton(ns("downloaddgePlot"), "Download Plot")
            )
          )))
}

#' Single Cell Differential Expession Tab Server
#'
#' @param finData Reactive value containing a seurat object with clustered data
#'
#' @export
#' @return  Returns Diffenretial Expression data
sc_de <- function(input, output, session, finData) {
  de <- reactiveValues()

  output$helpDEInfo <- renderUI({
    if(input$dgeButton == 0){
      HTML(
        "<div style='border:2px solid blue; font-size: 14px;
        padding-top: 8px; padding-bottom: 8px; border-radius: 10px;'>

        <p style='text-align: center'>
        <b>This tab enables DE analysis of clustering results.</b> </p> <br>
        To indentify Marker Genes for each cluster,
        proceed first by selecting the preferred DE method. <br>
        Then specify pre-filter options according to: <br>
        Fold-change, adj. P-value threshold,
        and genes expressed in a minimum fraction of cells. <br> <br>
        <i>Note: MAST was shown to be among
        the best scRNA-Seq DE methods (Soneson & Robinson, 2018),
        as such it is likely the best option here. </i>
        Also, please be patient as DE analysis is run on all clusters
        and as such it may take some time.
        MAST is particularly time consuming.  </div>"
        
      )
    } else {
      HTML("")
    }
  })

  ## Generate DE Data
  observeEvent(input$dgeButton, {
    waiter_show(html=tagList(spin_folding_cube(), h2("Loading...Stay Patient :)")))

    if(input$dgeTestCombo == "DESeq2"){
      finData$finalData[["RNA"]]@counts <- as.matrix(finData$finalData[["RNA"]]@counts) + 1
    }

    de$markers <- FindAllMarkers(
      finData$finalData,
      test.use = input$dgeTestCombo,
      min.pct = input$pctdgeInput,
      logfc.threshold = log(input$logFCdgeInput)
    )

    # Filter by adjusted P-value
    filter <- de$markers$p_val_adj < input$adjPdgeInput
    de$markers <- de$markers[filter,]


    waiter_hide()

    write.csv(de$markers, file=paste0(tempdir(),
                                      "/AllMarkerGenes_",
                                      input$dgeTestCombo,
                                      ".csv"), row.names = FALSE)

    output$dgeTable <-
      DT::renderDataTable(if (input$dgeClusterCheck) {
        de$markers[,1:(ncol(de$markers)-1)] %>% 
          rownames_to_column("gene_id") %>% 
          datatable(rownames = FALSE)
      } else{
        de$markers[de$markers$cluster == input$dgeClustInput,
                   1:(ncol(de$markers)-1)] %>%
          rownames_to_column("gene_id") %>% 
          datatable(rownames = FALSE)
      }, options = list(pageLength = 10))
  })


  ## Cluster Heatmap
  observeEvent(input$dgeHeatButton, {
    if (!is.null(de$markers)) {
      waiter_show(html=tagList(spin_folding_cube(), h2("Loading ...")))

      de$dgePlot <-
        getClusterHeatmap(finData$finalData, de$markers, input$clustHeatInput)

      hm.palette <-
        colorRampPalette(c("red", "white", "blue")) # Set the colour range

      de$dgePlot <- de$dgePlot +
        scale_fill_gradientn(colours = hm.palette(100))
      

      output$dgePlot <- renderPlot({
        de$dgePlot
      })

      waiter_hide()

      updateTabsetPanel(session, "deMainTabSet", selected = "dePlotTab")
    }
  })


  ## DE Plots
  observeEvent(input$dgePlotButton, {
    if (!is.null(de$markers)) {
      de$dgePlot <-
        genePlot(finData$finalData,
                 input$dgePlotType,
                 input$geneNameInput,
                 session)


      output$dgePlot <- renderPlot({
        de$dgePlot  +
          theme(axis.text.x = element_text(size = 18),
                axis.text.y = element_text(size = 18),  
                axis.title.x = element_text(size = 16),
                axis.title.y = element_text(size = 16))
      })

      updateTabsetPanel(session, "deMainTabSet", selected = "dePlotTab")

    } else {
      sendSweetAlert(
        session = session,
        title = "Marker Data Not Found",
        text = "Please run the differential expression pipeline first",
        type = "warning"
      )

    }
  })


  output$downloaddgePlot <- downloadHandler(
    filename = function() {
      paste("DEplot", device = ".png", sep = "")
    },
    content = function(file) {
      device <- function(..., width, height) {
        grDevices::png(
          ...,
          width = width,
          height = height,
          units = "px",
          pointsize = 14
        )
      }
      ggsave(
        file,
        plot = de$dgePlot,
        device = device,
        width = 1280,
        height = 720,
        limitsize = FALSE
      )
    }
  )

  output$deDownload <- downloadHandler(
    filename = function() {
      paste(format(Sys.time(), "%y-%m-%d_%H-%M"), "_deResults" , ".csv", sep = "")
    },
    content = function(file) {
      data <- de$markers

      write.csv(data, file)
    }
  )

  return(de)
}


#' Cluster Heatmap
#'
#' Heatmap generated with Suerat
#'
#' @param s_object Seurat object with clustered data
#' @param markers Differential expression data
#' @param geneNo Number of genes to be displayed
#'
#' @export
#' @return Returns DE Heatmap
getClusterHeatmap <- function(s_object, markers, geneNo) {
  topMarkers <-
    markers %>% 
    group_by(cluster) %>%
    top_n(n = geneNo, wt = avg_logFC)
  p <- DoHeatmap(s_object, features = topMarkers$gene)  +
    theme_classic(base_size = 14)
  return(p)
}


#' Gene Plots across clusters
#'
#' Function with exception handling that enables comparison of genes
#' across the different clusters
#'
#' @param finalData Seurat object with cluster data
#' @param plotType The desired plot type
#' @param geneName The name/symbol of the gene of interest
#'
#'
#' @export
#' @return Returns DE Gene Plots
genePlot <- function(finalData, plotType, geneName, session) {
  out <- tryCatch(
    {
      if (plotType == 1) {
        VlnPlot(finalData, features = geneName) +
          theme_classic(base_size = 20)

      } else if (plotType == 2) {
        FeaturePlot(finalData, features = geneName, pt.size = 1.5) +
          theme_classic(base_size = 20)

      } else if (plotType == 3) {
        RidgePlot(finalData, features = as.character(geneName))  +
          theme_classic(base_size = 20)
      }
    },
    error=function(cond) {

      sendSweetAlert(
          session = session,
          title = "Gene not found",
          text = "Please enter an existing gene name/symbol",
          type = "error"
      )

      return(NA)
    }
  )
  return(out)
}
dbdimitrov/BugleSeq documentation built on July 17, 2021, 1:02 p.m.