-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Warning: Graphics device changes when using ggplotGrob
inside future::future_lapply
with multisession plan
#6464
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
Comments
I have fought with these types of issues a lot in my cowplot package. The brief answer is converting a plot into a grob should ideally only be done when actually rendering the plot into an opened graphics device. Otherwise you will run into all sorts of issues. However, you could try the Here is the relevant source code, which is quite cumbersome and lists some of the problems that can arise in different settings: The reason why a graphics device needs to be open is that we need font metrics to generate the grob and we don't have access to font metrics without having a graphics device open. An additional problem is that the font metrics will (subtly) change for different graphics devices and settings (for example, for raster devices, they can depend on the size of the output image), so we're almost guaranteed to have incorrect font metrics if we convert to a grob outside of final rendering. Again, this is where we go back to the point that ideally we wouldn't do this in the first place. |
Thanks @clauswilke. I tried a couple of examples using
As it is necessary to open a device to get font metrics, how device is opened in ggplot and is it explicitly closed afterwards? My understanding is that this opens device (which is probably fine) without closing it. |
AFAIK ggplot2 doesn't open graphics devices explicitly except in |
I think I found a temporary solution that disables the
|
@teunbrand Yes, this is exactly what happens. If you request font metrics and no graphics device is open then R just opens one. |
Right, but that isn't really behaviour ggplot2 has any sensible control over so there isn't much to adapt in ggplot2's code, I think. |
It is possible to avoid it in ggplot2 at the cost of performance. Text rendering is clearly moving towards an A and B tier device support, so it is likely that e.g. the string dimensions we get from one device cannot sensibly be used with another device. It might make sense to investigate wether the performance benefit that prompted the upfront-unit conversion still exist today |
Is this: just check in |
@teunbrand No, temporary graphics devices cause a bunch of issues and are best avoided. If only because you don't typically get the correct font metrics as the temporary device will in general not exactly match the final device used for rendering. I'm not sure what @thomasp85 is thinking of but in general it is best to defer all requests for font metrics etc. until the final rendering time, so the correct graphics device is available and open. The problem is there are many extension packages out there that violate this rule. My own are among the worst offenders. I'm not sure off the top of my head whether ggplot2 itself has this problem anywhere in its code base. I think not. |
In ggplot2 we convert grob dimensions to absolute units in eg titleGrob. We do this because it is more performant to calculate up front but we could choose not to do it and keep it in grobWidth and grobHeight dimensions |
Yes I agree, but if nobody has opened a GD, then grid will open one for us (and never close it). So the problems with font metrics are already happening, they just aren't extremely noticible. |
Uh oh!
There was an error while loading. Please reload this page.
When using
ggplot2::ggplotGrob()
(and indirectlyggExtra::ggMarginal()
) inside afuture::future_lapply()
call withplan(multisession)
, warnings appear related to unexpected graphics device changes. This breaks the expected isolation of child processes: child workers should not open or close graphics devices that persist outside their scope or cause side effects detectable by the parent.Specifically, the warnings mention that a new device (usually pdf) is opened without being closed properly, or the device state changes unexpectedly during the future evaluation.
This happens even when
dev.list()
returnsNULL
before execution, and attempts to pre-open and explicitly close devices inside the future expression (e.g., usinggrDevices::pdf()
anddev.off()
) do not fully suppress these warnings.This makes it difficult to safely use ggplot2 in parallel workflows using multisession futures, where device state consistency is critical.
Reprex:
Opening a temporary pdf device explicitly before plotting and closing it afterwards did not fully solve the issue:
What internal calls in
ggplot2::ggplotGrob()
or related grid functions might open a graphics device implicitly, especially in headless or parallel contexts?Is there a recommended way to preemptively open and close devices, or to prevent implicit device openings, when using ggplot2 grobs in parallel processes?
See also: futureverse/future#788
The text was updated successfully, but these errors were encountered: