Using rgl with headless display
Asked Answered
L

1

9

I installed Xfvb and instantiated a display instance:

$ Xvfb :2 -screen 0 1280x960x24 &

I then installed R 3.2.5 and rgl 0.95.1441 separately from source, and I opened R with a connection to DISPLAY on port 2. I then tried to run a test rgl session with some basic rgl routines:

$ DISPLAY=:2 /usr/local/bin/R
R version 3.2.5 (2016-04-14) -- "Very, Very Secure Dishes"
...
> library(rgl)
> open3d()
> x <- sort(rnorm(1000))
> y <- rnorm(1000)
> z <- rnorm(1000) + atan2(x,y)
glX
 1
> plot3d(x, y, z, col=rainbow(1000))
> rgl.postscript("foo.pdf", fmt="pdf")
> sessionInfo()

The rgl.postscript() command here should print out a PDF file containing the rendering of the data points passed to plot3d(). However, the resulting PDF file is blank.

Is there a configuration issue with how I installed or instantiated Xvfb and/or R, which is causing display problems?


Here is a log of a typical run session:

R version 3.2.5 (2016-04-14)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Fedora release 14 (Laughlin)

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
 [9] LC_ADDRESS=C               LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  base

other attached packages:
[1] rgl_0.95.1441  optparse_1.3.2

loaded via a namespace (and not attached):
[1] getopt_1.20.0 methods_3.2.5

5 XSELINUXs still allocated at reset
SCREEN: 0 objects of 136 bytes = 0 total bytes 0 private allocs
DEVICE: 4 objects of 32 bytes = 128 total bytes 0 private allocs
CLIENT: 0 objects of 160 bytes = 0 total bytes 0 private allocs
WINDOW: 0 objects of 48 bytes = 0 total bytes 0 private allocs
PIXMAP: 1 objects of 16 bytes = 16 total bytes 0 private allocs
GC: 0 objects of 56 bytes = 0 total bytes 0 private allocs
CURSOR: 0 objects of 8 bytes = 0 total bytes 0 private allocs
CURSOR_BITS: 0 objects of 8 bytes = 0 total bytes 0 private allocs
DBE_WINDOW: 0 objects of 24 bytes = 0 total bytes 0 private allocs
TOTAL: 5 objects, 144 bytes, 0 allocs
4 DEVICEs still allocated at reset
DEVICE: 4 objects of 32 bytes = 128 total bytes 0 private allocs
CLIENT: 0 objects of 160 bytes = 0 total bytes 0 private allocs
WINDOW: 0 objects of 48 bytes = 0 total bytes 0 private allocs
PIXMAP: 1 objects of 16 bytes = 16 total bytes 0 private allocs
GC: 0 objects of 56 bytes = 0 total bytes 0 private allocs
CURSOR: 0 objects of 8 bytes = 0 total bytes 0 private allocs
CURSOR_BITS: 0 objects of 8 bytes = 0 total bytes 0 private allocs
DBE_WINDOW: 0 objects of 24 bytes = 0 total bytes 0 private allocs
TOTAL: 5 objects, 144 bytes, 0 allocs
1 PIXMAPs still allocated at reset
PIXMAP: 1 objects of 16 bytes = 16 total bytes 0 private allocs
GC: 0 objects of 56 bytes = 0 total bytes 0 private allocs
CURSOR: 0 objects of 8 bytes = 0 total bytes 0 private allocs
CURSOR_BITS: 0 objects of 8 bytes = 0 total bytes 0 private allocs
DBE_WINDOW: 0 objects of 24 bytes = 0 total bytes 0 private allocs
TOTAL: 1 objects, 16 bytes, 0 allocs

In addition to Fedora 14, I have also tested the same version of R and rgl under CentOS Linux release 7.2.1511.

On the Fedora 14 box, I am running:

xorg-x11-server-Xvfb.x86_64   v1.9.5-2.fc14

On the CentOS 7 box, I am running:

xorg-x11-server-Xvfb.x86_64   v1.17.2-10.el7

Under both test servers, when I run my test R script, I get a white, empty PDF from rgl.postscript() and black, empty PNG from rgl.snapshot() (along with the same Xvfb log statements).

I should stress that I am looking to create a PDF file containing the rendered scene, which is in a vector-based format. While rgl.snapshot() may help with troubleshooting the cause of the problem, that call returns a PNG bitmap, not a vector-formatted PDF. A bitmap is not useful as a final product for my purposes.

In addition to running R with the DISPLAY variable setting passed to it, I also have used export:

$ DISPLAY=:2 /usr/local/bin/R

Or:

$ export DISPLAY=":2" 
$ /usr/local/bin/R
...

Either approach yields the same results.

If other details would be of use, please feel free to leave a comment with specifics and I'll do what I can to follow up.


Neither the Fedora 14 nor the CentOS 7 box should have proprietary libgl drivers. To the best of my knowledge, these are standalone, headless servers. The Fedora 14 box is actually a virtual machine. If there is a specific way to confirm, please let me know.

I have the following Xdummy package installed under the Fedora 14 headless server:

xorg-x11-drv-dummy.x86_64   v0.3.4-1.fc14

On the CentOS 7 machine:

xorg-x11-drv-dummy.x86_64   v0.3.6-21.el7

On the CentOS 7 server, I run the Xdummy script to create a display on :10:

$ sudo ./Xdummy -debug :10 -depth 16 -geom 1024x768

In another shell, I run R and the test rgl routines:

$ DISPLAY=":10" /usr/local/bin/R
...
> library(rgl)
> open3d()
> x <- sort(rnorm(1000))
> y <- rnorm(1000)
> z <- rnorm(1000) + atan2(x,y)
> plot3d(x, y, z, col=rainbow(1000))
> rgl.postscript("foo.pdf", fmt="pdf")

As with Xvfb, the resulting PDF file is a blank document and contains no data points.

Leverage answered 30/5, 2016 at 8:42 Comment(15)
I haven't used Xvfb much, but I believe it doesn't normally keep a full display buffer. This might be configurable; hopefully someone can help. Alternatives for a headless display are to select the null device and output WebGL using rglwidget and view (or print) the results in a browser, or possibly use the new writeASY function to write Asymptote source, and use it to produce the Postscript.Shall
I should add: writeASY isn't in 0.95.1441 on CRAN, you'll need to update from R-forge or Github.Shall
Thanks for the suggestion. To clarify, I want to automate making PDF output, so an interactive solution via a web browser may not work here.Leverage
Try creating a png file with rgl.snapshot. Does that work? Also please post your sessionInfo - might be relevant.Zenithal
An rgl.snapshot call returns a black, empty PNG file of the specified dimensions. I have added a sessionInfo transcript to my question. Thanks for any feedback that you might think is useful.Leverage
writeASY may be the best choice. You'll need to install Asymptote to process the output, but it should all work on a headless display. Both rgl.postscript and writeASY are incomplete implementations; I'd expect they have different limitations.Shall
Do you have any proprietary drivers installed that have their own version of libgl? Could you try Xdummy as an alternative to xvfb, and see if that works?Cellaret
Perhaps I am not starting it correctly, but Xdummy seems to give the same result as Xvfb.Leverage
Have you tried the same with precompiled package instead of compiling R and rgl from source yourself ??Jair
No, why would I do that?Leverage
@AlexReynolds I was wondering if you could have missed some dependency or missed compiling some features.Jair
I don't see an error or other message in the log that suggests that I'm missing a dependency, so I'm not sure. Is there a feature or setting you think is missing, based on the session log or the commands I entered?Leverage
Specifically for rgl, can you skip the virtual frame buffer and just try: library(rgl) followed by rgl.useNULL() ? Not sure if it will work; just noticed this recent addition to rgl from the docs for shiny: "The ability to use a "null device" was recently added to RGL, allowing you to use RGL (thus shinyRGL) on a headless server without having to emulate a framebuffer using XVFB"Applicatory
rgl.useNULL(TRUE) would work with writeASY() (which writes Asymptote code) or rglwidget() (which writes Javascript), but not with rgl.postscript or rgl.snapshot.Shall
Since a software solution seems elusive, might an inexpensive hardware solution work for you? Do your headless boxes have any graphics capability? It seems likely, given that most motherboards come with a GPU, even if you don't have a separate graphics card. If they do, you can buy inexpensive dummy video adapters that plug in the hdmi socket, and emulate the existence of a screen. With one of these installed, the box should behave exactly as though it did have a screen.Cellaret
C
3

This seems to be intimately intertwined with the rgl package. Suppose we toss Xvfb and friends in favor of Cairo and substitute plot3D for rgl:

library(Cairo)
library(plot3D)
CairoPDF()
x <- sort(rnorm(1000))
y <- rnorm(1000)
z <- rnorm(1000) + atan2(x, y)
scatter3D(x, y, z)
dev.off()

This still needs to run under X11 (i.e. xterm) but avoids bringing up an X11 window and leaves a PDF plot behind in Rplots.pdf (you can control the file names, of course along with lots of the other details of the plot.)

enter image description here

(Converted to JPEG for insertion here, but it is truly a PDF.)

Cher answered 7/6, 2016 at 21:59 Comment(2)
I wasn't the one who downvoted you, so I added a vote. This looks interesting but I would need time to investigate that it works without an X11 frame buffer, as well as see if I could recapitulate an existing R/rgl script. Thanks for offering what looks like a potential alternative to rgl.Leverage
@AlexReynolds, after two years and three up votes, have I still not earned the 500 point bounty that was on this question when I put in the time to research and answer it?Cher

© 2022 - 2024 — McMap. All rights reserved.