8

I am using R to generate a series of plots within a loop, with the user hitting the enter key to indicate they have seen the plot and it is time to move on. These are interactive rotatable plots generated with the rgl package and therefore using something like Sys.sleep() is not good enough.

Currently I can use readline() which works find when running R interactively. However, if I want to run my R script within a bash script all the plots appear flashing before the screen. This happens whether I call R using:

R --no-save -f myfile.r
R --no-save -e "source('myfile.r')"
R --no-save << myfile.r

How do I get R to pause and wait for the user to hit when run as a bash subprocess?

Setjmp
  • 27,279
  • 27
  • 74
  • 92
  • Why not just write the plots to file and let the user open them at his/her leisure? –  Oct 04 '11 at 21:38
  • Jack - this will require a separate StackOverflow question: how to write rgl 3d plots to disk in a manner so that they may be loaded (ideally by a web browser) and rotated at the user's leisure. Doable naively in R--yes (encoding points, colors, symbols, etc), but I hope I won't have to go there. If this leads to a portable, browser based solution then its a potential win. Otherwise, its an extra process in the work flow solving a problem that R should be able to on its own. – Setjmp Oct 05 '11 at 15:34
  • Here is the companion question: http://stackoverflow.com/questions/7663982/r-using-rgl-to-generate-3d-rotatable-plots-that-can-be-viewed-in-a-web-browser – Setjmp Oct 05 '11 at 15:46

5 Answers5

3

It's a late answer but my goal was similar: Rscript execution should bring up an rgl window with a plot and nothing else, and it should remain there till the window is closed, i.e. the rgl window should not terminate.

To achieve this, I simply placed this at the end of the R script, and the rgl plot will remain there for manipulation until you quit the window, consuming little CPU time:

play3d(function(time) {Sys.sleep(0.01); list()} )

For regular 2D R plots, locator() works similarly, or locator(1) if one click should close the plot window.

  • Works quite well, but will open a new, empty, RGL device window on closing the old one and never (?) terminate. – Raketenolli Jan 26 '17 at 14:02
3

Use this:

readLines("stdin", n = 1)

That will get the real stdin instead of what stdin() uses.

I'd invoke it with:

Rscript myfile.r
Michael Hoffman
  • 32,526
  • 7
  • 64
  • 86
  • This almost works, but it causes the plots to be non-interactive (frozen). The graphics library I am using is rgl with the plot3d function which allows me to rotate the plots. – Setjmp Oct 05 '11 at 15:21
  • It seems that `plot3d()` has different behavior when R is run non-interactively. Changing that is an entirely separate question. This answer will solve your question as asked. – Michael Hoffman Oct 05 '11 at 18:32
2

I'm not sure if there is an easy way to wait a keyboard input, but at least you can wait mouse click.
Not elegant but try this script:

quartz() # or maybe windows() in windows
for (i in 1:5) {plot(i, i); locator(1)}
kohske
  • 65,572
  • 8
  • 165
  • 155
  • locator seems to expect me to use the function plot(), however I am using plot3d from the rgl library. Also, I will be making mouse clicks as I rotate the plot manually which might interfere with an approach that uses mouse clicks as a signal. – Setjmp Oct 05 '11 at 15:30
1

Here is an example script that works for me (tested your first calling method on windows). It uses the tcltk package and creates an extra, small window with a single button, the script will pause (but still allow you to interact with the rgl window) until you either click on the 'continue' button on press a key while that window is active, then continue with the script.

library(tcltk)
library(rgl)

mywait <- function() {
    tt <- tktoplevel()
    tkpack( tkbutton(tt, text='Continue', command=function()tkdestroy(tt)),
        side='bottom')
    tkbind(tt,'<Key>', function()tkdestroy(tt) )

    tkwait.window(tt)
}


x <- rnorm(10)
y <- rnorm(10)
z <- rnorm(10)

plot3d(x,y,z)

mywait()

x <- rnorm(100)
y <- rnorm(100)
z <- rnorm(100)

plot3d(x,y,z)

mywait()

cor(x,y)
Greg Snow
  • 48,497
  • 6
  • 83
  • 110
0

plot.lm uses devAskNewPage(TRUE); perhaps that would also work here.

Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142