1

I'm using RPy2 to make some plots. The plot shows up but the X11 window immediately disappears.

All I'm typing is the following, where CCFS is a data matrix

 import rpy2.robjects as robjects
 r = robjects.r

 pca = r.princomp(CCFS)
 r.plot(pca,main="Eigenvalues")
 r.biplot(pca,main="biplot")
 r['dev.off']() #*EDIT* the problem persists even if I remove this line.

Am I failing to include something? I know that there is something to plot because princomp returns a ListVector that isn't null.

mac389
  • 3,004
  • 5
  • 38
  • 62
  • 1
    Are you doing this at an interactive prompt? If so, try not issuing that last `'dev.off'` operation. – zwol Sep 29 '12 at 19:28
  • I did and it changes nothing. The plot does show up but then it closes. I'll add an x11 tag. – mac389 Sep 29 '12 at 19:29
  • No, this is in a Python module. – mac389 Sep 29 '12 at 19:30
  • OK, then it's probably going away because the program has exited. You need the program to keep running until you're done, or else you need to use a batch-mode device like `pdf` or `png`. – zwol Sep 29 '12 at 19:32
  • Hmmm. I already have X11 running for something else (SSH forwarding, if that's important.) So, I'm sure that X11 doesn't close. – mac389 Sep 29 '12 at 19:33
  • 1
    The X server keeps running, sure, but when the *Python script* terminates, all windows it has opened are automatically closed. – zwol Sep 29 '12 at 19:46

2 Answers2

5

Add

input()         # for Python3
# raw_input()   # for Python2

to the end of the script to prevent the program from ending until the user presses Enter.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • This works! However, it doesn't explain why the X11 window doesn't persist. For instance, the example RPy biplot script doesn't use this so I think I'm missing a bigger point. – mac389 Sep 29 '12 at 19:37
  • When the `r` object is garbage collected, it apparently closes any window that it has created. I don't know what biplot script you are referring to, but if it was from documentation, it might just be showing the important bits, assuming you either know about `raw_input()` or that you'd use the code in a larger script that doesn't happen to end there. – unutbu Sep 29 '12 at 20:00
  • Ah, I understand. I don't use RPy for any thing else in the script after the biplot line. So, of course, a smart garbage collector would close all windows right there. As if that's not enough, the Python script also ends right there. As @Zack noted, that would kill the X11 window even if it survived the garbage collector. Thanks- it makes sense now. – mac389 Sep 29 '12 at 20:06
  • 1
    "raw_input" is renamed to "input" in Python 3, but this trick is still valid. – Irene Feb 16 '19 at 16:12
3

As Zack pointed it out calling dev.off() on interactive graphical devices will just cause the device to close (and what it displays to disappear). On the other hand, closing non-interactive devices is mostly required before the plot can be checked (See rpy2's documentation on graphical devices).

I am guessing that your Python code is called as a standalone program / script rather than part of an interactive Python session. In other words I am suspecting that you are having something like python myscript.py in a shell (the content of myscript.py being your code above); when the script ends the embedded R is obviously terminated, taking with it the interactive plot. This is likely also what Zack is thinking. Try python -i myscript.py, and then once in the Python console import sys; sys.exit(0) to see that exiting Python means closing R interactive devices.

lgautier
  • 11,363
  • 29
  • 42
  • You're right. I'm used to the Matplotlib functionality where the script stops until you close the plot, even if you generate the plot from a standalone script. – mac389 Sep 30 '12 at 01:55
  • Customizing R devices to behave this way through rpy2 might be possible in the future (e.g., http://rpy.sourceforge.net/rpy2/doc-2.3/html/graphicaldevices.html#rpy2.rinterface._rpy_device.GraphicalDevice.close). However, that's not yet the case. – lgautier Sep 30 '12 at 07:03