Observer loop plot update in brilliant app

I wrote a simulation in R that I want to visualize with brilliant now. I put the bulk of the simulation in the observation unit to evaluate it. During this evaluation process, that is, for each iteration, I want to build the current status. The question is how can I achieve this, since in my actual code the plot rendering is only performed after the main observer has been evaluated. Is there a way, for example, to suspend the execution of the monitoring unit and resume it after updating the schedule?

Shouldn't there be more functionality from brilliant to solve such a case, since I could imagine that I was not the only one who would like to do something like this?

It would be nice if you could help me :)

Below is the skeleton code for the server and ui.

ui.R:

library(shiny) shinyUI(pageWithSidebar( headerPanel("... Simulation"), sidebarPanel( sliderInput("epochs", "Number of Epochs:", min = 1, max = 100, value = 10), verbatimTextOutput("curr.iter"), actionButton("actionB", "Action!") ), mainPanel( plotOutput("distPlot") ) )) 

server.R:

 library(shiny) sinus <- data.frame() shinyServer(function(input, output) { dummy <- reactiveValues(iter=0) obsMain <- observe({ for (i in 1:input$epochs) { cat(i, " ") x <- seq(1:input$epochs) y <- sin(x) sinus <<- data.frame(x, y) dummy$iter <- i # # At this time I want distPlot & curr.iter to be evaluated/updated! # Sys.sleep(1) } }, suspended=TRUE) obsAction <- observe({ if(input$actionB > 0) obsMain$resume() }) # Helps to avoid initial evaluation of obsMain... output$curr.iter <- renderText({ as.numeric(dummy$iter) }) output$distPlot <- renderPlot({ if (dummy$iter > 1) plot(sinus, type="l") }) }) 
+8
r shiny
source share
2 answers

I already thought a little about it. I believe that the correct solution is to use invalidateLater to plan work in small pieces, but allow other reactive dependencies to interrupt our long-term process in order to do things like updating schedules.

I put together a quick example at https://gist.github.com/trestletech/8608815 . You can run this with

 runGist(8608815) 

The basic premise is that we do some lengthy iterative calculations, like what was done in your simulator, but we do it in small pieces to allow other reactive tools to work between them. My code is very simple to execute, so I can process 100,000 iterations of my loop in 1 second, which is about how long I will wait for my application to update interactively. I want to do 5 million iterations, so I plan to spend 50 pieces.

Each time I run a fragment of 100,000 iterations, I update a couple of reactive values ​​that spawn some other updates that end up being sent to my user interface in renderText (although a renderPlot , like yours, will work the same way). If you run the application, you will see that these reagents are updated between each piece that I run, before the next fragment is launched.

There is a bit of overhead with this method, so your calculation may drop slightly. But on my machine, 5 million iterations took 21 seconds while running on the console at the same time and took 23 seconds in this model with delayed sending. Of course, you can control this by making large chunks.

Let me know what you think. I think it makes sense to wrap this up and include it in Shiny or as an expansion pack.

+7
source share

Since you have a Sys.sleep() call in your code, I assume that you want to use only one iteration per second. In this case, you can install reactiveTimer , which will evaluate the code every second. Inside this timer, you run the code for the current iteration, then raise the dummy$iter variable.

0
source share

All Articles