[R] Passing arguments between S4 methods fails within a function:bug? example with raster package.

Joris Meys jorismeys at gmail.com
Thu Aug 26 15:32:45 CEST 2010


Dear all,

This problem came up initially while debugging a function, but it
seems to be a more general problem of R. I hope I'm wrong, but I can't
find another explanation. Let me illustrate with the raster package.

For an object "RasterLayer" (which inherits from Raster), there is a
method xyValues defined with the signature
(object="RasterLayer",xy="matrix"). There is also a method with
signature (object="Raster",xy="vector"). The only thing this method
does, is change xy into a matrix and then pass on to the next method
using callGeneric again. Arguments are passed.

Now this all works smoothly, as long as you stay in the global environment :
require(raster)

a <- raster()
a[] <- 1:ncell(a)

origin <- c(-80,50)
eff.dist <- 100000

unlist(xyValues(a,xy=origin,buffer=eff.dist))
[1] 14140 14141 14500 14501

Now let's make a very basic test function :

test <- function(x,orig.point){
    eff.distance <- 100000
    p <- unlist(xyValues(x,xy=orig.point,buffer=eff.distance))
    return(p)
}

This gives the following result :
> test(a,origin)
Error in .local(object, xy, ...) : object 'eff.distance' not found

huh? Apparently, eff.distance got lost somewhere in the parsetree (am
I saying this correctly?)

The funny thing is when we change origin to a matrix :
> origin <- matrix(origin,ncol=2)

> unlist(xyValues(a,xy=origin,buffer=eff.dist))
[1] 14140 14141 14500 14501

> test(a,origin)
[1] 14140 14141 14500 14501

It all works again! So something goes wrong with passing the arguments
from one method to another using callGeneric. Is this a bug in R or am
I missing something obvious?

The relevant code from the raster package :

setMethod("xyValues", signature(object='Raster', xy='vector'),
	function(object, xy, ...) {
		if (length(xy) == 2) {
			callGeneric(object, matrix(xy, ncol=2), ...)
		} else {
			stop('xy coordinates should be a two-column matrix or data.frame,
or a vector of two numbers.')
		}
	} )

setMethod("xyValues", signature(object='RasterLayer', xy='matrix'),
	function(object, xy, method='simple', buffer=NULL, fun=NULL, na.rm=TRUE) {

		if (dim(xy)[2] != 2) {
			stop('xy has wrong dimensions; it should have 2 columns' )
		}

		if (! is.null(buffer)) {
			return( .xyvBuf(object, xy, buffer, fun, na.rm=na.rm) )
		}

		if (method=='bilinear') {
			return(.bilinearValue(object, xy))
		} else if (method=='simple') {
			cells <- cellFromXY(object, xy)
			return(.readCells(object, cells))
		} else {
			stop('invalid method argument. Should be simple or bilinear.')
		}
	}	
)	



-- 
Joris Meys
Statistical consultant

Ghent University
Faculty of Bioscience Engineering
Department of Applied mathematics, biometrics and process control

tel : +32 9 264 59 87
Joris.Meys at Ugent.be
-------------------------------
Disclaimer : http://helpdesk.ugent.be/e-maildisclaimer.php



More information about the R-help mailing list