shinystan icon indicating copy to clipboard operation
shinystan copied to clipboard

Shinystan animated

Open saudiwin opened this issue 8 years ago • 9 comments

I am submitting a pull request that creates a new Animation tab within the Explore page. I had this idea for a while that it would be useful to animate the time dimension instead of looking at chains in a "flat" dimension like a line graph. I've also benefited a lot from shinystan, so I wanted to give a bit back. My code makes use of the gg_animate package to create a .WEBM movie from scatterplots of one or more X variables and a single Y variable. The gg_animate package will produce one frame for each iteration in the Markov chain. Furthermore, I used the tweenr package to add interpolation between the Markov transitions; this enables the animation to run very smoothly.

The package also requires use of the ffmpeg library. I included a markdown file that loads in the animation tab explaining what the user must do in order to create movies.

Currently I have tested the animation using sample data from the rstan package; the test file is in the tests folder. It seems to work with a range of options, including many of the options from the bivariate scatterplot (on which I largely based the code). I have tried to keep my code separate as much as possible from other shinystan functions, and also to use current code format and method.

The resulting videos are fairly high quality (default setting 2000x1000 pixels). However, production of the plots is slow as ggplot has to create a separate graph for each animation. But once the files are produced, they can be downloaded for later storage.

The animation options allow the user to select varying levels of quality in terms of picture size, and also to control animation speed and smoothness. Generally, a more smooth animation results in more frames produced and more time required.

For example, to produce a smooth animation for 200 iterations with 10 smoothing frames, ggplot2 must produce 2,000 separate images, and requires about half an hour of CPU time. This processing could be done in parallel, but would require some work on the gganimate package.

On the plus side, .WEBM files can be uploaded directly to youtube, as I just did with this example. On the downside, it may not display in Safari or Internet Explorer without the user downloading additional plugins.

saudiwin avatar Jun 14 '16 17:06 saudiwin

This is really cool. Thanks! I played around with something like this for shinystan a while ago and then had to put it off to work on other things. So this is a nice surprise!

I've only taken a quick glance at it so far but I'll review the whole thing soon and get back to with questions and feedback.

Thanks again!

On Tuesday, June 14, 2016, saudiwin [email protected] wrote:

I am submitting a pull request that creates a new Animation tab within the Explore page. I had this idea for a while that it would be useful to animate the time dimension instead of looking at chains in a "flat" dimension like a line graph. I've also benefited a lot from shinystan, so I wanted to give a bit back. My code makes use of the gg_animate package to create a .WEBM movie from scatterplots of one or more X variables and a single Y variable. The gg_animate package will produce one frame for each iteration in the Markov chain. Furthermore, I used the tweenr package to add interpolation between the Markov transitions; this enables the animation to run very smoothly.

The package also requires use of the ffmpeg library. I included a markdown file that loads in the animation tab explaining what the user must do in order to create movies.

Currently I have tested the animation using sample data from the rstan package; the test file is in the tests folder. It seems to work with a range of options, including many of the options from the bivariate scatterplot (on which I largely based the code). I have tried to keep my code separate as much as possible from other shinystan functions, and also to use current code format and method.

The resulting videos are fairly high quality (default setting 2000x1000 pixels). However, production of the plots is slow as ggplot has to create a separate graph for each animation. But once the files are produced, they can be downloaded for later storage.

The animation options allow the user to select varying levels of quality in terms of picture size, and also to control animation speed and smoothness. Generally, a more smooth animation results in more frames produced and more time required.

For example, to produce a smooth animation for 200 iterations with 10 smoothing frames, ggplot2 must produce 2,000 separate images, and requires about half an hour of CPU time. This processing could be done in parallel, but would require some work on the gganimate package.

On the plus side, .WEBM files can be uploaded directly to youtube, as I just did with this example https://youtu.be/ARUDHjsl61o. On the downside, it may not display in Safari or Internet Explorer without the

user downloading additional plugins.

You can view, comment on, or merge this pull request online at:

https://github.com/stan-dev/shinystan/pull/126 Commit Summary

  • Modify explore page to add an animation option
  • developing new site for explore animate tab
  • make animate_options source
  • Add selection options for animate very similar to trivariate option in explore page, but instead use a single select option for the y axis and multiple select for the x axis. This allows the animation of multiple variables together compared to a single third (y) variable.
  • create basic plot function for animate in animate.R
  • added tweened and gganimated function to animate.R. should have basic graphs working now in the explore tab
  • update animate_plot function to be reactive to .animate_plot
  • fixed variable name scoping issue with regard to ggplot2 aes function
  • now have params loaded from the input$param upper left-hand dialog box instead of the one in the tab animate itself
  • removed mention of id variable in melt function because tweenR removes that variable
  • fixed .png issue (changed to .gif)
  • added an action button so that it only animates when you hit the button
  • trying to get a better usage of the action button by moving it down closer to the underlying .animate_plot function
  • Fixed issue where returning a NULL to renderImage produced an error because renderImage requires a file reference. Instead, before the user clicks the Animate button, a blank .png image is returned to renderImage. Sort of a hack, but it works.
  • add annotations to moving points, fix download button
  • fixed action button
  • still don't have GIF download fixed yet. adding options tracker
  • attempt to get all options working
  • further work on customizing display options for the animate plot
  • trying to fix the transforms
  • add frame speed option
  • add chain selection options
  • bugfixes on correct number of chains
  • trying to get chain options to work for multiple chains with one parameter
  • switching to video, better files
  • Have video working, still trying to figure out download code
  • basic error checking on chain numbers now working
  • working on getting divergent transitions to show correctly
  • update ignore
  • adding more option to control display and selection of rows
  • bug fixed for new options
  • now have options working
  • finished with adjusting video options
  • documentation, add standardize function
  • Add more help text and adjust video options
  • adjust video settings. add detailed help information when tab loads (including checks for whether the system file libraries exist).
  • Rmarkdown file working correctly, still trying to get video options working right
  • fixing video options
  • made new save functions to streamline video processing and also add greater control
  • new video creation functions working, minor bugfixes
  • minor viewing changes
  • lowered default number of iterations to animate
  • bugfix
  • unnecessary file
  • prepare for pull
  • added additional packages used under "Depends" option because they are not imported, they only need to be installed
  • add knitr to depends because it is used to create markdown file for animate intro
  • fixed mistake
  • cleaning up for pull
  • cleanup
  • final changes
  • final commit
  • not needed

File Changes

  • M .Rbuildignore https://github.com/stan-dev/shinystan/pull/126/files#diff-0 (7)
  • M .gitignore https://github.com/stan-dev/shinystan/pull/126/files#diff-1 (20)
  • D .travis.yml https://github.com/stan-dev/shinystan/pull/126/files#diff-2 (9)
  • M DESCRIPTION https://github.com/stan-dev/shinystan/pull/126/files#diff-3 (5)
  • M inst/ShinyStan/helper_functions/shinystan_helpers.R https://github.com/stan-dev/shinystan/pull/126/files#diff-4 (223)
  • A inst/ShinyStan/markdown/about_video.Rmd https://github.com/stan-dev/shinystan/pull/126/files#diff-5 (34)
  • A inst/ShinyStan/markdown/about_video.md https://github.com/stan-dev/shinystan/pull/126/files#diff-6 (28)
  • M inst/ShinyStan/server.R https://github.com/stan-dev/shinystan/pull/126/files#diff-7 (4)
  • A inst/ShinyStan/server_files/pages/explore/server/animate.R https://github.com/stan-dev/shinystan/pull/126/files#diff-8 (85)
  • A inst/ShinyStan/server_files/pages/explore/ui/ui_animate_select_y.R https://github.com/stan-dev/shinystan/pull/126/files#diff-9 (9)
  • A inst/ShinyStan/server_files/utilities/new_saveVideo.R https://github.com/stan-dev/shinystan/pull/126/files#diff-10 (101)
  • M inst/ShinyStan/server_utils.R https://github.com/stan-dev/shinystan/pull/126/files#diff-11 (162)
  • A inst/ShinyStan/server_utils_changeres.R https://github.com/stan-dev/shinystan/pull/126/files#diff-12 (166)
  • M inst/ShinyStan/ui_files/PAGE_explore.R https://github.com/stan-dev/shinystan/pull/126/files#diff-13 (16)
  • A inst/ShinyStan/ui_files/animate_customize.R https://github.com/stan-dev/shinystan/pull/126/files#diff-14 (153)
  • A inst/ShinyStan/ui_files/animate_select.R https://github.com/stan-dev/shinystan/pull/126/files#diff-15 (26)
  • A inst/ShinyStan/ui_files/animate_select2.R https://github.com/stan-dev/shinystan/pull/126/files#diff-16 (11)
  • A inst/ShinyStan/www/.gitignore https://github.com/stan-dev/shinystan/pull/126/files#diff-17 (1)
  • A inst/ShinyStan/www/gg_animate_shinystan.webm https://github.com/stan-dev/shinystan/pull/126/files#diff-18 (0)
  • A shinystan_develop.Rproj https://github.com/stan-dev/shinystan/pull/126/files#diff-19 (17)
  • A tests/gg_animate_test.R https://github.com/stan-dev/shinystan/pull/126/files#diff-20 (38)

Patch Links:

  • https://github.com/stan-dev/shinystan/pull/126.patch
  • https://github.com/stan-dev/shinystan/pull/126.diff

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/stan-dev/shinystan/pull/126, or mute the thread https://github.com/notifications/unsubscribe/AHb4Q1NMsUdxjIKAIc6VlnPhuf0NPFl8ks5qLuGZgaJpZM4I1jbT .

jgabry avatar Jun 14 '16 19:06 jgabry

Sure thing take your time. I tried to test it thoroughly, but it is definitely experimental. A particular question is what the default settings should be as producing video is resource-intensive.

saudiwin avatar Jun 14 '16 21:06 saudiwin

Haven't gone through the code yet but I do have some general thoughts/questions:

  • the way the code is written, would it be pretty straightforward to plug in other kinds of plots? For example, taking the same code and making animated histograms of the chains?
  • given how long it takes to make the videos, maybe this should (probably also, maybe only) be available as its own function in the shinystan package that doesn't require the app to be launched. what do you think?

jgabry avatar Jun 15 '16 21:06 jgabry

That is certainly an idea re: using a separate function. Were you thinking of just having command line usage or creating a separate shiny interface? I think in an ideal world someone could be running a video production task in the background while continuing to look at other parts of the shiny app. I'm not sure though how to do that in shiny code. I also think that it might be good to disable the video production in any app that is shared online because it would take up a lot of resources on the server, and I know those are usually limited.

When I was testing settings, I would only run it relatively low smoothing, and that doesn't take too long. But because interpolation is multiplicative, it massively increases the number of plots. So I think part of the resource intensity issue may depend on getting the right settings that users would find useful. If someone wanted to have a full-length, high-quality video, then they could take a full hour to produce it, but if someone just wanted to examine a particular difficult sampling problem, they could use much less "pretty" settings.

The function is essentially 1) interpolate the data, 2) melt the data either by X variables or by chain, 3) run ggplot on the melted data, and 4) create the animation. So because #3 is separate, it is easy to switch out settings or change the type of plot used.

By animated histogram, are you thinking of running it on full log-posterior samples, indexed by both n and t? I see no reason why that shouldn't be possible. Of course, you could get seasick watching it...

saudiwin avatar Jun 16 '16 00:06 saudiwin

Hi Robert, a bunch of comments inline below:

On Wednesday, June 15, 2016, Robert Kubinec [email protected] wrote:

That is certainly an idea re: using a separate function. Were you thinking of just having command line usage or creating a separate shiny interface?

Hmm, I guess either or both. More on this below,

I think in an ideal world someone could be running a video production task in the background while continuing to look at other parts of the shiny app. I'm not sure though how to do that in shiny code.

Yeah, I've run into this issue before and I'm not sure if that's possible given the way shiny is implemented. I haven't looked into it in a while though.

I also think that it might be good to disable the video production in any

app that is shared online because it would take up a lot of resources on the server, and I know those are usually limited.

Agreed.

When I was testing settings, I would only run it relatively low smoothing, and that doesn't take too long. But because interpolation is multiplicative, it massively increases the number of plots. So I think part of the resource intensity issue may depend on getting the right settings that users would find useful. If someone wanted to have a full-length, high-quality video, then they could take a full hour to produce it, but if someone just wanted to examine a particular difficult sampling problem, they could use much less "pretty" settings.

For making high quality videos it would probably be good to also have a way to do it from the command line without running a shiny app. That way someone could do it just with an R script and it could conceivably be sent to a remote machine, cluster, server, whatever.

The function is essentially 1) interpolate the data, 2) melt the data either by X variables or by chain, 3) run ggplot on the melted data, and 4) create the animation. So because #3 https://github.com/stan-dev/shinystan/issues/3 is separate, it is easy to switch out settings or change the type of plot used.

Ok great.

By animated histogram, are you thinking of running it on full log-posterior samples, indexed by both n and t? I see no reason why that shouldn't be possible. Of course, you could get seasick watching it...

I was thinking that if we can see each chain exploring the parameter space then we could also show how the shape of the distribution of sampled values from each chain is changing over time. So we could see, e.g., four different histograms that look very different and converge towards each other (or not converge if that's the case).

And there are probably all sorts of other interesting things to look at with animations like this!

Jonah

jgabry avatar Jun 16 '16 15:06 jgabry

Yeah that's interesting. Adding histograms should be pretty easy given how modular ggplot2 is. One of the cool things about animation is that it seems like more variables can be combined in one plot because you can see change in variation over time, while one-dimensional plots can become messy quickly (like the pairs plot). I'll go ahead and add histogram support.

An R-level function call with parallel support makes a lot of sense. I think that I could make a wrapper for the animation function that splits up the frames into separate objects and then recombines them before processing into video. That could be put into an mclapply loop for large videos. I think to make it an R function call I would need to add in some convenience functions to pull apart the shinystan object, but nothing too difficult. Most of the difficult coding involved getting from ggplot to video; everything else is just data processing.

saudiwin avatar Jun 16 '16 21:06 saudiwin

Ok cool. Let me know if you have any questions about accessing anything from a shinystan object. I'll hopefully have time this weekend to actually go over the code for everything you already have. Thanks again for working on this!

On Thursday, June 16, 2016, Robert Kubinec [email protected] wrote:

Yeah that's interesting. Adding histograms should be pretty easy given how modular ggplot2 is. One of the cool things about animation is that it seems like more variables can be combined in one plot because you can see change in variation over time, while one-dimensional plots can become messy quickly (like the pairs plot). I'll go ahead and add histogram support.

An R-level function call with parallel support makes a lot of sense. I think that I could make a wrapper for the animation function that splits up the frames into separate objects and then recombines them before processing into video. That could be put into an mclapply loop for large videos. I think to make it an R function call I would need to add in some convenience functions to pull apart the shinystan object, but nothing too difficult. Most of the difficult coding involved getting from ggplot to video; everything else is just data processing.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/stan-dev/shinystan/pull/126#issuecomment-226619333, or mute the thread https://github.com/notifications/unsubscribe/AHb4Q9-cA5_6fOcYfGsmb9e2f73OZKLCks5qMcAQgaJpZM4I1jbT .

jgabry avatar Jun 17 '16 16:06 jgabry

Sounds good, Jonah. It's been a fun project to work on.

saudiwin avatar Jun 17 '16 18:06 saudiwin

OK I've got basic histogram support working:

https://youtu.be/wqmgI_iEYRM

It only works by manually selecting each variable of the density individually and it only can show one chain at a time because I set up the original function to show scatterplots. To enable multiple chains I have to change the way that the data is melted; I think what I need to do is create a sub-function that does data processing, currently the code is getting a little busy.

saudiwin avatar Jun 20 '16 11:06 saudiwin