Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ggsave() can change active graphics device #2363

Closed
wch opened this issue Dec 8, 2017 · 8 comments · Fixed by #2364
Closed

ggsave() can change active graphics device #2363

wch opened this issue Dec 8, 2017 · 8 comments · Fixed by #2364

Comments

@wch
Copy link
Member

wch commented Dec 8, 2017

If there is more than one graphics device open, calling ggsave() can change which one is active.

For example, in RStudio:

library(ggplot2)

dev.new()
dev.new()
dev.cur()
#> quartz 
#>      4 

p <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
ggsave('test.png', p)
dev.cur()
#> RStudioGD 
#>         2 

In R at the terminal:

library(ggplot2)

dev.new()
dev.new()
dev.cur()
#> quartz 
#>      3 

p <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
ggsave('test.png', p)
dev.cur()
#> quartz 
#>      2 
@dracodoc
Copy link

dracodoc commented Dec 8, 2017

A simple fix would be saving current device and restoring it.

cur_dev <- dev.cur()
ggsave("plot.png", g)
dev.set(cur_dev)

To fix it inside ggsave we can do something like this

cur_dev <- dev.cur()
dev(file = filename, width = dim[1], height = dim[2], ...)
on.exit(utils::capture.output({
  grDevices::dev.off()
  dev.set(cur_dev)
}))
grid.draw(plot)

@basjacobs93
Copy link

basjacobs93 commented Jul 13, 2018

On Ubuntu 17.10, when putting the below code in an Rscript and running it from the command line, the graphics device is still changed.

library(ggplot2)

print(dev.cur())
p <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
ggsave('test.png', p)
print(dev.cur())
$ Rscript test.R
null device 
          1 
Saving 7 x 7 in image
pdf 
  2 

It also creates an empty Rplots.pdf file next to test.png. In fact, such a file is already created when simply running

old_dev <- grDevices::dev.cur()
grDevices::pdf(file = "test.pdf")
grDevices::dev.off()
grDevices::dev.set(old_dev)

as an Rscript from the command line. I therefore believe this is also closely related to #2752 .

getOption("device") gives a function which is grDevices::pdf, and the environment variable R_DEFAULT_DEVICE is empty.

Running this from within Rstudio does give the expected behavior.

@clauswilke
Copy link
Member

I'm reopening this issue, since I think I know what's going on. And I agree #2752 is likely the same problem.

This code tries to save the current graphics device and then restore it once the plot is saved:

ggplot2/R/save.r

Lines 57 to 62 in 79e8b45

old_dev <- grDevices::dev.cur()
dev(filename = filename, width = dim[1], height = dim[2], ...)
on.exit(utils::capture.output({
grDevices::dev.off()
grDevices::dev.set(old_dev)
}))

The problem is this doesn't work when no device is currently open. When no device is open, dev.cur() returns 1. However, when dev.set() is called with an argument of 1, it opens a new device (!):

library(grDevices)
dev.off()
#> null device 
#>           1
dev.list()
#> NULL
dev.cur()
#> null device 
#>           1
dev.set(1)
#> null device 
#>           1
dev.list()
#> pdf 
#>   2

(This is documented behavior: "dev.set makes the specified device the active device. If there is no device with that number, it is equivalent to dev.next. If which = 1 it opens a new device and selects that.")

The solution I think is to replace line 61 in the code quoted above with:

if (old_dev > 1) grDevices::dev.set(old_dev)

@clauswilke
Copy link
Member

clauswilke commented Jul 13, 2018

I made a pull request. It would be great if somebody could test it. Install from github via:

devtools::install_github("clauswilke/ggplot2@issue-2363-ggsave")

@basjacobs93
Copy link

I can confirm that the pull request @clauswilke made works for me.

$ Rscript test.R
null device 
          1 
Saving 7 x 7 in image
null device 
          1 

@basjacobs93

This comment has been minimized.

@clauswilke

This comment has been minimized.

@lock
Copy link

lock bot commented Feb 3, 2019

This old issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with reprex) and link to this issue. https://reprex.tidyverse.org/

@lock lock bot locked and limited conversation to collaborators Feb 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants