Nothing
#' eval.linim.R
#'
#' Analogues of eval.im, harmonise.im and im.apply for 'linim'
#'
#' $Revision: 1.6 $ $Date: 2025/11/29 06:06:54 $
harmonize.linim <- harmonise.linim <- function(...) {
argz <- list(...)
n <- length(argz)
if(n < 2) return(argz)
result <- vector(mode="list", length=n)
isim <- sapply(argz, is.im)
isfun <- sapply(argz, is.function)
islinim <- sapply(argz, is.linim)
islinnet <- sapply(argz, is.linnet)
islinfun <- sapply(argz, inherits, what="linfun")
hasnet <- islinim | islinnet | islinfun
if(!any(hasnet))
stop("No network information was supplied", call.=FALSE)
## Extract the network
nets <- unique(solapply(argz[hasnet], as.linnet))
if(length(nets) > 1)
stop("Not all data refer to the same linear network", call.=FALSE)
L <- nets[[1L]]
## Select argument which determines the common resolution
imax <- NULL
if(any(islinim)) {
## Use linim objects to determine resolution
if(sum(islinim) == 1) {
imax <- which(islinim) # the unique linim object
} else {
## Extract data frames of linim objects
dframes <- lapply(argz[islinim], attr, which="df")
dfexists <- !sapply(dframes, is.null)
if(any(dfexists)) {
if(sum(dfexists) == 1) {
## Use the unique linim object which has a data frame
imax <- which(islinim)[which(dfexists)]
} else {
## find the data frame with finest spacing
nr <- sapply(dframes[dfexists], nrow)
imax <- which(islinim)[which(dfexists)[which.max(nr)]]
}
} # else there are no data frames to compare
}
}
if(is.null(imax) && any(isim)) {
## Find image object with finest pixel resolution
xstep <- sapply(argz[[isim]], attr, which="xstep")
ystep <- sapply(argz[[isim]], attr, which="ystep")
imax <- which.min(xstep * ystep)
}
if(is.null(imax)) {
## There is no resolution information.
## Convert everything at the same default resolution.
argz <- solapply(argz, as.linim, L=L)
} else {
## Use argument number 'imax' to determine resolution
template <- argz[[imax]]
G <- as.im(template)
dftemplate <- if(is.linim(template)) attr(template, which="df") else NULL
if(is.null(dftemplate)) {
## Convert everything using the pixel grid of 'template'
argz <- solapply(argz, as.linim, L=L, xy=G)
} else {
## Convert everything using the grid and data frame of template
argz <- solapply(argz, as.linim, L=template, xy=G)
}
}
return(argz)
}
#' analogue of eval.im
eval.linim <- function(expr, envir, harmonize=TRUE, warn=TRUE) {
sc <- sys.call()
# Get names of all variables in the expression
e <- as.expression(substitute(expr))
varnames <- all.vars(e)
allnames <- all.names(e, unique=TRUE)
funnames <- allnames[!(allnames %in% varnames)]
if(length(varnames) == 0)
stop("No variables in this expression")
# get the values of the variables
if(missing(envir)) {
envir <- parent.frame() # WAS: sys.parent()
} else if(is.list(envir)) {
envir <- list2env(envir, parent=parent.frame())
}
vars <- mget(varnames, envir=envir, inherits=TRUE, ifnotfound=list(NULL))
funs <- mget(funnames, envir=envir, inherits=TRUE, ifnotfound=list(NULL))
# Find out which variables are (linear) images
islinim <- unlist(lapply(vars, inherits, what="linim"))
if(!any(islinim))
stop("There are no linear images (class linim) in this expression")
# ....................................
# Evaluate the pixel values using eval.im
# ....................................
sc[[1L]] <- as.name('eval.im')
sc$envir <- envir
Y <- eval(sc)
# .........................................
# Then evaluate data frame entries if feasible
# .........................................
dfY <- NULL
linims <- vars[islinim]
nlinims <- length(linims)
dframes <- lapply(linims, attr, which="df")
nets <- lapply(linims, attr, which="L")
isim <- unlist(lapply(vars, is.im))
if(!any(isim & !islinim)) {
# all images are 'linim' objects
# Check that the images refer to the same linear network
if(nlinims > 1) {
agree <- unlist(lapply(nets[-1L], identical, y=nets[[1L]]))
if(!all(agree))
stop(paste("Images do not refer to the same linear network"))
}
dfempty <- unlist(lapply(dframes, is.null))
if(!any(dfempty)) {
# ensure data frames are compatible
if(length(dframes) > 1 && (
length(unique(nr <- sapply(dframes, nrow))) > 1 ||
!allElementsIdentical(dframes, "seg") ||
!allElementsIdentical(dframes, "tp")
)) {
# find the one with finest spacing
imax <- which.max(nr)
# resample the others
dframes[-imax] <- lapply(dframes[-imax],
resampleNetworkDataFrame,
template=dframes[[imax]])
}
# replace each image variable by its data frame column of values
vars[islinim] <- lapply(dframes, getElement, "values")
# now evaluate expression
Yvalues <- eval(e, append(vars, funs))
# pack up
dfY <- dframes[[1L]]
dfY$values <- Yvalues
}
}
result <- linim(nets[[1L]], Y, df=dfY, restrict=FALSE)
return(result)
}
resampleNetworkDataFrame <- function(df, template) {
# resample 'df' at the points of 'template'
invalues <- df$values
insegment <- df$mapXY
inteepee <- df$tp
out <- template
n <- nrow(out)
outvalues <- vector(mode = typeof(invalues), length=n)
outsegment <- out$mapXY
outteepee <- out$tp
for(i in seq_len(n)) {
relevant <- which(insegment == outsegment[i])
if(length(relevant) > 0) {
j <- which.min(abs(inteepee[relevant] - outteepee[i]))
outvalues[i] <- invalues[relevant[j]]
}
}
out$values <- outvalues
return(out)
}
linim.apply <- function(X, FUN, ...,
fun.handles.na=FALSE, check=TRUE, verbose=TRUE) {
## determine function to be applied
fun <- if(is.character(FUN)) get(FUN, mode="function") else
if(is.function(FUN)) FUN else stop("Unrecognised format for FUN")
funcode <- match(list(fun),
list(base::sum,
base::mean,
base::mean.default,
stats::var,
stats::sd),
nomatch=0L)
funtype <- c("general", "sum", "mean", "mean", "var", "sd")[funcode+1L]
## ensure images are compatible
if(check)
X <- do.call(harmonise.linim, X)
if(!all(sapply(X, is.linim)))
stop("All elements of X must be pixel images on a network (class linim)",
call.=FALSE)
## extract linear network
L <- as.linim(X[[1]])
## First apply function to pixel values
result <- im.apply(X, FUN, ..., fun.handles.na=fun.handles.na,
check=check, verbose=verbose)
single <- is.im(result)
## Consider data for sample points on network
dframes <- lapply(X, attr, which="df")
if(any(sapply(dframes, is.null))) {
## Give up and convert result to linim
if(single) {
result <- linim(L=L, Z=result)
} else {
result <- solapply(result, linim, L=L)
}
} else {
## Extract values at sample points
vals <- sapply(dframes, getElement, name="values")
## apply function to these values
y <- ImApplyEngine(vals, fun, funtype, fun.handles.na, ...)
## attach to results
df <- dframes[[1L]]
if(single) {
df$values <- y
result <- linim(L=L, Z=result, df=df)
} else {
n <- length(result)
class(result) <- "list"
for(i in seq_len(n)) {
df$values <- y[,i]
result[[i]] <- linim(result[[i]], L=L, df=df)
}
result <- as.solist(result)
}
}
return(result)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.