R/app.R

library(shiny)
library(mzR)
library(ggplot2)
library(gridExtra)

appwd <- dirname(getwd())   # Get the parent directory of the app
applibpath <- file.path(appwd, "packageLibrary") # Get the path for the "packageLibrary" folder
pwizFolderLocation <- installed.packages(applibpath) # List packages
pwizFolderLocation <- as.list(pwizFolderLocation[grep("proteowizardinstallation",pwizFolderLocation), ]) # find pwiz parent path
pwizFolderLocation <- file.path(pwizFolderLocation$LibPath,"proteowizardinstallation","pwiz") # create pwiz path

remove(appwd, applibpath)
plots <- new.env()


# Define UI for application that draws a histogram
ui <- fluidPage(

  # Application title
  titlePanel("GNPS Data Conversion and Spectra Quality Check"),
  # Sidebar with a slider input for number of bins
  sidebarLayout(
    sidebarPanel(
      actionButton("rawFolderInput", label = "Click to select folder where raw files are"),
      fluidRow(column(12, verbatimTextOutput("selectedFolderFileNames", placeholder = TRUE))),
      actionButton("outputDirectory", label = "Click to select where mzXML files should be created"),
      fluidRow(column(12, verbatimTextOutput("selectedOutputDirectory", placeholder = TRUE))),
      actionButton("convertFiles", label = "Click to Convert Files"),
      br(),
      br(),
      uiOutput("uib"),
      radioButtons("downloadType", choices = c(".eps", ".ps", ".tex", ".pdf", ".jpeg", ".tiff", ".png", ".bmp", ".svg", ".wmf"),inline=TRUE,label = "Image Type"),
      downloadButton("downloadImage", label = "Download Images"),
      h3("Warnings"),
      br(),
      uiOutput("noms2")

    ),

    # Show a plot of the generated distribution
    mainPanel(
      uiOutput("ms2Plots")
    )
  )
)

# Define server logic required to draw a histogram
server <- function(input, output, session) {

  #---------------------------------------------------------- Select directories
  # Selecting folder that contains raw data
  rawDataFolder <- reactive({
    if(is.null(input$rawFolderInput)){ }else if (input$rawFolderInput > 0){
      choose.dir(default = "", caption = "Select files")
    }
  })

  # Selecting folder that contains mzXML files (already-created or to-be-created)
  selectedDirectory <- reactive({
    if(is.null(input$outputDirectory)){ }else if (input$outputDirectory > 0){
      choose.dir()
    }
  })

  #---------------------------------------------------------- Display chosen directories

  # List files within the chosen raw-file directory
  rawData <- reactive ({
    if(is.null(rawDataFolder())){"No Folder Selected"}else{
      list.files(rawDataFolder(), recursive = FALSE)}
  })
  # Render text to display choices chosen
  output$selectedFolderFileNames <- renderText({
    if(is.null(rawDataFolder())){"No Folder Selected"}else{
      paste0(rawData(), "\n")} # Creates user feedback about which raw data folders were chosen.  Individual folders displayed on a new line "\n"
  })

  # Display chosen directory that (will) contain mzXML files
  output$selectedOutputDirectory <- renderText({
    if(is.null(selectedDirectory())){"No Folder Selected"}else{selectedDirectory()}})


  # Display radio selectors for selecting which mzXML file to display
  output$uib <- renderUI({
    if(is.null(selectedDirectory())){ }else{

      mzXMLFiles <- list.files(selectedDirectory(), pattern=".mzXML")
      mzXMLFiles2 <- list.files(selectedDirectory(), pattern=".mzXML", full.names = TRUE)
      radioButtons("radio", choices = mzXMLFiles2,label = "Converted Files:" )}
  })


  #---------------------------------------------------------- File Conversion

  # Convert raw to mzXML

  observeEvent(input$convertFiles, {
    rawFiles <- list.files(rawDataFolder(), recursive = FALSE, full.names = TRUE)
    fileNames <- sapply(rawFiles, function(x) strsplit(x, "\\.")[[1]][[1]])

     zz <- lapply(seq_along(fileNames), function(x){
      paste0(file.path(pwizFolderLocation, "msconvert.exe"), " ",
             paste0(rawFiles[[x]], collapse = "", sep=" "),
             "--filter \"peakPicking true 1-\"",
             " --mzXML --32 ",
             " -o ",
             selectedDirectory(),
             " --outfile ",
             paste0(fileNames[[x]],".mzXML", " --ignoreUnknownInstrumentError")
      )
    })

     lengthProgress <- length(zz)


     withProgress(message = 'Conversion in progress',
                  detail = 'This may take a while...', value = 0, {

                    for(i in zz){
                      incProgress(1/lengthProgress)

                      system(command = as.character(i))
                    }

                  })

  })


  #---------------------------------------------------------- Read mzXML

  readmzXML <- reactive({
    req(input$radio)
    mzXMLFiles <- list.files(selectedDirectory(), pattern=".mzXML")
    mzR::openMSfile(file = input$radio)

  })


  #----------------------------------------------------------

  ticMS1 <- reactive({

    list(TIC=mzXMLHeader()$totIonCurrent[mzXMLHeader()$msLevel==1])
  })

  mzXMLHeader <- reactive({
    mzR::header(readmzXML())
  })


observeEvent(input$radio,{
  output$noms2 <- renderUI("")


   if(!any(mzXMLHeader()$msLevel == 1)){ # If no MS1 scans present display warning...
      output$noms2 <- renderUI(paste(bquote(NO ~ MS[1] ~ datafound)))
  }

  if(!any(mzXMLHeader()$msLevel == 2)){   # If no MS2 scans present display warning...
    output$noms2 <- renderUI(HTML(paste0("No MS", tags$sup(2)," data found.")))
  }

})


observeEvent(input$radio, {

if(!any(mzXMLHeader()$msLevel == 2) & !any(mzXMLHeader()$msLevel == 1)){

}else if(!any(mzXMLHeader()$msLevel == 2)){

  output$ms2Plots <- renderUI({
    column(12,
           plotOutput("distPlot0")
    )})

}else if(!any(mzXMLHeader()$msLevel == 1)){
  output$ms2Plots <- renderUI({
    column(12,

           plotOutput("plot1"),
           plotOutput("plot2"),
           plotOutput("plot3")
    )})

}else{

   output$ms2Plots <- renderUI({
          column(12,
                 plotOutput("distPlot0"),
                 plotOutput("plot1"),
                 plotOutput("plot2"),
                 plotOutput("plot3"),
                 plotOutput("plot4")
          )})

}
})


#------------------------- Plots


# Plot MS1 Trace
output$distPlot0 <-  renderPlot({
    relInt <- max(mzXMLHeader()[mzXMLHeader()$msLevel == 1, ]$totIonCurrent) / max(mzXMLHeader()[mzXMLHeader()$msLevel == 1, ]$basePeakIntensity)
    plots$p0 <- ggplot(mzXMLHeader()[mzXMLHeader()$msLevel == 1, ]) +
      geom_line(aes(x = retentionTime / 60, y = totIonCurrent, colour = "TIC"))+
      geom_line(aes(x = retentionTime / 60, y = -basePeakIntensity * (max(totIonCurrent) / max(basePeakIntensity)), colour = "BPC"))+
      scale_y_continuous(sec.axis = sec_axis(~. * -(relInt), name = "BPC (As Negative Chromatogram)"))+
      scale_colour_manual(values = c("#1b9e77", "#7570b3"))+
      theme(legend.position = c(0.8, 0.9))+
      labs(y = "TIC", x = "Retention Time (min)", colour = "")+
      guides(colour = guide_legend(override.aes = list(size = rel(3)), reverse = T))

    plots$p0
})

output$plot1 <-  renderPlot({
    plots$p1 <-  ggplot(mzXMLHeader()[mzXMLHeader()$msLevel==2,]) +
      geom_point(aes(x = retentionTime/60, y = precursorMZ, alpha=basePeakIntensity)) +
      scale_alpha_continuous(range = c(0.1, 1), trans="log10")+
      xlab("Retention Time (min)") +
      ylab(bquote(Precursor ~ italic(m/z))) +
      labs(alpha= bquote(MS^2 ~ Base ~ Peak ~ Intensity))
    plots$p1
})

output$plot2 <-  renderPlot({

    plots$p2 <-  ggplot(mzXMLHeader()[mzXMLHeader()$msLevel==2,]) +
      geom_point(aes(x = retentionTime/60, y = peaksCount, alpha=basePeakIntensity, size=precursorMZ)) +
      scale_alpha(range = c(0.1, 1), trans="log10")+
      scale_size_continuous(range = c(.5, 3.5)) +
      xlab("Retention Time (min)") +
      ylab(bquote(Number ~ of ~ Peaks ~ "in" ~ MS^2 ~ Scan)) +
      labs(alpha= bquote(MS^2 ~ Base ~ Peak ~ Intensity), size= bquote(Precursor ~italic(m/z)))
    plots$p2
})

output$plot3 <-  renderPlot({
    plots$p3 <-  ggplot(mzXMLHeader()[mzXMLHeader()$msLevel==2,]) +
      geom_point(aes(x = precursorMZ, y = peaksCount, alpha=basePeakIntensity)) +
      scale_alpha(range = c(0.1, 1), trans="log10")+
      xlab(bquote(Precursor ~ italic(m/z))) +
      ylab(bquote(Number ~ of ~ Peaks ~ "in" ~ MS^2 ~ Scan)) +
      labs(alpha= bquote(MS^2 ~ Base ~ Peak ~ Intensity))
    plots$p3
})

output$downloadImage <- downloadHandler(
      filename = function(){paste0("Output", input$downloadType)},
    content = function(file1){

        q0<-plots$p0 +labs(tag="A")
        q1<-plots$p1 +labs(tag="B")
        q2<-plots$p2 +labs(tag="C")
        q3<-plots$p3 +labs(tag="D")


        captionTitle <- 'bold("Caption:")'
        captionA <- 'bold("A:")~" Description of plot A"'
        captionB <- 'bold("B:")~" Description of plot A"'
        captionC <- 'bold("C:")~" Description of plot A"'
        captionD <- 'bold("D:")~" Description of plot A"'


        q4 <- ggplot() +
          annotate("text", x = 2.5, y = 26, size=8, label = captionTitle, parse = TRUE) +
          annotate("text", x = 4, y = 25, size=8, label = captionA, parse = TRUE) +
          annotate("text", x = 4, y = 24, size=8, label = captionB, parse = TRUE) +
          annotate("text", x = 4, y = 23, size=8, label = captionC, parse = TRUE) +
          annotate("text", x = 4, y = 22, size=8, label = captionD, parse = TRUE) +
          theme_void()+
          coord_cartesian(xlim=c(2,6), ylim=c(20,30))


        l1 <- gridExtra::grid.arrange(q0)
        l2 <- gridExtra::grid.arrange(q1, q2, nrow = 1)
        l3 <- gridExtra::grid.arrange(q3, nrow = 1)
        ww <- gridExtra::grid.arrange(l1,l2,l3, nrow=3, heights=c(.9,.9,.9))

        ggplot2::ggsave(file1, plot=ww, width= 38, height= 28, units= "cm")
        if (file.exists(paste0(file1, input$downloadType)))
          file.rename(paste0(file1, input$downloadType), file1)
     }
)
}

# Run the application
shinyApp(ui = ui, server = server)
chasemc/GNPSeasy documentation built on May 30, 2019, 4:02 p.m.