From p.murrell at auckland.ac.nz  Wed Sep  6 05:35:28 2006
From: p.murrell at auckland.ac.nz (Paul Murrell)
Date: Wed, 06 Sep 2006 15:35:28 +1200
Subject: [Rd] Two submitted packages
In-Reply-To: <eb555e660609052028t45899247lc443af40da9ebbda@mail.gmail.com>
References: <20060905223031.BHI71699@po-d.temple.edu>
	<eb555e660609052028t45899247lc443af40da9ebbda@mail.gmail.com>
Message-ID: <44FE4200.5030908@stat.auckland.ac.nz>

Hi


Deepayan Sarkar wrote:
> On 9/5/06, Richard M. Heiberger <rmh at temple.edu> wrote:
>> Deepayan wrote:
>>
>>>> xyplot(y ~ x | a,
>>>>        data=tmp, ylim=c(1.5,4.5),
>>>>        par.settings = list(clip = list(panel = "off")),
>>>>        layout=c(2,2))
>>> I'm curious to know why this functionality is not enough.
>>
>> ## 1. Here is a more realistic example.
>>
>> tmp <- data.frame(x=1:5, y=1:5, a=factor(c(1,1,1,1,1), levels=1:4))
>>
>> ## This gives what I want.
>> ## It looks like the upViewport/downViewport sequence is the control I
>> ## should be using.  If this is a stable sequence, it answers my needs.
>> xyplot(y ~ x,
>>        data=tmp, ylim=c(1.5,4.5),
>>        panel=function(...) {
>>           panel.xyplot(...)
>>             upViewport()
>>             downViewport(trellis.vpname("panel",
>>                                         row = 1, column = 1, clip.off = TRUE))
>>           panel.axis(side="right", outside=TRUE)
>>        },
>>        layout=c(2,2),
>>        main="right axis visible by control, points clipped by default")
>>
>> ## If I turned off clipping at the top, I would get the unwanted points
>> ## plotted outside the figure region.
>> xyplot(y ~ x,
>>        data=tmp, ylim=c(1.5,4.5),
>>        par.settings = list(clip = list(panel = "off")),
>>        panel=function(...) {
>>           panel.xyplot(...)
>>           panel.axis(side="right", outside=TRUE)
>>        },
>>        layout=c(2,2),
>>        main="right axis visible by control, points not clipped")
> 
> I see.
> 
>> ## This doesn't work, but it illustrates the syntax I would like.
>> xyplot(y ~ x,
>>        data=tmp, ylim=c(1.5,4.5),
>>        panel=function(...) {
>>           panel.xyplot(...)
>>           panel.axis(side="right", outside=TRUE, clip="off")
>>        },
>>        layout=c(2,2),
>>        main="right axis visible by control, points clipped by default")
> 
> This might be possible, but there is a potential for unanticipated
> problems. On the other hand, it's easy to achieve the equivalent of
> this with a couple of extra lines, e.g.
> 
> xyplot(y ~ x,
>        data=tmp, ylim=c(1.5,4.5),
>        panel=function(...) {
>            cpl <- current.panel.limits()
>            panel.xyplot(...)
>            pushViewport(viewport(xscale = cpl$xlim,
>                                  yscale = cpl$ylim,
>                                  clip = "off"))
>            ## put anything you want unclipped inside this:
>            panel.axis(side="right", outside=TRUE)
>            ## end of unclipped part
>            upViewport()
>        },
>        layout=c(2,2))
> 
> This already works, and should be stable, but I'm not sure; Paul has
> previously mentioned this feature that an unclipped viewport inside a
> clipped viewport allows plotting outside the clipped one, but I don't
> know if that's intentional. 


Yep, that's intentional.

Paul


Even if this behaviour does change, the
> opposite should be stable: turn off clipping globally and then insert
> the part of the panel function you want clipped into a clipped
> viewport, e.g.:
> 
> xyplot(y ~ x,
>        data=tmp, ylim=c(1.5,4.5),
>        par.settings = list(clip = list(panel = "off")),
>        panel=function(...) {
>            cpl <- current.panel.limits()
>            pushViewport(viewport(xscale = cpl$xlim,
>                                  yscale = cpl$ylim,
>                                  clip = "on"))
>            panel.xyplot(...)
>            upViewport()
>            panel.axis(side="right", outside=TRUE)
>        },
>        layout=c(2,2))
> 
>> ## 2
>>> Unfortunately, there is currently no easy way to find out which column
>>> and row the current panel occupies. I plan to make some changes before
>>> R 2.4.0 is released that should expose that information, so please try
>>> again in a few weeks.
>> The way I have been using is to back up the calling sequence and
>> use statements like
>> {
>>     ## This loop is needed because
>>     ##    console usage has i=2,
>>     ##    Rcmdr script window has i=5,
>>     ##    Rcmdr justDoIt has i=20
>>     for (i in seq(2, length=30)) {
>>       sf2 <- sys.frame(i)
>>       column.tmp <- try(get("column", pos=sf2), silent=TRUE)
>>       if (class(column.tmp) != "try-error") break
>>     }
>>     if (class(column.tmp) == "try-error")
>>       stop("panel.interaction2wt is too deeply nested in the system stack.")
>>     row <- get("row", pos=sf2)
>>     column <- get("column", pos=sf2)
>>     cols.per.page <- get("cols.per.page", pos=sf2)
>>     rows.per.page <- get("rows.per.page", pos=sf2)
>>   }
>>
>> ## A cleaner way would be preferable.  Will the above stay valid?  The
>> ## need for a loop to find out how far up the calling sequence to go
>> ## caught me by surprise.  I don't understand why generating commands
>> ## the way Rcmdr does it should have an effect on the depth of the
>> ## calling sequence.
> 
> I hope to add 3 new features before R 2.4.0, two of which are relevant
> for you: (1) more control over axis annotation and (2) an API to
> access auxiliary information (like row/column/layout) from inside a
> panel function. I should have a testable version in a week or so,
> after which I'll be happy to consider suggestions for further
> additions.
> 
> Deepayan
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

-- 
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/




[Rd] Two submitted packages
Paul Murrell