John G. Bullock
2018-Oct-30 18:34 UTC
[R] grid.grab(): strange behavior of "wrap" argument when working with lattice output
grid.grab() captures all of the current viewports and stores them as a grob. In theory, and often in practice, you can use grid.grab() to store an image now for drawing later on. But I have noticed some odd behavior of grid.grab() when working with lattice output. It is all related to the wrap argument: 1. When wrap = TRUE, the saved grob should produce a drawing faithful to the original viewports. But sometimes it doesn't. ??? 2. wrap = FALSE is supposed to produce less faithful output if it differs at all, but sometimes its output is more faithful. ??? 3. Even when using wrap = TRUE, grid.grab() warns me to use wrap = TRUE. Here is a minimal example to illustrate all of these behaviors: library(grid) ??? library(lattice) ??? xyplot(1:5 ~ 1:5) trellis.focus() ??? panel.abline(h = 3) ??? panel.abline(h = 5) myGrob <- grid.grab(wrap = TRUE) At this point, I receive a warning -- ?? ?? In grabDL(warn, wrap, ...) : ? ? ? ? one of more grobs overwritten (grab WILL not be faithful; try 'wrap = TRUE') -- which is strange, given that I specified wrap = TRUE. I proceed by running grid.draw(myGrob). According to Paul Murrell (R Graphics, 2nd ed., page 239), using grid.grab(wrap = TRUE) is "guaranteed to replicate the original output." But it doesn't. Specifically, the top horizontal line (from panel.abline(h = 5)) isn't reproduced. Matters get stranger when I consider the following code: ??? xyplot(1:5 ~ 1:5) ??? trellis.focus() ??? panel.abline(h = 3) panel.abline(h = 5) ??? myGrob <- grid.grab(wrap = FALSE) grid.draw(myGrob) These commands are the same as in the previous example, except that this time, wrap = FALSE. But this time, grid.draw() does faithfully reproduce the captured viewports. So the behavior is the opposite of what I expect: when wrap = FALSE, grid.draw() faithfully reproduces the captured viewports, but when wrap = TRUE, it doesn't. I've run these examples in R 3.3.2 and 3.5.1. (Session info from 3.3.2 is appended.) The result is the same in both cases. Are these bugs, or am I overlooking something? Thank you, John Bullock > sessionInfo() R version 3.3.2 (2016-10-31) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 10 x64 (build 17134) locale: [1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252??? LC_MONETARY=English_United States.1252 LC_NUMERIC=C [5] LC_TIME=English_United States.1252 attached base packages: [1] grid????? stats???? graphics? grDevices utils???? datasets methods base other attached packages: [1] lattice_0.20-34 RevoUtilsMath_10.0.0 loaded via a namespace (and not attached): [1] RevoUtils_10.0.2 [[alternative HTML version deleted]]
Paul Murrell
2018-Oct-31 00:33 UTC
[R] [FORGED] grid.grab(): strange behavior of "wrap" argument when working with lattice output
Hi Mostly these are bugs. One source of confusion: wrap=FALSE is NOT doing better than wrap=TRUE, which you can see if you start a new page before drawing the grabbed grob ... xyplot(1:5 ~ 1:5) trellis.focus() panel.abline(h = 3) panel.abline(h = 5) myGrob <- grid.grab(wrap = FALSE) ## start new page, otherwise just drawing over the top grid.newpage() grid.draw(myGrob) But you are correct that wrap=TRUE is underperforming. The problem is that your code is producing two grobs with the same name (and grid.grab() gets upset because you cannot create a gTree with two grobs with the same name). Here is a workaround (make sure that each grob has a different name) ... xyplot(1:5 ~ 1:5) trellis.focus() panel.abline(h = 3) panel.abline(h = 5, identifier="abline2") myGrob <- grid.grab() grid.grab(wrap=TRUE) does not fix the problem because it does not wrap grobs. For a more permanent solution, I have added a 'wrap.grobs' argument to grid.grab() (in r-devel), so that you can now do this (wrap.grobs=TRUE implicitly sets wrap=TRUE) ... xyplot(1:5 ~ 1:5) trellis.focus() panel.abline(h = 3) panel.abline(h = 5) myGrob <- grid.grab(wrap.grobs = TRUE) I have also fixed grid.grab() so that it does not complain about grobs with the same name if you have set wrap.grobs=TRUE. Thanks for the report. I hope this fixes the problems for you. Paul On 31/10/18 7:34 AM, John G. Bullock wrote:> > grid.grab() captures all of the current viewports and stores them as a > grob. In theory, and often in practice, you can use grid.grab() to store > an image now for drawing later on. But I have noticed some odd behavior > of grid.grab() when working with lattice output. It is all related to > the wrap argument: > > 1. When wrap = TRUE, the saved grob should produce a drawing faithful to > the original viewports. But sometimes it doesn't. > ??? 2. wrap = FALSE is supposed to produce less faithful output if it > differs at all, but sometimes its output is more faithful. > ??? 3. Even when using wrap = TRUE, grid.grab() warns me to use wrap > TRUE. > > Here is a minimal example to illustrate all of these behaviors: > > library(grid) > ??? library(lattice) > ??? xyplot(1:5 ~ 1:5) > trellis.focus() > ??? panel.abline(h = 3) > ??? panel.abline(h = 5) > myGrob <- grid.grab(wrap = TRUE) > > At this point, I receive a warning -- > > ?? ?? In grabDL(warn, wrap, ...) : > ? ? ? ? one of more grobs overwritten (grab WILL not be faithful; try > 'wrap = TRUE') > > -- which is strange, given that I specified wrap = TRUE. > > I proceed by running grid.draw(myGrob). According to Paul Murrell (R > Graphics, 2nd ed., page 239), using grid.grab(wrap = TRUE) is > "guaranteed to replicate the original output." But it doesn't. > Specifically, the top horizontal line (from panel.abline(h = 5)) isn't > reproduced. > > Matters get stranger when I consider the following code: > > ??? xyplot(1:5 ~ 1:5) > ??? trellis.focus() > ??? panel.abline(h = 3) > panel.abline(h = 5) > ??? myGrob <- grid.grab(wrap = FALSE) > grid.draw(myGrob) > > These commands are the same as in the previous example, except that this > time, wrap = FALSE. But this time, grid.draw() does faithfully reproduce > the captured viewports. So the behavior is the opposite of what I > expect: when wrap = FALSE, grid.draw() faithfully reproduces the > captured viewports, but when wrap = TRUE, it doesn't. > > I've run these examples in R 3.3.2 and 3.5.1. (Session info from 3.3.2 > is appended.) The result is the same in both cases. Are these bugs, or > am I overlooking something? > > Thank you, > John Bullock > > > > sessionInfo() > R version 3.3.2 (2016-10-31) > Platform: x86_64-w64-mingw32/x64 (64-bit) > Running under: Windows 10 x64 (build 17134) > > locale: > [1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United > States.1252??? LC_MONETARY=English_United States.1252 LC_NUMERIC=C > [5] LC_TIME=English_United States.1252 > > attached base packages: > [1] grid????? stats???? graphics? grDevices utils???? datasets methods base > > other attached packages: > [1] lattice_0.20-34 RevoUtilsMath_10.0.0 > > loaded via a namespace (and not attached): > [1] RevoUtils_10.0.2 > > > > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >-- Dr Paul Murrell Department of Statistics The University of Auckland Private Bag 92019 Auckland New Zealand 64 9 3737599 x85392 paul at stat.auckland.ac.nz http://www.stat.auckland.ac.nz/~paul/