## This example runs in R 2.3.1 and does not run in R 2.4.1. I am ## raising it here for two questions: one on how to debug functions ## inside a namespace, the other on how to control clipping. tmp <- data.frame(x=1:5, y=1:5, a=factor(c(1,1,1,1,1), levels=1:4)) xyplot(y ~ x, data=tmp, ylim=c(1.5,4.5), panel=function(x,y, ...) { cpv <- current.viewport() cpv$clip <- "off" pushViewport(cpv) panel.xyplot(x, y, ...) popViewport() }) ## R version 2.4.0 Under development (unstable) (2006-08-14 r38872) ## gives the error message Error in grid.Call.graphics("L_setviewport", pvp, TRUE) : LOGICAL() can only be applied to a 'logical', not a 'character'>## Question 1. How do I place a trace() on grid.Call.graphics to make ## it stop and give me a traceback. I tried many variations of the ## command ## trace(grid:::grid.Call.graphics, exit=recover, ## where=environment(grid:::grid.Call.graphics)) ## None of them trapped the error and let me trace it. What is the ## correct incantation? ## Question 2. How do I control clipping from within a panel ## function? In 2.3.1, both of the following statements run without ## error. Neither of them turns clipping off. ## ## In 2.4.0, the "off" statement gives the error message above. The ## FALSE statement runs without error, but it didn't turn clipping off. xyplot(y ~ x | a, data=tmp, ylim=c(1.5,4.5), panel=function(x,y, ...) { cpv <- current.viewport() cpv$clip <- "off" pushViewport(cpv) panel.xyplot(x, y, ...) popViewport() }, layout=c(2,2)) xyplot(y ~ x | a, data=tmp, ylim=c(1.5,4.5), panel=function(x,y, ...) { cpv <- current.viewport() cpv$clip <- FALSE pushViewport(cpv) panel.xyplot(x, y, ...) popViewport() }, layout=c(2,2)) ## ?viewport in 2.4.0 says ## clip ## ## One of "on", "inherit", or "off", indicating whether to clip to the ## extent of this viewport, inherit the clipping region from the ## parent viewport, or turn clipping off altogether. For ## back-compatibility, a logical value of TRUE corresponds to "on" and ## FALSE corresponds to "inherit". ## Notice that "off" is current and FALSE is back-compatible, and ## "off" is the value that causes the error. ## What is the correct way to turn off clipping? ## The way that I would like to use is something on the order of xyplot(y ~ x | a, data=tmp, ylim=c(1.5,4.5), panel=function(x,y, ...) { panel.xyplot(x, y, ..., par.settings = list(clip = list(panel = "off"))) }, layout=c(2,2)) ## I believe par.settings is currently valid only in xyplot() and not ## valid in panel functions. Is my understanding correct? Can the ## behavior be changed? ## ## The following statement works correctly in both 2.3.1 and 2.4.0. ## This statement controls clipping for the entire xyplot, not just ## for the single statement within the panel function. xyplot(y ~ x | a, data=tmp, ylim=c(1.5,4.5), par.settings = list(clip = list(panel = "off")), layout=c(2,2))
On 9/4/06, Richard M. Heiberger <rmh at temple.edu> wrote:> ## This example runs in R 2.3.1 and does not run in R 2.4.1. I am > ## raising it here for two questions: one on how to debug functions > ## inside a namespace, the other on how to control clipping. > > tmp <- data.frame(x=1:5, y=1:5, a=factor(c(1,1,1,1,1), levels=1:4)) > xyplot(y ~ x, > data=tmp, ylim=c(1.5,4.5), > panel=function(x,y, ...) { > cpv <- current.viewport() > cpv$clip <- "off" > pushViewport(cpv) > panel.xyplot(x, y, ...) > popViewport() > }) > > ## R version 2.4.0 Under development (unstable) (2006-08-14 r38872) > ## gives the error message > Error in grid.Call.graphics("L_setviewport", pvp, TRUE) : > LOGICAL() can only be applied to a 'logical', not a 'character' > > > > ## Question 1. How do I place a trace() on grid.Call.graphics to make > > [snipped] > > > ## Question 2. How do I control clipping from within a panel > ## function? In 2.3.1, both of the following statements run without > ## error. Neither of them turns clipping off. > ## > ## In 2.4.0, the "off" statement gives the error message above. The > ## FALSE statement runs without error, but it didn't turn clipping off. > > xyplot(y ~ x | a, > data=tmp, ylim=c(1.5,4.5), > panel=function(x,y, ...) { > cpv <- current.viewport() > cpv$clip <- "off" > pushViewport(cpv) > panel.xyplot(x, y, ...) > popViewport() > }, > layout=c(2,2)) > > xyplot(y ~ x | a, > data=tmp, ylim=c(1.5,4.5), > panel=function(x,y, ...) { > cpv <- current.viewport() > cpv$clip <- FALSE > pushViewport(cpv) > panel.xyplot(x, y, ...) > popViewport() > }, > layout=c(2,2)) > > > ## ?viewport in 2.4.0 says > ## clip > ## > ## One of "on", "inherit", or "off", indicating whether to clip to the > ## extent of this viewport, inherit the clipping region from the > ## parent viewport, or turn clipping off altogether. For > ## back-compatibility, a logical value of TRUE corresponds to "on" and > ## FALSE corresponds to "inherit". > > ## Notice that "off" is current and FALSE is back-compatible, and > ## "off" is the value that causes the error. > > ## What is the correct way to turn off clipping?I don't believe there /is/ a documented way.> ## The way that I would like to use is something on the order of > > xyplot(y ~ x | a, > data=tmp, ylim=c(1.5,4.5), > panel=function(x,y, ...) { > panel.xyplot(x, y, ..., > par.settings = list(clip = list(panel = "off"))) > }, > layout=c(2,2)) > > ## I believe par.settings is currently valid only in xyplot() and not > ## valid in panel functions. Is my understanding correct?Yes.> ## Can the > ## behavior be changed?In the original design of lattice, no. In the current design, two separate viewports exist for each panel (which is why you can use trellis.focus with clipping turned off). So, there might be a way to switch to that. A reasonably clean approach might be to do the following: xyplot(y ~ x, data=tmp, ylim=c(1.5,4.5), panel=function(x, y, ...) { upViewport() downViewport(trellis.vpname("panel", row = 1, column = 1, clip.off = TRUE)) panel.xyplot(x, y, ...) panel.points(1.4, 1.4) }) 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 following statement works correctly in both 2.3.1 and 2.4.0. > ## This statement controls clipping for the entire xyplot, not just > ## for the single statement within the panel function. > > 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. Deepayan
On Mon, 4 Sep 2006, Richard M. Heiberger wrote:> ## This example runs in R 2.3.1 and does not run in R 2.4.1. I amThere is no '2.4.1', and your R-devel is not very recent. It looks as if R-devel has detected an error of yours that previously went undetected. You set cpv$clip <- "off" and the internal code assumes that it is logical (as the message says). I can't find any documentation to support your code: if there is some please report it to the maintainer of grid (Paul Murrell).> ## raising it here for two questions: one on how to debug functions > ## inside a namespace, the other on how to control clipping. > > tmp <- data.frame(x=1:5, y=1:5, a=factor(c(1,1,1,1,1), levels=1:4)) > xyplot(y ~ x, > data=tmp, ylim=c(1.5,4.5), > panel=function(x,y, ...) { > cpv <- current.viewport() > cpv$clip <- "off" > pushViewport(cpv) > panel.xyplot(x, y, ...) > popViewport() > }) > > ## R version 2.4.0 Under development (unstable) (2006-08-14 r38872) > ## gives the error message > Error in grid.Call.graphics("L_setviewport", pvp, TRUE) : > LOGICAL() can only be applied to a 'logical', not a 'character' > > > > ## Question 1. How do I place a trace() on grid.Call.graphics to make > ## it stop and give me a traceback. I tried many variations of the > ## command > ## trace(grid:::grid.Call.graphics, exit=recover, > ## where=environment(grid:::grid.Call.graphics)) > ## None of them trapped the error and let me trace it. What is the > ## correct incantation?Not sure why you want to do that, as traceback() works here.> traceback(max.lines=3)10: .Call.graphics(fnname, ..., PACKAGE = "grid") 9: grid.Call.graphics("L_setviewport", pvp, TRUE) 8: push.vp.viewport(X[[1]], ...) 7: FUN(X[[1]], ...) 6: lapply(vps, push.vp, recording) 5: pushViewport(cpv) 4: panel(x = c(1, 2, 3, 4, 5), y = c(1, 2, 3, 4, 5), packet.number = 1, panel.number = 1) 3: do.call("panel", pargs) 2: print.trellis(list(formula = y ~ x, as.table = FALSE, aspect.fill = TRUE, legend = NULL, panel = function (x, y, ...) { ... 1: print(list(formula = y ~ x, as.table = FALSE, aspect.fill = TRUE, legend = NULL, panel = function (x, y, ...) { ... as does options(error=recover). What does a namespace have to do with this? -- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
From: Prof Brian Ripley> There is no '2.4.1', and your R-devel is not very recent.Apologies on the typo and the two-week old 2.4.0dev. I just downloaded version 2.4.0 Under development (unstable) (2006-09-04 r39086) 1.> You set cpv$clip <- "off" and the internal code assumes that it is logical > (as the message says). I can't find any documentation to support your > code: if there is some please report it to the maintainer of grid (Paul > Murrell).The documentation for "off" comes from ?viewport that is part of 2.4.0dev.> installed.packages()["grid",]Package LibPath "grid" "C:/PROGRA~1/R/R-24~1.0DE/library" Version Priority "2.4.0" "base" Bundle Contains NA NA Depends Imports "grDevices" NA Suggests Built "lattice" "2.4.0" clip One of "on", "inherit", or "off", indicating whether to clip to the extent of this viewport, inherit the clipping region from the parent viewport, or turn clipping off altogether. For back-compatibility, a logical value of TRUE corresponds to "on" and FALSE corresponds to "inherit". The above description of clip is identical to the description in ?viewport in the released 2.3.1. I still get the same error in 2.4.0dev that did not appear in 2.3.1 and it still looks to me like this is an equally valid statement in both versions of R.> Error in grid.Call.graphics("L_setviewport", pvp, TRUE) : > LOGICAL() can only be applied to a 'logical', not a 'character' > >I think something needs to be changed to make the documentation and the program consistent. I like the documentation, with the three options for clipping, and hope to see the program changed to match it. 2.> > ## Question 1. How do I place a trace() on grid.Call.graphics to make > > ## it stop and give me a traceback. > Not sure why you want to do that, as traceback() works here.... as does options(error=recover). I was interested in the argument trace(..., exit=recover) I see now that options(error=recover) does exactly what I want. That is the incantation I was looking for. Thank you.
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") ## this is what happens if I don't do any control of clipping xyplot(y ~ x, data=tmp, ylim=c(1.5,4.5), panel=function(...) { panel.xyplot(...) panel.axis(side="right", outside=TRUE) }, layout=c(2,2), main="right axis invisible by clipping, points clipped by default") ## 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") ## 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.