Gabor Grothendieck
2005-May-31 03:19 UTC
[R] Problem going back to a viewport with gridBase
I am setting up base plots -- one in viewport A and and one in B. This part works fine. But if I go back to A after having done B and add horizontal lines it seems to not use the correct coordinates. How do I tell it to resume using A's coordinates? I am already using par(fig = gridFIG()) but it seems that that's not enough to reestablish them. What happens is that when I go back to A it draws the horizontal lines as if its relative to B's coordinates rather than restablishing A's coordinates. As a result the horizontal lines are drawn near the bottom of the graph instead of at the correct heights. Try running the code below to see what I mean. I have also tried to use baseViewports with this but did not have any success. How do I modify this example so that the horizontal red lines come out at the appropriate levels? Note that this is just an example and in the future I will want to have multiple viewports each with a base plot and add arbitrary additional line or point plots to them so the solution needs to be sufficiently general that I can so generalize it. Thanks. library(gridBase) opar <- par(no.readonly = TRUE) grid.newpage() # two columns, one row unit. <- unit(c(1,1), c("null","null")) pushViewport(viewport(layout = grid.layout(1, 2, widths = unit.))) # draw green graph in first column (viewport A) pushViewport(viewport(layout.pos.col = 1, name = "A")) par(fig = gridFIG()); par(new = TRUE) plot(1:10, col = "green", pch = 20) upViewport(1) # draw purple graph in second column (viewport B) pushViewport(viewport(layout.pos.col = 2, name = "B")) par(fig = gridFIG()); par(new = TRUE) plot(1:100, col = "purple", pch = 18) upViewport() # go back to A and add horizontal grid lines seekViewport("A") par(fig = gridFIG()) abline(h=1:10, col = "red") #### THESE DO NOT GET DRAWN AS EXPECTED popViewport() # go back to B and add vertical grid lines seekViewport("B") par(fig = gridFIG()) abline(v=1:10, col = "red") popViewport() par(opar)
Hi Gabor Grothendieck wrote:> I am setting up base plots -- one in viewport A and and one in B. This part > works fine. But if I go back to A after having done B and add > horizontal lines it seems > to not use the correct coordinates. How do I tell it to resume using A's > coordinates? I am already using par(fig = gridFIG()) but it seems that that's > not enough to reestablish them. What happens is that when I go back to > A it draws the horizontal lines as if its relative to B's coordinates > rather than > restablishing A's coordinates. As a result the horizontal lines are > drawn near the > bottom of the graph instead of at the correct heights. Try running the code > below to see what I mean. > > I have also tried to use baseViewports with this but did not have any > success. > > How do I modify this example so that the horizontal red lines come out > at the appropriate levels? Note that this is just an example and in > the future I will want to have multiple viewports each with a base plot and > add arbitrary additional line or point plots to them so the solution needs > to be sufficiently general that I can so generalize it. > > Thanks. > > > library(gridBase) > > opar <- par(no.readonly = TRUE) > grid.newpage() > > # two columns, one row > unit. <- unit(c(1,1), c("null","null")) > pushViewport(viewport(layout = grid.layout(1, 2, widths = unit.))) > > # draw green graph in first column (viewport A) > pushViewport(viewport(layout.pos.col = 1, name = "A")) > par(fig = gridFIG()); par(new = TRUE) > plot(1:10, col = "green", pch = 20) > upViewport(1) > > # draw purple graph in second column (viewport B) > pushViewport(viewport(layout.pos.col = 2, name = "B")) > par(fig = gridFIG()); par(new = TRUE) > plot(1:100, col = "purple", pch = 18) > upViewport() > > # go back to A and add horizontal grid lines > seekViewport("A") > par(fig = gridFIG()) > abline(h=1:10, col = "red") #### THESE DO NOT GET DRAWN AS EXPECTED > popViewport() > > # go back to B and add vertical grid lines > seekViewport("B") > par(fig = gridFIG()) > abline(v=1:10, col = "red") > popViewport() > par(opar)The base, or "traditional", graphics system only records the *current* plotting coordinates; it does not retain a memory of previous plotting coordinates. What your example does is *reposition* the plotting region, but to do what you want you would have to recreate the plotting coordinates of the first plot. This is possible (at least in simple cases like the above), as shown below. However, perhaps a better approach would be to use a combination of grid and lattice plots, where the coordinate systems are retained and don't need to be recreated. An example of this approach is given at the end. ####### # Modified example using gridBase ####### library(gridBase) opar <- par(no.readonly = TRUE) grid.newpage() # two columns, one row unit. <- unit(c(1,1), c("null","null")) pushViewport(viewport(layout = grid.layout(1, 2, widths = unit.))) # draw green graph in first column (viewport A) pushViewport(viewport(layout.pos.col = 1, name = "A")) par(fig = gridFIG()); par(new = TRUE) plot(1:10, col = "green", pch = 20) upViewport(1) # draw purple graph in second column (viewport B) pushViewport(viewport(layout.pos.col = 2, name = "B")) par(fig = gridFIG()); par(new = TRUE) plot(1:100, col = "purple", pch = 18) upViewport() # go back to A and add horizontal grid lines seekViewport("A") par(fig = gridFIG()); par(new=TRUE) #### extra par(new=TRUE) plot(1:10, type="n", axes=FALSE, ann=FALSE) #### RESET PLOT A AXES abline(h=1:10, col = "red") popViewport() # go back to B and add vertical grid lines seekViewport("B") par(fig = gridFIG()); par(new=TRUE) #### extra par(new=TRUE) plot(1:100, type="n", axes=FALSE, ann=FALSE) #### RESET PLOT B AXES abline(v=1:10, col = "red") popViewport() par(opar) ####### # Similar result but using grid and lattice ####### library(grid) library(lattice) grid.newpage() # two columns, one row unit. <- unit(c(1,1), c("null","null")) pushViewport(viewport(layout = grid.layout(1, 2, widths = unit.))) # draw green graph in first column (viewport A) pushViewport(viewport(layout.pos.col = 1, name = "A")) # lattice plot instead of base plot p1 <- xyplot(1:10 ~ 1:10, col="green", pch=20) # prefix important so I can refer to it later print(p1, newpage=FALSE, prefix="plotA") upViewport(1) # draw purple graph in second column (viewport B) pushViewport(viewport(layout.pos.col = 2, name = "B")) p2 <- xyplot(1:100 ~ 1:100, col="purple", pch=18) print(p2, newpage=FALSE, prefix="plotB") upViewport() # go back to A and add horizontal grid lines seekViewport(trellis.vpname("panel", 1, 1, prefix="plotA")) # I'm working on a grid.abline() ... grid.segments(x0=0, x1=1, y0=unit(1:10, "native"), y1=unit(1:10, "native"), gp=gpar(col="red")) # go back to B and add vertical grid lines seekViewport(trellis.vpname("panel", 1, 1, prefix="plotB")) grid.segments(y0=0, y1=1, x0=unit(1:10, "native"), x1=unit(1:10, "native"), gp=gpar(col="red")) upViewport(0) Paul -- 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/
Gabor Grothendieck
2005-Jun-03 14:55 UTC
[Rd] Re: [R] Problem going back to a viewport with gridBase
On 6/2/05, Paul Murrell <p.murrell@auckland.ac.nz> wrote:> HiThanks. I have mucked around in vpTree structures and discovered its actually quite easy to specify children so I have changed my example so that instead of naming the children of 'layout' and then remembering coordinates linked to the names of the children of 'layout' in the 'coords' structure (which really just duplicates state information already available in grid) it simply follows the order of the children of 'layout' directly. This permits elimination of 'coords' and the two naming functions. Using the depth approach you advocate, 'with' also becomes shorter and I think I have it to the point where it works with both vpPath and viewport classes. Once Deepayan implements the use.viewport= argument to print, 'with' can be eliminated too. No questions this time but I thought I would post the latest version for completeness. Regards. [pushLayout is same as before except there are no names on the children of 'layout' and the rest is new] library(grid) library(lattice) pushLayout <- function(nr, nc, name="layout") { pushViewport(viewport(layout=grid.layout(nr, nc), name=name)) for (i in 1:nr) { for (j in 1:nc) { pushViewport(viewport(layout.pos.row=i, layout.pos.col=j)) upViewport() } } upViewport() } with.vpPath <- with.viewport <- function(data, expr, ...) { # if data is a vpPath it cannot be ROOT since NULL will never dispatch here depth <- if (data$name == "ROOT") 0 else downViewport(data$name) result <- eval.parent(substitute(expr)) upViewport(depth) invisible(result) } grid.newpage() # specify number of cells to fill and number of rows n <- 5; nr <- 3 nc <- ceiling(n/nr) downViewport(pushLayout(nr, nc)) vpt <- current.vpTree(all = FALSE) for(k in 1:n) with(vpt$children[[k]], print( xyplot(v ~ v, list(v = 1:k)), newpage = FALSE ) )
Apparently Analagous Threads
- Problem going back to a viewport with gridBase
- viewport bug in 2.8.0?: Error: Cannot pop the top-level viewport (grid and graphics output mixed?)
- print.trellis(..., draw.in=...)
- Problem when combining dotplot() and textplot() using grid
- gridBase and new.page() / grid.newpage()