4

For various functions in my cowplot package, I need to be able to convert ggplot2 plots into grobs, via the ggplotGrob() function. A known problem in this context is that ggplotGrob() requires an open graphics device, and depending on the graphics device currently open the call to this function creates a spurious empty plot. For examples of this problem, see ggplot2 issue #809 or most recently cowplot issue #82.

It is possible to fix the problem by opening a null pdf device. See the following example:

library(ggplot2)

# make a plot
p <- qplot(1:10, 1:10)

pdf(NULL) # open NULL pdf device to absorb empty page
grob <- ggplotGrob(p) # convert plot
dev.off()

Now here is my question: Is the sequence pdf(NULL); ggplotGrob(...); dev.off() safe to use in an R package, or are there scenarios where I cannot assume that pdf(NULL) will be successful/possible? If such scenarios exist, are there other graphics devices I can assume exist, and can I test when I'm in a situation where pdf(NULL) would not be a good idea? Alternatively, what would be the best way to make the code tolerant to potential failure of the pdf(NULL) call?

Update: See also this SO post which discusses the problem of blank pages but doesn't go into much detail of what safe methods there may be to work around the problem.

Update 2: This comment states that some R installs don't have a functioning pdf(). So it seems that it is indeed not always possible to open a pdf NULL device. The question then is: How can I work around this problem?

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104
  • 1
    https://bugs.r-project.org/bugzilla/show_bug.cgi?id=16378 – baptiste Dec 02 '17 at 22:31
  • Thanks @baptiste! I assume you encounter similar issues in the `egg` library. What do you do? Use `pdf(NULL)` and hope for the best? – Claus Wilke Dec 02 '17 at 22:48
  • to be honest I've given up on this issue, like many others that were closed or dismissed. This sounds like a reasonable workaround. – baptiste Dec 02 '17 at 22:56

1 Answers1

1

I looked into this briefly when you first posted it. As "pdf" is not in capabilities(), it "should" always work. Or so one hopes. And I tried a to construct a counter example without X11 access---and hence no font metrics---but failed.

Now, I still see two work-arounds that should always help you:

  1. Use the virtual framebuffer device in your R call; this is eg how we run the reverse depends checks "head-less". The call becomes something like this set of lines:

    xvfb-run-safe --server-args="-screen 0 1024x768x24" R CMD ...whatyouneed...

  2. Just say no to pdf() and use cairo() instead which is a) known to work headlessly and b) provided by two different packages.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Dirk, thanks for your answer. Had you seen [this comment,](https://github.com/wilkelab/cowplot/pull/72#issue-250568701) which states that some R installs don't have a functioning `pdf()`? I think the `cairo()` solution is a no-go, because it creates an additional dependency for my package. – Claus Wilke Dec 02 '17 at 19:01
  • I honestly have no idea. Sure, there will be _some_ R installations with something or other broken as people do the darndest things to their systems. The question is: is this systematic? Would your unit tests break? Would it fail at CRAN? And I don't think, but maybe I am biased and spoiled as the systems we set up are sound and working ... – Dirk Eddelbuettel Dec 02 '17 at 19:09