Image slideshow in R Shiny - r

I am still learning R and thus would request the experts in this platform to help me out.
I am trying to create a slideshow of .jpg images in a panel in Shiny. The below code when I run in RStudio gives me the slideshow in the Plot window of RStudio.
folder <- "D:/Photos/Foreign Trips/2014_07_08_USA_Irvine/JulyAugust/"
file_list <- list.files(path=folder, pattern="*.jpg", full.names = TRUE)
for (j in 1:30) {
myJPG <- stack(file_list[[j]])
plotRGB(myJPG)
}
But, when I try to put the same code in server.R and try to call through ui.R, I don't get the slideshow or any image getting displayed. I am getting a blank page when I click on the tab "Photo Slides". I tried using renderUI, renderImage and renderPlot but none works.
ui.R
tabPanel("Photo Slides",
plotOutput("trvImg")
),
server.R
output$trvImg <- renderPlot({
folder <- "D:/Photos/Foreign Trips/2014_07_08_USA_Irvine/JulyAugust/"
file_list <- list.files(path=folder, pattern="*.jpg", full.names = TRUE)
for (j in 1:30) {
myJPG <- stack(file_list[[j]])
plotRGB(myJPG)
}
As a learner, I am sure I'm going wrong somewhere and thus seek your help.
Thanks

Another solution, with the slickR package (based on the slick javascript library).
library(shiny)
library(slickR)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
####
),
mainPanel(
slickROutput("slickr", width="500px")
)
)
)
server <- function(input, output) {
output$slickr <- renderSlickR({
imgs <- list.files("D:/Photos/Foreign Trips/2014_07_08_USA_Irvine/JulyAugust/", pattern=".png", full.names = TRUE)
slickR(imgs)
})
}
# Run the application
shinyApp(ui = ui, server = server)

library(shiny)
imgs <- list.files("D:/Photos/Foreign Trips/2014_07_08_USA_Irvine/JulyAugust/", pattern=".png", full.names = TRUE)
ui <- fluidPage(
titlePanel("Slideshow"),
sidebarLayout(
sidebarPanel(
actionButton("previous", "Previous"),
actionButton("next", "Next")
),
mainPanel(
imageOutput("image")
)
)
)
server <- function(input, output, session) {
index <- reactiveVal(1)
observeEvent(input[["previous"]], {
index(max(index()-1, 1))
})
observeEvent(input[["next"]], {
index(min(index()+1, length(imgs)))
})
output$image <- renderImage({
x <- imgs[index()]
list(src = x, alt = "alternate text")
}, deleteFile = FALSE)
}
# Run the application
shinyApp(ui = ui, server = server)
If you want the buttons below the image, you can do:
sidebarLayout(
sidebarPanel(
# actionButton("previous", "Previous"),
# actionButton("next", "Next")
),
mainPanel(
imageOutput("image"),
fluidRow(
column(1, offset=1, actionButton("previous", "Previous")),
column(1, offset=1, actionButton("next", "Next"))
)
)
)

I wanted to do the same, but needed a static html output so couldn't use Shiny. I created a simple revealjs presentation and then included this in the flexdashboard as an iframe.
revealjs:
---
title:
output:
revealjs::revealjs_presentation:
transition: convex
reveal_options:
loop: true
autoSlide: 3000
keyboard: false
progress: false
shuffle: true
embedded: true
---
```{r setup, include=FALSE}
library(tidyverse)
library(glue)
library(pander)
```
```{r echo = FALSE, results ='asis'}
files <- list.files(path="./path/to/dir", full.names = TRUE)
headers <- lapply(files,
function(f){glue("{data-background='{{f}}'}",
.open = "{{",
.close = "}}")
})
pandoc.header(headers, 2)
```
Then in my flexdashboard I added:
```{r}
tags$iframe(style = "height:400px; width:100%; scrolling=yes",
src ="./imageSlider.html")
```

Related

Loading RDS data from drop down menu not changing when selection is made in shiny R

I have created a drop-down menu where each item has an rds file that can be loaded for analysis. The code works perfectly fine when only one tab exists in the interface. When I add more than one tab in the app, Only the first item in the drop-down menu is selected.
Is there an optimal way to select and upload different objects from the drop-down menu, where a selection once made would be applied to all the tabs in the app.
Here is the sample code I have.
server.R
## Load required libraries
library('dplyr')
library('data.table')
library("DT")
library("ggplot2")
library("stringi")
library("cowplot")
library("tidyverse")
shinyServer(function(input, output, session)
{
################################################################################
inputfunc <- reactive(
{
infile <- input$rdsfile
if (is.null(infile)){
return(NULL)
}
rds_file <- readRDS(paste0('path to folder data/',infile))
}
)
## Load data- UMAP plot
sum_input <- reactive(
{
rds_file <- inputfunc()
if (is.null(rds_file))
{
return(invisible())
}
else
{
sc_file <- rds_file
## Do Some plotting
}
})
## Expression plots-1
sum2_input <- reactive(
{
rds_file <- inputfunc()
if (is.null(rds_file))
{
return(invisible())
}
else
{
sc_file <- rds_file
sometasktodo <- input$sometask
## Do Some plotting
}
}
)
## Render plots
output$plot_sum.output <- renderPlot(
{
print(sum_input())
})
## Downloading plots
output$plot_sum2.output <- renderPlot(
{
print(sum2_input())
})
})
ui.R
library("shiny")
library("shinythemes")
library("ggplot2")
shinyUI(fluidPage(
# theme = "bootstrap.css",
theme = shinytheme("readable"),
# themeSelector(),
titlePanel(h3("Demo Application", style= "font-family: 'American Typewriter'; color:#081d58"), windowTitle = "scVisualizer"),
hr(),
navbarPage("",
tabPanel(h4("Load Data"),
#########################################################################
selectInput(inputId = 'rdsfile',
label = 'Choose a file:',
choices = list.files(path = "./data",
full.names = FALSE,
recursive = FALSE), selected = list.files("./data")[1]),
column(12, align="center", br(), plotOutput(outputId= 'plot_sum.output', width = "700px", height = "500px"), #50%
)),
tabPanel(h4("Some Plots"),
sidebarPanel(textInput("sometask",label="Name"),submitButton("submit"), helpText("Enter symbol")),
column(12, align="center", br(), plotOutput('plot_sum2.output', width = "1000px", height = "500px")
))
)))
Nothing happens when I select the second item in the drop-down menu.
Edit- I also tried moving the selectInput into sidebarLayout and sidebarPanel and moved all the tabs into tabsetPanel under mainPanel still it's not working.
Any suggestions would be greatly helpful!

R Shiny - Pass user input (text and uploaded image) as parameter to generate report

I am trying to create a shiny application that allows users to enter text and upload an image. I would then like the text inputted by the user and image uploaded by the user to be downloaded as an html report in a similar format only with the headings, text, and image. My aim is to have multiple text boxes and associated images in a report that is downloaded.
I have the following code:
library(shiny)
library(rmarkdown)
ui <-
fluidPage(
titlePanel("QA Template"),
sidebarLayout(
sidebarPanel(
radioButtons('format', 'Document format', c('HTML'),
inline = TRUE),
downloadButton('downloadReport')
)),
mainPanel(
fluidRow(
h2("Presentation"),
column(5,h4("Titles"),
textAreaInput("inText", "Do titles properly convey
content?",height='100px',width='400px')),
column(1,h4("Upload Image"),
fileInput("file1",label="",
accept = c('image/png', 'image/jpeg','image/jpg')
)),
column(4,offset = 1,imageOutput('p1')))))
server <- function(input, output, session) {
inText<-reactive({textAreaInput()})
output$inText<-renderText({textAreaInput()})
file1 <- reactive({gsub("\\\\", "/", input$file1$datapath)})
output$p1<-renderImage({list(src = file1())})
downloadHandler(
filename =
paste("QA_report","file",".html",sep=""),
content = function(file) {
tempReport<-file.path(tempdir(),"QA_report.Rmd")
file.copy('QA_report.Rmd', tempReport,overwrite = TRUE)
##Parameters to pass
params <- list(text1=inText,pic1=file1)
rmarkdown::render(tempReport,output_file=file, params=params,
envir = new.env(parent = globalenv()))
}
)
}
shinyApp(ui = ui, server = server)
I also have this in the .Rmd:
---
title: "QA Template"
output: html_document
params:
text1: NA
pic1: NA
---
```{r include=FALSE}
library(knitr)
```
### Presentation
## Titles
# Do titles properly convey content?
```{r, results='asis',echo=FALSE,warning=FALSE}
print(params[["text1"]])
```
```{r, results='asis',echo=FALSE,warning=FALSE}
knitr::include_graphics(params[["pic1"]])
```
There is a small quirk with using renderImage() we need to set the deleteFile flag to FALSE. Otherwise, the file is read into the temp directory, displayed for the user and then deleted.
Not sure what you were trying to do here but it looks wrong textAreaInput is a UI function. You need to refer to the text flowing into the server with input$inText not output$inText or textAreaInput()
inText<-reactive({textAreaInput()})
output$inText<-renderText({textAreaInput()})
Here is the working code,
library(shiny)
library(rmarkdown)
ui <-fluidPage(
titlePanel("QA Template"),
sidebarLayout(
sidebarPanel(
radioButtons('format', 'Document format', c('HTML'),
inline = TRUE),
downloadButton('downloadReport')
),
mainPanel(
fluidRow(
h2("Presentation"),
column(5,h4("Titles"),
textAreaInput("inText", "Do titles properly convey
content?",height='100px',width='400px')),
column(1,h4("Upload Image"),
fileInput("file1",label="",
accept = c('image/png', 'image/jpeg','image/jpg')
)),
column(4,offset = 1,imageOutput('p1'))
)
)
)
)
server <- function(input, output, session) {
file1 <- reactive({gsub("\\\\", "/", input$file1$datapath)})
output$p1<-renderImage({
req(file1())
browser()
list(src = file1())
},deleteFile = FALSE)
output$downloadReport <- downloadHandler(
filename =
paste("QA_report","file",".html",sep=""),
content = function(file) {
tempReport<-file.path(tempdir(),"QA_report.Rmd")
file.copy('QA_report.Rmd', tempReport,overwrite = TRUE)
##Parameters to pass
params <- list(text1=input$inText,pic1=file1())
rmarkdown::render(tempReport,output_file=file, params=params,
envir = new.env(parent = globalenv()))
}
)
}
shinyApp(ui = ui, server = server)

How to export HTML Output using downloadHandler in R shiny?

I have an R shiny app using the compare_df function as part of the compareDF package and it produces an HTML output. I was wondering how to export this as an HTML file using downloadHandler? This is my attempt:
Partial Code
ui <- fluidPage(
sliderPanel(
downloadButton("Export_HTML", "Export as Data Listing")
),
# Main panel for displaying outputs ----
mainPanel(uiOutput('html'))
)
server <- function(input,output){
a<-- c("1","2","3")
diff<-compare_df(filedata2, filedata1, group_col = a)
output$html <- renderUI({
HTML(knit2html(text=diff[["html_output"]], fragment.only=TRUE))
})
output$Export_HTML <- downloadHandler(
filename = function() {
paste("Comparison-", Sys.Date(), ".html", sep = "")
},
content = function(file) {
saveWidget(as_widget(diff[["html_output"]]), file, selfcontained = TRUE)
}
)
}
To download html file when comparing two datasets, we need to have two files in application structure
app.R
report.Rmd
app.R
library(shiny)
library(diffobj)
library(rmarkdown)
ui <- fluidPage(
sidebarPanel(
downloadButton('downloadReport')
),
# Main panel for displaying outputs ----
mainPanel(htmlOutput('html'))
)
server <- function(input,output){
filedata1 <- data.frame(a = c(1,2,3,4), b= c(3,5,8,9))
filedata2 <- data.frame(a = c(1,2,3,4), b= c(4,5,8,10))
output$html <- renderUI({
HTML(as.character(diffPrint(filedata2, filedata1, color.mode="rgb", format="html",
style=list(html.output="diff.w.style"))))
})
output$downloadReport <- downloadHandler(
filename = function() {
paste('Compare-report', "html", sep = '.')
},
content = function(file) {
src <- normalizePath('report.Rmd')
# temporarily switch to the temp dir, in case you do not have write
# permission to the current working directory
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'report.Rmd', overwrite = TRUE)
out <- render('report.Rmd')
file.rename(out, file)
}
)
}
shinyApp(ui = ui, server = server)
report.Rmd
```{r, echo=FALSE}
filedata1 <- data.frame(a = c(1,2,3,4), b= c(3,5,8,9))
filedata2 <- data.frame(a = c(1,2,3,4), b= c(4,5,8,10))
HTML(as.character(as.character(diffPrint(filedata2, filedata1, color.mode="rgb", format="html",
style=list(html.output="diff.w.style")))))
```
You may want to take a look at the Shiny Tutorial page on using the download handler to produce HTML through an R Markdown template: https://shiny.rstudio.com/articles/generating-reports.html

Downloading wordcloud2 output as png/jpg on shiny

I am trying to download output from wordcloud2 on shiny.
My code is as below:
library(shiny)
library(htmlwidgets)
library(webshot)
ui <- shinyUI(fluidPage(mainPanel(
wordcloud2Output("wordcl"),
downloadButton(outputId = "savecloud"),
downloadButton(outputId = "savecloud2")
)))
server <- shinyServer(function(input, output, session) {
wordcl <- reactive ({
wordcloud2(demoFreq, color = "random-light", backgroundColor = "grey")
})
output$wordcl <- renderWordcloud2({ wordcl() })
##### SOLUTION 1 #########
output$savecloud <- downloadHandler(
filename = "word.png",
content = function(cloud) {
file.copy(wordcl(), cloud)
})
##### SOLUTION 2 ##########
output$savecloud2 <- downloadHandler(
saveWidget(wordcl(), file="temp.html", selfcontained = F),
webshot("temp.html", file = "word2.png",
cliprect = "viewport")
)
})
shinyApp(ui = ui, server = server)
I have tried two styles using downloadhandler as shown in the code but they return empty results.
Any insight on why they downloadhandler doesn't work or redirection on how best to effect the download function will be appreciated.
I managed to make my download work by using an example of download handler function posted on LeafletMaps here: Why is webshot not working with leaflets in R shiny?
My updated code is as below:
library(shiny)
library(htmlwidgets)
library(webshot)
library(wordcloud2)
#webshot::install_phantomjs()
ui <- shinyUI(fluidPage(mainPanel(
wordcloud2Output("wordcl"),
downloadButton(outputId = "savecloud")
)))
server <- shinyServer(function(input, output, session) {
wordcl <- reactive ({
wordcloud2(demoFreq, color = "random-light", backgroundColor = "grey")
})
output$wordcl <- renderWordcloud2({
wordcl()
})
output$savecloud <- downloadHandler(
filename = paste("wordcloud", '.png', sep=''),
content = function(file) {
owd <- setwd(tempdir())
on.exit(setwd(owd))
saveWidget(wordcl(), "temp.html", selfcontained = FALSE)
webshot("temp.html", delay =15, file = file, cliprect = "viewport")
})
})
shinyApp(ui = ui, server = server)
The solution given on the link seems to combine the solutions I was trying to implement in my original post.
The only issue is that it does not work when the app is deployed on shiny.io

How to update UI on file change

Hello I'm building a shinydashboard using several excel files.
I inserted links to these files in the footer of the box and I want to refresh the shinydashboard when changing something in my excel file.
I don't want to run the whole R code each time.
How can I re-render the Output once the file content changes?
Here an example:
sidebar <- dashboardSidebar(
sidebarMenu( menuItem("Hello", tabName = "Hello", icon = icon("dashboard"))
))
body <- dashboardBody(
tabItems(
tabItem(tabName = "Hello",
box(title = "my file",
footer = a("df.xlsx", href="df.xlsx" ) ,
DT::dataTableOutput("df1"),style = "font-size: 100%; overflow: auto;",
width = 12, hight = NULL, solidHeader = TRUE, collapsible = TRUE, collapsed = TRUE, status = "primary")
)))
ui <- dashboardPage(
dashboardHeader(title = "My Dashboard"),
sidebar,
body)
server <- function(input, output) {
output$df1 <- renderDataTable({
df <- read_excel("df.xlsx")
DT::datatable(df, escape = FALSE, rownames=FALSE,class = "cell-border",
options =list(bSort = FALSE, paging = FALSE, info = FALSE)
)
})
}
shinyApp(ui, server)
To monitor the change in a file you could use the cheksum of the file like this:
library(shiny)
library(digest)
# Create data to read
write.csv(file="~/iris.csv",iris)
shinyApp(ui=shinyUI(
fluidPage(
sidebarLayout(
sidebarPanel(
textInput("path","Enter path: "),
actionButton("readFile","Read File"),
tags$hr()
),
mainPanel(
tableOutput('contents')
)))
),
server = shinyServer(function(input,output,session){
file <- reactiveValues(path=NULL,md5=NULL,rendered=FALSE)
# Read file once button is pressed
observeEvent(input$readFile,{
if ( !file.exists(input$path) ){
print("No such file")
return(NULL)
}
tryCatch({
read.csv(input$path)
file$path <- input$path
file$md5 <- digest(file$path,algo="md5",file=TRUE)
file$rendered <- FALSE
},
error = function(e) print(paste0('Error: ',e)) )
})
observe({
invalidateLater(1000,session)
print('check')
if (is.null(file$path)) return(NULL)
f <- read.csv(file$path)
# Calculate ckeksum
md5 <- digest(file$path,algo="md5",file=TRUE)
# If no change in cheksum, do nothing
if (file$md5 == md5 && file$rendered == TRUE) return(NULL)
output$contents <- renderTable({
print('render')
file$rendered <- TRUE
f
})
})
}))
If I understand the question correctly, I'd say you need the reactiveFileReader function.
Description from the function's reference page:
Given a file path and read function, returns a reactive data source
for the contents of the file.
The file reader will poll the file for changes, and once a change is detected the UI gets updated reactively.
Using the gallery example as a guide, I updated the server function in your example to the following:
server <- function(input, output) {
fileReaderData <- reactiveFileReader(500,filePath="df.xlsx", readFunc=read_excel)
output$df1 <- renderDataTable({
DT::datatable(fileReaderData(), escape = FALSE, rownames=FALSE,class = "cell-border",
options =list(bSort = FALSE, paging = FALSE, info = FALSE)
)
})
}
With that, any changes I saved to 'df.xlsx' were propagated almost instantly to the UI.

Resources