Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

renderImage() and .svg in shiny app

Tags:

r

shiny

I don't get renderImage()to work with a .svg file. My minimal example (adapted from the corresponding RStudio-tutorial):

ui.R

shinyUI(pageWithSidebar(
  headerPanel("renderSVG example"),
  sidebarPanel(
    sliderInput("obs", "Number of observations:",
                min = 0, max = 1000,  value = 500),
    actionButton("savePlot", "savePlot")
  ),
  mainPanel(
    # Use imageOutput to place the image on the page
    imageOutput("plot"),
    imageOutput("plot_as_svg")
  )
))

server.R

require("ggplot2")
library(svglite)

shinyServer(function(input, output, session) {
  
  ## create plot with renderPlot() 
  

      output$plot<- renderPlot({
        hist(rnorm(input$obs), main="Generated in renderPlot()")
        })

  
  ## create .svg file of the plot and render it with renderImage() 
  
  output$plot_as_svg <- renderImage({
    # A temp file to save the output.
    # This file will be removed later by renderImage
    outfile <- tempfile(fileext='.svg')
    
    # Generate the svg
    svglite(outfile, width=400, height=300)
    hist(rnorm(input$obs), main="Generated in renderImage()")
    dev.off()
    
    # Return a list containing the filename
    list(src = outfile,
         contentType = 'text/svg+xml',
         width = 400,
         height = 300,
         alt = "This is alternate text")
  }, deleteFile = TRUE)
  
})

Any ideas where the problem is?

like image 646
sammerk Avatar asked Aug 23 '16 06:08

sammerk


2 Answers

I struggled with this same issue, and there is nothing out on the web that I have found to address this problem which is frustrating. Here is the solution that worked for me:

ui.R:

shinyUI(pageWithSidebar(
  headerPanel("renderSVG example"),
  sidebarPanel(
    sliderInput("obs", "Number of observations:",
                min = 0, max = 1000,  value = 500),
    actionButton("savePlot", "savePlot")
  ),
  mainPanel(
    # Use imageOutput to place the image on the page
    imageOutput("plot"),
    imageOutput("plot_as_svg")
  )
))

server.R:

require("ggplot2")

shinyServer(function(input, output, session) {

  ## create plot with renderPlot()


      output$plot<- renderPlot({
        hist(rnorm(input$obs), main="Generated in renderPlot()")
        })


  ## create .svg file of the plot and render it with renderImage()

  output$plot_as_svg <- renderImage({

      width  <- session$clientData$output_plot_width
      height <- session$clientData$output_plot_height
      mysvgwidth <- width/96
      mysvgheight <- height/96

    # A temp file to save the output.
    # This file will be removed later by renderImage

    outfile <- tempfile(fileext='.svg')

    # Generate the svg
    svg(outfile, width=mysvgwidth, height=mysvgheight)
    hist(rnorm(input$obs), main="Generated in renderImage()")
    dev.off()

    # Return a list containing the filename
    list(src = normalizePath(outfile),
         contentType = 'image/svg+xml',
         width = width,
         height = height,
         alt = "My Histogram")
  })

})

Notice I did not use the svglite package, just the svg device from the grDevices (base) package. I also normalized the path in the source because I am on a Windows machine (I believe this will change my source from forward slashes to back slashes, but maybe someone will comment on that).

Also, I created four new variables to house the svg width and height and image width and height to still be fluid with the page. I'm sure there is an easier workaround than this, but this is what I found that worked.

like image 124
R_User123456789 Avatar answered Nov 15 '22 15:11

R_User123456789


Inspired by R_User123456789s solution (here) for base graphics above I got it the following way with ggplot2

ui.r

shinyUI(pageWithSidebar(
  headerPanel("renderSVG example"),
  sidebarPanel(
    sliderInput("obs", "Number of observations:",
                min = 0, max = 1000,  value = 500)
  ),
  mainPanel(
    # Use imageOutput to place the image on the page
    imageOutput("plot"),
    imageOutput("plot_as_svg")
  )
))

server.r

require("ggplot2")

shinyServer(function(input, output, session) {

  ## create plot with renderPlot()


  output$plot<- renderPlot({
    hist(rnorm(input$obs), main="Generated in renderPlot() as png")
  })


  ## create .svg file of the plot and render it with renderImage()

  output$plot_as_svg <- renderImage({

    width  <- session$clientData$output_plot_width
    height <- session$clientData$output_plot_height
    mysvgwidth <- width/96
    mysvgheight <- height/96

    # A temp file to save the output.
    # This file will be removed later by renderImage

    outfile <- tempfile(fileext='.svg')

    # Generate the svg
    #to see actually what will be plotted and compare 
    qplot(clarity, data=diamonds, fill=cut, geom="bar")
    #save the plot in a variable image to be able to export to svg
    image=qplot(clarity, data=diamonds[1:input$obs,], fill=cut, geom="bar", main = "ggplot as svg")
    #This actually save the plot in a image
    ggsave(file=outfile, plot=image, width=mysvgwidth, height=mysvgheight)

    # Return a list containing the filename
    list(src = normalizePath(outfile),
         contentType = 'image/svg+xml',
         width = width,
         height = height,
         alt = "My svg Histogram")
  })

})
like image 21
sammerk Avatar answered Nov 15 '22 15:11

sammerk