From p.murrell at auckland.ac.nz  Thu Jun  2 03:08:13 2005
From: p.murrell at auckland.ac.nz (Paul Murrell)
Date: Thu Jun  2 03:09:44 2005
Subject: [Rd] Re: [R] Problem going back to a viewport with gridBase
References: <971536df05053020191ebe8f44@mail.gmail.com>	<429CEA59.7020206@stat.auckland.ac.nz>	<971536df050531163353031d97@mail.gmail.com>	<429CFA42.4080106@stat.auckland.ac.nz>
	<971536df05053118215366e02c@mail.gmail.com>
Message-ID: <429E5BFD.9080508@stat.auckland.ac.nz>

Hi


Gabor Grothendieck wrote:
> [moved from r-help to r-devel]
> 
> On 5/31/05, Paul Murrell <p.murrell@auckland.ac.nz> wrote:
> 
> 
>>>   # mm.row[j] gives the row in the layout of the jth cell
>>>   # mm.col[j] gives the col in the layout of the jth cell
>>>   mm <- matrix(seq(nr*nc), nr, nc)
>>>   mm.row <- c(row(mm))
>>>   mm.col <- c(col(mm))
>>>
>>>  # go to next cell in the array
>>>   j <- j + 1 # increment position
>>>  pushViewport(viewport(layout.pos.row = mm.row[j], layout.pos.col = mm.col[j]))
>>>
>>>Is that how to do it or is there some layout/mfcol-like way?
>>
>>
>>That is how to do it.
>>
>>As far as grid is concerned, all viewports are equal and grid has no
>>idea whether a viewport corresponds to a "plot region" or a "margin" or
>>whatever, so grid has no concept of which viewport is the "next" one to use.
>>
> 
> 
> OK. Thanks.  One suggestion.  Maybe the cells in a layout could have
> an order to them and there could be an optional argument that takes a linear
> index directly allowing easy linear traversals:
> 
> for(i in seq(nr*nc)) {
>    pushViewport(viewport(i)) # might need different syntax here
>    xyplot(seq(i) ~ seq(i))
>    popViewport()
> }


I think this sort of thing can easily be built on top rather than into 
the existing system.  For example, here's a function that pushes all of 
the basic cells in a layout using a simple naming convention:

layoutVPname <- function(i, j) {
   paste("layoutViewport", i, ",", j, sep="")
}

layoutVPpath <- function(i, j, name="layout") {
   vpPath(name, layoutVPname(i, j))
}

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,
                             name=layoutVPname(i, j)))
       upViewport()
     }
   }
   upViewport()
}

And here's a use of the function to push lots of layout cells, then draw 
lattice plots in different cells using downViewport() to go to the cell 
with the appropriate name.  In this case, we use cells by column, but 
simply reverse the order of the loops to use cells by row.

pushLayout(2, 3)
for (i in 1:2) {
   for (j in 1:3){
     depth <- downViewport(layoutVPpath(i, j))
     print(xyplot(seq(i*j) ~ seq(i*j)), newpage=FALSE)
     upViewport(depth)
   }
}


> and taking it one further perhaps 'with' could have a viewport method 
> that automatically pushes the viewport on entry and pops or moves
> up one level on exit reducing the above to:
> 
> for(i in seq(nr*nc)) with(viewport(i), xyplot(seq(i) ~ seq(i)))


The raw grid functions have a 'vp' argument for this purpose.  It would 
be nice if lattice functions had something similar (or maybe just 
print.trellis).  Here's your example using the 'vp' argument to 
grid.text() (and using the layout that was pushed above) ...

for (i in 1:2) {
   for (j in 1:3){
     grid.text(i*j, vp=layoutVPpath(i, j))
   }
}

Paul
-- 
Dr Paul Murrell
Department of Statistics
The University of Auckland
Private Bag 92019
Auckland
New Zealand
64 9 3737599 x85392
paul@stat.auckland.ac.nz
http://www.stat.auckland.ac.nz/~paul/


[Rd] Re: [R] Problem going back to a viewport with gridBase
Paul Murrell