Detecting whether shiny runs the R code - r

I would like to run R code in two locations, in an Rnw file and as an interactive shiny R markdown document.
Thus, what I need, since interactive shiny components do not work in Rnw files, is a code snippet in R that detects whether to load the interactive code or not.
This seems to work, but it feels like a quick hack:
if (exists("input")) { # input is provided by shiny
# interactive components like renderPlot for shiny
} else {
# non-interactive code for Rnw file
}
Is there a stable solution or something like a global variable that I can access that says whether shiny is running at the moment? Or should I check whether the shiny package is loaded?
What's safest?

There is now a function shiny::isRunning().

This information is provided directly via Shiny’s isRunning function.
Outdated answer below:
You can do the following:
shiny_running = function () {
# Look for `runApp` call somewhere in the call stack.
frames = sys.frames()
calls = lapply(sys.calls(), `[[`, 1)
call_name = function (call)
if (is.function(call)) '<closure>' else deparse(call)
call_names = vapply(calls, call_name, character(1))
target_call = grep('^runApp$', call_names)
if (length(target_call) == 0)
return(FALSE)
# Found a function called `runApp`, verify that it’s Shiny’s.
target_frame = frames[[target_call]]
namespace_frame = parent.env(target_frame)
isNamespace(namespace_frame) && environmentName(namespace_frame) == 'shiny'
}
Now you can simply use shiny_running() in code and get a logical value back that indicates whether the document is run as a Shiny app.
This is probably (close to) the best way, according to a discussion on Shiny the mailing list — but do note the caveats mentioned in the discussion.
Adapted from code in the “modules” package.
Alternatively, the following works. It may be better suited for the Shiny/RMarkdown use-case, but requires the existence of the YAML front matter: It works by reading the runtime value from that.
shiny_running = function ()
identical(rmarkdown::metadata$runtime, 'shiny')

Update: After Konrad Rudolphs comment I rethought my approach. My original answer can be found down below.
My approach is different from Konrad Rudolphs and maybe different to the OPs initial thoughts. The code speaks for itself:
if (identical(rmarkdown::metadata$runtime, "shiny")) {
"shinyApp"
} else {
"static part"
}
I would not run this code from inside an app but use it as a wrapper around the app. If the code resides within a .Rmd with runtime: shiny in the YAML front matter it will start the app, if not, it will show the static part.
I guess that should do what you wanted, and be as stable as it could get.
My original thought would have been to hard code whether or not you were in an interactive document:
document_is_interactive <- TRUE
if (document_is_interactive) {
# interactive components like renderPlot for shiny
} else {
# non-interactive code for Rnw file
}
Although possible, this could lead to problems and would therefore be less stable than other the approach with rmarkdown::metadata$runtime.

Related

How do I log or trace using shinytest?

I would like to be able to see what happens inside the reactive({...}) parts in my code. I thought that using shinytest could be a way to execute parts of my application which use Shiny Modules and learn about callModule.
I tried the following in my code to log/trace/print.
print("hello1")
message("hello2")
cat(file=stderr(), "hello3")
logging::loginfo("hello4")
runtest.R
library(shinytest)
testApp("/home/eddy/rwork/filters", "mytest")
viewTestDiff("/home/eddy/rwork/filters", interactive = FALSE)
output:
Rscript runtest.R
Running mytest.R
==== Comparing mytest... No changes.
==== mytest ====
No differences between expected and current results
How can I add some trace output to the test run?
I don't think there's a really convenient way to see app output in shinytest right now, but there is this method on ShinyDriver objects:
app$getDebugLog() queries one or more of the debug logs: shiny_console, browser or shinytest.
https://rstudio.github.io/shinytest/reference/ShinyDriver.html
You could use this with the shiny_console option to print app output in individual tests like:
# mytest.R
app <- ShinyDriver$new()
...
log <- app$getDebugLog("shiny_console")
print(log)
shinytest integrates with the shiny concept of export values while in test, so you can use the function, shiny::exportTestValues() to create a named expressions with the values, including the reactive, you want to export.
For example, if you had the reactive data.frame, scaledData, that used some sort of input binding in your app code, you could do the following:
scaledData <- reactive({
dummyData[, "y"] <- dummyData[, "y"] * input$scale
return(dummyData)
})
# The scaledData will be captured as a json object in the shinytest output
exportTestValues(scaledData = scaledData())
This will capture the reactive value in the snapshot under the exports key in the json file, so you can then use this in your test comparisons (as well as view the data if you'd like).
One last note is that these export values only get run when the app is in test mode, e.g. isTRUE(getOption("shiny.testmode")).
I wrote a blog post about how I use this to test DataTables in shiny, you can read that here: https://nadirsidi.github.io/Shinytest/.
You can alocate an print(), cat(), warning() inside your reactive function to check value o class of your object inside R prompt. This works for me using only Shinny in RStudio without shinytest.
Additioanlly, as you said its not working the previous options, you can place a write.myformat() function in order to write any kind of object and check it externally.

scoping in shiny flexdashboard

I have a flexdashboard that uses shiny. Here's a MRE repo and gist of the .Rmd. When I put the app live on shinyapps.io, I realized that one user's actions could affect other users. I understand that this is a scoping issue, but I'm confused about how scoping works in Flexdashboard.
This page explains scoping for 'regular' shiny apps:
You might want some objects to be visible across all sessions. For example, if you have large data structures, or if you have utility functions that are not reactive (ones that don’t involve the input or output objects), then you can create these objects once and share them across all user sessions (within the same R process), by placing them in app.R , but outside of the server function definition.
In Flexdashboard, there is no app.R file or server function. How does scoping work in these types of shiny apps?
I have several eventReactive() functions like this that get updated for User 2 when User 1 hits submit and triggers observeEvent(input$submit, {}) at the end of the file.
eventReactive(rv$run2, {
if (remote==1) {
master$df <- drop_read_csv("/dash/master.csv", stringsAsFactors = FALSE)
} else {
master$df <- read.csv("dash/master.csv", stringsAsFactors = FALSE)
}
}, ignoreNULL = TRUE)
I originally posted this to RStudio Community about 9 hours ago, but it did not generate many views (<20) or any discussion.
Moving rv <- reactiveValues() out of the global chunk did the trick.

import file when not in use (any more)

I have a flexdashboard which is used by multiple users. They read, modify and write the same (csv) file. I haven't been able to figure out how to do this with a SQL connection so in the meantime (I need a working app) I would like to use a simple .csv file as a database. This should be fine since the users aren't likely to work on it the exact same time and loading and writing the full file is almost instant.
My strategy is therefore:
1-load file,
2-edit (edits are done in rhandsontable which is backconverted to a dataframe)
3-save:
(a)-loads file again (to get the latest data),
(b)-appends the edits from the rhandsontable and keeps the latest data (indicated by a timestamp)
(c)-write.csv
I'm thinking I should add something in (1) such that it checks if the file is not already in use/open (because an other user is at (3). So: check if open, if not-> continue, else-> sys.sleep(3) and try again.
Any ideas about how to do this in R? In Delphi it would be something like:
if fileinuse(filename) then sleep(3) else df<-read.csv
What's the R way?
Edit:
I'm starting with the my edited answer as it's more elegant. This uses a shell command to test whether a file is available as discussed in this question:
How to check in command-line if a given file or directory is locked (used by any process)?
This avoids loading and saving the file, and is therefor more efficient.
# Function to test availability
IsInUse <- function(fName) {
shell(paste("( type nul >> ", fName, " ) 2>nul && echo available || echo in use", sep=""), intern = TRUE)=="in use"
}
# Test availability
IsInUse("test.txt")
Original answer:
Interesting question! I did not find a way to check if a file is in use before trying to write to it. The solution below is far from elegant. It relies on a tryCatch function, and on reading and writing to a file to check if it is available (which can be quite slow depending on your file size).
# Function to check if the file is in use (relies on reading and writing which is inefficient)
IsInUse <- function(fName) {
rData <- read.csv(fName)
tryCatch(
{
write.csv(rData, file=fName, row.names = FALSE)
return(FALSE)
},
error=function(cond) {
return(TRUE)
}
)
}
# Loop to check if file is in use
while(IsInUse(fName)) {
print("Still in use")
Sys.sleep(0.1)
}
# Your action here
I also found the answer to this question useful How to write trycatch in R to make sense of the tryCatch function.
I'd be interested to see if anyone else has a more elegant suggestion!
Interesting question, indeed! Curious about an elegant solution too...

Which knitr hooks are invoked when a DiagrammeR graph is rendered in rmarkdown?

I have an RMarkdown document where I use data.tree and DiagrammeR to generate models. I then display these using a set-up similar to the one used in How to include DiagrammeR/mermaid flowchart in a Rmarkdown file
For example:
```{r fig.cap="Structureel model bij enkelvoudige regressie.", fig.with=4, fig.height=1}
drawStructuralModel <- function(covariates, criterion) {
### Create tree
res <- Node$new(criterion);
for (covariate in covariates) {
res$AddChild(covariate);
}
### Set display settings
SetEdgeStyle(res, dir='back');
res <- ToDiagrammeRGraph(res, direction = "descend");
res <- add_global_graph_attrs(res, "layout", "dot", "graph");
res <- add_global_graph_attrs(res, "rankdir", "RL", "graph");
### Draw and return tree
render_graph(res);
}
drawStructuralModel("X", "Y");
```
So far so good. The caption text is added, which is what you'd expect.
Except :-)
Above, in the 'setup' knitr chunk, I used setFigCapNumbering from userfriendlyscience (see https://github.com/Matherion/userfriendlyscience/blob/master/R/setFigCapNumbering.R). This function uses knit_hooks$set to set a hook for plots, so that the captions are automatically numbered.
But this numbering isn't applied to the DiagrammeR output.
I guess that makes sense, since it's not actually a plot, rather an HTML widget or some SVG or so. I would still like it to be numbered as a figure, though.
But how do I find out which hook knitr invokes when DiagrammeR output is generated?
I could always resort to using the more generic 'automatic caption' function setCaptionNumbering (https://github.com/Matherion/userfriendlyscience/blob/master/R/setCaptionNumbering.R), and tell it to use the same counter option as the figure caption thingy uses. That would sidestep the issue, but I'd prefer to modify the appropriate knitr hook.
And since this problem (figuring out which hook knitr uses for output produced by a given function) probably occurs more often, I thought it would be worth opening an SA question.
Does anybody know how you can find this out?
knitr calls knit_print on the output produced by a given chunk. This then calls the appropriate method based on the class of the output. You can find out what methods are available by running methods("knit_print"), then see if any of those match the class of the output from DiagrammeR.
Looking at your example, I'm guessing the class of your output is "DiagrammeR" "htmlwidget", so knitr is calling knit_print.htmlwidget.
Digging into that source code, it calls htmltools::knit_print.html, which wraps the tags and then outputs asis. So to answer your question, it uses the default hooks for asis output in whatever output format you're using.

Variables in Shiny to a sourced file via environment

Im trying to build a small shiny app that will call a sourced file once an actionButton is pressed. The actionButton observer will capture the input$topic and input$num from the ui.R and then call this source("downloadTweets.R") file that needs the topic and num variables defined in the environment to work properly.
# Entry shiny server function
shinyServer(function(input, output) {
observeEvent(input$searchButton, {
topic <- as.character(input$hashtagClass)
num <- as.numeric(input$numTweetsClass)
source("downloadTweets_Topic.R")
})
})
When I try to run it, there is an error message that outputs that topic value was not found once the source("downloadTweets_Topic.R") call is made. I'm fairly new to Shiny, I read the scope documentation and use the reactive() function, but I'm afraid that I don't really get how it works. Is there a way to do this or should I reimplement the .R file so I can pass these values to a function?
The reason I'm doing it like this is just merely code reusal from a different project in R Studio which is not a Shiny app.
Looks like the input$hashtagClass is missing. Throw a browser() line above that line but inside the observe expression. This'll drop you into a breakpoint when the app is run and this code is triggered. You can likely solve the issue with a req call. Look it up with ?req.
#pork chop's suggestion to add local=T to source is also important. This will put any assigned variables into the global env.

Resources