Shiny Module: Downloading all plots into a single PDF

Hello! I am working on moving my Shiny app to a module format. Currently, I can load a .fcs file, analyze it and output plots and a table. I now need to take the plot outputs from each ID and generate a single PDF. I have tried with and without the the ns labeling with the download server 'grid.arrange(ns(vals$plotSSC,vals$plotFL2))` but that didn't work. I think that keeping the download UI and server separate from the modules is correct, but I haven't found much literature to guild me.

Currently, if I click the download button it cannot find the vals function from the fcsGatingServer
Any help is much appreciated

Here is a simplified version of my code:

library(shiny)
library(flowCore)
library(flowMeans)
library(flowViz)
library(grid)

fcsGatingServer<-function(id){
  moduleServer(id, function(input, output, session) {
vals <- reactiveValues(plotSSC=NULL, plotFL2=NULL) 
 filePath<- reactive(input$file$datapath) 
 
  output$plotSSC <- renderPlot({ 
      
      myfcs <- read.FCS(paste(filePath()), alter.names=TRUE)
temp1<-as.data.frame(myfcsT)
      
      vals$plotSSC<-ggplot(data=temp1,aes(x=`FSC.A`,y=`SSC.A`)),  size=.5)+labs(title=("BDS77 Isotype"))+theme(plot.title = element_text(size = rel(0.8)))
      
 plot(myfcs[,c("FSC.A", "SSC.A")],pch=".",  xlab="FSC.A", ylab="SSC.A")

output$plotFL2 <- renderPlot({
    
    plot(myfcs[,c("FSC.A", "FL2.A")],pch=".",  xlab="FSC.A", ylab="PE")
######
downloadServer = function(input, output) {
   
  output$export = downloadHandler(
    filename = function() {"plots.pdf"},
    content = function(file) {
      pdf(file, onefile = TRUE)
      grid.arrange(ns(vals$plotSSC))
      dev.off()
    }
  )}
##############

fcsGatingUI<-function(id) {
  ns<-NS(id)
  
  sidebarLayout(
    sidebarPanel(
      fileInput(ns("file"), label =ns("File"), multiple = F, accept = ".FCS", buttonLabel ="Browse")
     
    ),
    mainPanel(
      splitLayout(cellWidths =c("50%","50%"), plotOutput(ns("plotSSC")), 
                  plotOutput(ns("plotFL2")))
    )
  )}


server <- function(input, output, session) {
  fcsGatingServer("BDS65 CD54")
  fcsGatingServer("BDS65 Isotype")
  downloadServer
}

ui <- fluidPage(
  downloadButton("export", label = "Generate report"),
  fcsGatingUI("BDS65 CD54"),
  fcsGatingUI("BDS65 Isotype")
)

  shinyApp(ui, server)  

I'm trying to look at your example but I think you may have missed a few brackets/parentheses in your editing.

ggplot(data=temp1,aes(x=FSC.A,y=SSC.A)), size=.5)
Are there supposed to be two parentheses after the SSC.A`?

Also are you missing a }) for both of your renderPlot({ ? I must be going crazy as I can't find them. :slight_smile:

I just to make sure I'm not missing any details before I look at it in more detail.

Hi flowcyto,

You may be interested by IFCshiny package for interactive analysis of imaging and conventional flow cytometry(DISCLAIMER,I am the maintainer)

Nonetheless, here are some lines that may help:

library(shiny)
library(ggplot2)
library(flowCore)
library(grid)
library(gridExtra)

fcsGatingServer <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      vals <- reactiveValues(plotSSC=NULL, plotFL2=NULL) 
      temp1 <- reactive({
        tryCatch({
          # as a reprex I used example fileS from flowCore package to mimic e.g.
          # a BDS65 CD54 or a BDS65 Isotype
          # in your app you will have to use input$file$datapath
          # In addition, channels in this file are not the same as what you may have in your own project
          # so you will have to modify the names accordingly
          if(id == "BDS65 CD54") {
            fcsFile <- system.file("extdata", "0877408774.B08", package="flowCore") #input$file$datapath
          } else {
            fcsFile <- system.file("extdata", "0877408774.E07", package="flowCore") #input$file$datapath
          }
          myfcs <- read.FCS(fcsFile, alter.names=TRUE)
          as.data.frame(exprs(myfcs))
        }, error = function(e) {
          stop("please input fcs file")
        })
      })
      
      output$plotSSC <- renderPlot({
        vals$plotSSC <- ggplot(data=temp1()) +
          geom_point(aes(x=`FSC.H`,y=`SSC.H`),size=.5) +
          labs(title=("FSC / SSC")) +
          theme(plot.title = element_text(size = rel(0.8)))
        # I don't really understand why you compute a ggplot and then use a base plot
        # plot(temp1()[,c("FSC.H", "SSC.H")],pch=".",  xlab="FSC.H", ylab="SSC.H")
        vals$plotSSC
      })
      output$plotFL2 <- renderPlot({
        vals$plotFL2 <- ggplot(data=temp1()) +
          geom_point(aes(x=`FSC.H`,y=`FL2.H`),size=.5) +
          labs(title=("FSC / FL2")) +
          theme(plot.title = element_text(size = rel(0.8)))
        # plot(temp1()[,c("FSC.H", "FL2.H")],pch=".",  xlab="FSC.H", ylab="FL2.H") # ylab="PE")
        vals$plotFL2
      })
      output$export <- downloadHandler(
        filename = function() {
          paste0("plot_",id,".pdf")
        },
        content = function(file) {
          g_tbl <- arrangeGrob(vals$plotSSC, vals$plotFL2,
                               nrow=1, ncol=2, respect = TRUE, heights = 1)
          ggsave(file, arrangeGrob(g_tbl), device = "pdf", width = 8.5, height = 11)
        }
      )
      vals
    }
  )
}

fcsGatingUI<-function(id) {
  ns<-NS(id)
  
  sidebarLayout(
    sidebarPanel(
      downloadButton(ns("export"), label = "Generate report"),
      fileInput(ns("file"), label ="File", multiple = FALSE, accept = ".FCS", buttonLabel ="Browse")
    ),
    mainPanel(
      splitLayout(cellWidths =c("50%","50%"),
                  plotOutput(ns("plotSSC")), 
                  plotOutput(ns("plotFL2")))
    )
  )
}


server <- function(input, output, session) {
  fcsGatingServer("BDS65 CD54")
  fcsGatingServer("BDS65 Isotype")
}

ui <- fluidPage(
  fcsGatingUI("BDS65 CD54"),
  fcsGatingUI("BDS65 Isotype")
)

shinyApp(ui, server)  

EDIT:
I read too quickly...
You want a pdf with all the plots inside:

library(shiny)
library(ggplot2)
library(flowCore)
library(grid)
library(gridExtra)

fcsGatingServer <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      vals <- reactiveValues(plotSSC=NULL, plotFL2=NULL) 
      temp1 <- reactive({
        tryCatch({
          # as a reprex I used example fileS from flowCore package to mimic e.g.
          # a BDS65 CD54 or a BDS65 Isotype
          # in your app you will have to use input$file$datapath
          # In addition, channels in this file are not the same as what you may have in your own project
          # so you will have to modify the names accordingly
          if(id == "BDS65 CD54") {
            fcsFile <- system.file("extdata", "0877408774.B08", package="flowCore") #input$file$datapath
          } else {
            fcsFile <- system.file("extdata", "0877408774.E07", package="flowCore") #input$file$datapath
          }
          myfcs <- read.FCS(fcsFile, alter.names=TRUE)
          as.data.frame(exprs(myfcs))
        }, error = function(e) {
          stop("please input fcs file")
        })
      })
      
      output$plotSSC <- renderPlot({
        vals$plotSSC <- ggplot(data=temp1()) +
          geom_point(aes(x=`FSC.H`,y=`SSC.H`),size=.5) +
          labs(title=("FSC / SSC")) +
          theme(plot.title = element_text(size = rel(0.8)))
        # I don't really understand why you compute a ggplot and then use a base plot
        # plot(temp1()[,c("FSC.H", "SSC.H")],pch=".",  xlab="FSC.H", ylab="SSC.H")
        vals$plotSSC
      })
      output$plotFL2 <- renderPlot({
        vals$plotFL2 <- ggplot(data=temp1()) +
          geom_point(aes(x=`FSC.H`,y=`FL2.H`),size=.5) +
          labs(title=("FSC / FL2")) +
          theme(plot.title = element_text(size = rel(0.8)))
        # plot(temp1()[,c("FSC.H", "FL2.H")],pch=".",  xlab="FSC.H", ylab="FL2.H") # ylab="PE")
        vals$plotFL2
      })
      vals
    }
  )
}

fcsGatingUI<-function(id) {
  ns<-NS(id)
  
  sidebarLayout(
    sidebarPanel(
      fileInput(ns("file"), label ="File", multiple = FALSE, accept = ".FCS", buttonLabel ="Browse")
    ),
    mainPanel(
      splitLayout(cellWidths =c("50%","50%"),
                  plotOutput(ns("plotSSC")), 
                  plotOutput(ns("plotFL2")))
    )
  )
}


server <- function(input, output, session) {
  v1 <- fcsGatingServer("BDS65 CD54")
  v2 <- fcsGatingServer("BDS65 Isotype")
  output$export <- downloadHandler(
    filename = function() {
      paste0("plot.pdf")
    },
    content = function(file) {
      g_tbl <- arrangeGrob(v1$plotSSC, v1$plotFL2,
                           v2$plotSSC, v2$plotFL2,
                           nrow=2, ncol=2, respect = TRUE, heights = rep(1, 2))
      ggsave(file, arrangeGrob(g_tbl), device = "pdf", width = 8.5, height = 11)
    }
  )
}

ui <- fluidPage(
  fcsGatingUI("BDS65 CD54"),
  fcsGatingUI("BDS65 Isotype"),
  downloadButton("export", label = "Generate report")
)

shinyApp(ui, server)  

Sorry! I took out a lot of code to try and make everything easier to follow and definitely deleted to many })'s. you are not going crazy. I should have double checked the the parentheses before posting

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.