Mat W
Mat W

Reputation: 35

Evaluating text within a raster calc function

I would to evaluate a text argument in a raster calculate function then use parallel processing in the R raster package to map the function.

The code below works fine (but is not desirable):

library(raster)
library(snow)
library(doParallel)

# using a RasterStack as input
r <- raster(ncols=36, nrows=18)
r[] <- 1:ncell(r)
s <- stack(r, r*2, sqrt(r))

# create the raster calculation function
f1<-function(x) calc(x, fun=function(x){
rast<-(x[1]/x[2])*x[3];return(rast)
})

# Map it using parallel processing capabilities (via clusterR in the raster package)
beginCluster()
pred <- clusterR(s, fun=f1, filename=paste("test.tif",sep=""),format="GTiff",progress="text",overwrite=T)
endCluster()

I would prefer the above raster calculation function to be a line of text that can be evaluated in the raster function itself, something like this:

#Create the equivalent string argument
str<-"rast<-(x[1]/x[2])*x[3];return(rast)"

#Evaluate it in the raster calculation function using eval and parse commands
f1<-function(x) calc(x, fun=function(x){
eval(parse(text=str))
})

#Map it using parallel processing capabilities (via clusterR in the raster package)
beginCluster()
upper_pred <- clusterR(s, fun=f1, filename =paste("test.tif",sep=""),format="GTiff",progress="text",overwrite=T)
endCluster()

Unfortunately, this method falls over in the ClusterR function.

What do I need to do in order for the second method to work? It seems the eval command is not recognized in the raster calculation. I have many string arguments structured like this and would like to evaluate each one without having to manually copy/paste into the console.

Thanks for your help!

Upvotes: 3

Views: 175

Answers (1)

Nick Kennedy
Nick Kennedy

Reputation: 12640

I suspect it's because the function refers to str which is defined in the global environment of your main R process but not exported to the cluster. One option which might be neater anyway is to produce a function from str:

f1 <- eval(parse(text = paste0("function(x) calc(x, fun = function(x){", str, "})")))

You could even have a function that does this:

make_f1 <- function(str) {
  eval(parse(text = paste0("function(x) calc(x, fun = function(x){", str, "})")))
}
f1 <- make_f1(str)

It's also worth noting that your particular example could be simplified to:

str<-"x[1]/x[2])*x[3]"

Upvotes: 0

Related Questions