# NOTE: improve structure, reusability and readability!!!
# - first do cat based calculations (how to guess required xylim?)
# - afterwards do all the plotting
plotFootprint <- function(x, SensorName, rn = NULL, MyMap = NULL, type = c("CE", "wCE", "uCE"),
use.avg = FALSE, use.sym = FALSE, use.var = TRUE, wTDcutoff = NULL, origin = NULL,
dx = 2, dy = dx, levels = c(0.01, 0.1, 0.5, 0.9), breaks = function(x) quantile(c(0, max(x)), levels),
xlim = c(-100, 100), ylim = c(-100, 100), add = FALSE, alpha = 0.3, axs = c("r", "i"),
main = NULL, asp = 1, fill = TRUE, sub = NULL, bg.col = NULL, fp_only = FALSE, addSource = !fp_only,
showMax = FALSE, showSensor = !fp_only, dispSname = showSensor, N0 = NULL, lpos = NULL,
showPerc = FALSE, leg.bg.col = grey(0.9), cpal = NULL, lty = 1, lwd = 1, decPlaces = 0, sigNums = 1,
addWR = FALSE, WRpos = 2, WRfrac = 20, WRscale = 1, xy_transform = NULL, transformArgs = NULL,
useSTRtree = TRUE, avoidGEOS = FALSE, addSB = FALSE, SBpos = 3, StaticMapArgs = NULL,
showLegend = !fp_only, verbose = FALSE){
if (fill) {
if(!requireNamespace("maptools", quietly = TRUE)){
stop('filled polygons are not yet supported without the retired(!) package maptools')
}
if(!requireNamespace("rgeos", quietly = TRUE)){
stop('filled polygons are not yet supported without the retired(!) package rgeos')
}
if(!requireNamespace("sp", quietly = TRUE)){
stop("package 'sp' is required for filled polygons - please install the package by running install.packages('sp')")
}
}
# Notizen:
# - Sources spaeter hinzufuegen
# - Methode fuer Catalog hinzufuegen
# - arguments besser organisieren
# - main auch bei MyMap
# - xlim/ylim xy_transform WGS84 etc... besser organisieren!!!
# - xy_transform --> coords_2_WGS84 oder so
# - TrueProj als Argument, oder besser: if add=TRUE, par()$usr -> MyMap$size???
sx <- as.character(substitute(x))
if(inherits(x, "footprint")){
# breaks=rev(brks)
xy_transform <- x$xy_transform
transformArgs <- x$transformArgs
SensorPosition <- x$SensorPosition
WDmean <- x$WDmean
xlimOriginal <- x$xlimOriginal
ylimOriginal <- x$ylimOriginal
xm <- x$xm
ym <- x$ym
if (!is.null(origin)) {
old_ll <- data.frame(x = ym[1], y = xm[1])
# transf to origin
new_ll <- rotate(old_ll, Angle = -WDmean)
# shift origin
new_ll <- sweep(new_ll, 2, rev(origin))
# transf back
new_ll <- rotate(new_ll, Angle = WDmean)
# shift xm & ym
xm <- xm - old_ll[[2]] + new_ll[[2]]
ym <- ym - old_ll[[1]] + new_ll[[1]]
# shift xlimOriginal & ylimOriginal
xlimOriginal <- xlimOriginal - origin[1]
ylimOriginal <- ylimOriginal - origin[2]
}
xy <- x$xy
if(!add){
stop("argument 'add' must be TRUE when providing a footprint object")
}
} else {
# convert old versions
x <- copy(x)
setDT(x)
switchNames(x)
if(is.null(attr(x, "Version"))){
warning(paste0("Object '", sx[min(length(sx), 2)], "' has not yet been converted to version 4.2+"))
convert(x)
}
# checks:
if(missing(SensorName)){
stop("SensorName must be provided")
} else {
getThisSensor <- as.character(SensorName[1])
if(!nrow(x[Sensor==getThisSensor]))stop("No results for Sensor: ",getThisSensor," availabe!")
}
stopifnot(type[1] %in% c("CE","wCE","uCE"))
if(is.null(rn)){
getThisRows <- x[Sensor==getThisSensor,unique(rn)]
} else {
getThisRows <- rn
}
getThisSource <- x[rn%in%getThisRows&Sensor==getThisSensor,Source[1]]
index <- x[,which(rn%in%getThisRows&Sensor==getThisSensor&Source==getThisSource)]
WD <- x[index,WD]
if(is.null(N0)){
N0 <- x[index[1],N0]
} else {
if(any(x[index,N0]<N0))stop("Choose N0 smaller or equal to original N0!")
}
Ustar <- x[index,Ustar]
Suu <- x[index,sUu]
Svu <- x[index,sVu]
bw <- x[index,bw]
z <- x[index,SensorHeight]
L <- x[index,L]
Zo <- x[index,Zo]
Sources <- attr(x, 'ModelInput')[['Sources']]
if (is.null(Sources)) {
addSource <- FALSE
} else {
Source <- attr(procSources(Sources),"SourceList")
}
if(length(index)>1){
WDmean <- (360 + atan2(sum(sin(WD/180*pi)*Ustar)/sum(Ustar),sum(cos(WD/180*pi)*Ustar)/sum(Ustar))/pi*180) %% 360
} else {
WDmean <- WD
}
Calc.Sensors <- procSensors(attr(x,"ModelInput")$Sensors)$"Calc.Sensors"
SensorPosition <- Calc.Sensors[Calc.Sensors[, "Sensor Name"] %chin% SensorName,
c("Sensor Name", "x-Coord (m)", "y-Coord (m)", "Sensor ID", "Node")]
SPR <- rotate(SensorPosition[,2:3],Angle=-WDmean)
if(is.null(origin)){
origin <- colMeans(SensorPosition[,2:3])
}
if(!add){
if(is.null(main))main <- switch(type[1],
"CE"="C-Footprint",
"wCE"="w'C'-Footprint",
"uCE"="u'C'-Footprint")
if(is.null(MyMap)){
plot(SensorPosition[,2],SensorPosition[,3],type="n",xlim=xlim + origin[1],ylim=ylim + origin[2],xlab="",ylab="",asp=asp,yaxt="n",xaxt="n",main=main,sub=sub)
pr <- par()
if(!is.null(bg.col))polygon(pr$usr[c(1,2,2,1)],pr$usr[c(3,3,4,4)],col=bg.col)
axis(1,at=atx<-pretty(pr$usr[1:2]))
axis(2,at=aty<-pretty(pr$usr[3:4]))
} else {
do.call(PlotOnStaticMap,c(list(MyMap=MyMap),StaticMapArgs))
add <- TRUE
}
}
pr <- par()
if(!is.null(MyMap)){
if(!("TrueProj" %in% names(StaticMapArgs))||!StaticMapArgs$TrueProj){
xy_transformOriginal <- xy_transform
if(is.null(xy_transform)){
xy_transform <- function(x,y,mymap=MyMap,...){
LatLon2XY.centered(mymap,y,x)
}
} else {
xy_transform <- function(x,y,mymap=MyMap,...){
xy <- xy_transformOriginal(x,y,...)
LatLon2XY.centered(mymap,xy$y,xy$x)
}
}
}
}
if(addSource){
for(i in Source){
pg <- i
if(!is.null(xy_transform)){
pg[1:2] <- do.call(xy_transform,c(list(x=pg[,1],y=pg[,2]),transformArgs))
}
upg <- unique(pg[,3])
for(j in upg){
ind <- which(pg[,3]==j)
polygon(pg[ind,1],pg[ind,2],col="#006837")
}
}
}
# transform x/y:
if(!is.null(xy_transform)){
SensorPosition[, 2:3] <- do.call(xy_transform,c(list(x=SensorPosition[,2],y=SensorPosition[,3]),transformArgs))
}
if(showSensor){
sp_dt <- setnames(as.data.table(attr(x,"ModelInput")$Sensors[,
c("Sensor Name", "x-Coord (m)", "y-Coord (m)", "Sensor ID", "Node")]),
c("name", "x", "y", "id", "node"))[name == getThisSensor]
# cat("hier stimmt's noch nicht falls google maps!\n")
if(dispSname){
if(sp_dt[, length(unique(id)) > 1]){
sp_dt[, {
ind <- order(node)
lines(x[ind], y[ind], lty = 2, cex = 1.5)
points(x[ind], y[ind], pch = 20, cex = 1.5)
text(mean(x), mean(y), paste0(name[1], " (", .BY$id, ")"), cex = 0.6, pos = 4)
}, by = id]
} else {
sp_dt[, {
ind <- order(node)
lines(x[ind], y[ind], lty = 2, cex = 1.5)
points(x[ind], y[ind], pch = 20, cex = 1.5)
text(mean(x), mean(y), name[1], cex = 0.6, pos = 4)
}, by = id]
}
} else {
sp_dt[, {
ind <- order(node)
lines(x[ind], y[ind], lty = 2, cex = 1.5)
points(x[ind], y[ind], pch = 20, cex = 1.5)
}, by = id]
}
}
xlim <- pr$usr[1:2]
ylim <- pr$usr[3:4]
xlimOriginal <- xlim
ylimOriginal <- ylim
if(!is.null(xy_transform)){
parscale1 <- max(c(xlim[1],ylim[1]))
parscale2 <- max(c(xlim[2],ylim[2]))
lim1 <- optim(c(-1,-1),function(x)sum((unlist(do.call(xy_transform,c(list(x=x[1],y=x[2]),transformArgs))) - c(xlim[1],ylim[1]))^2),control=list(reltol=sqrt(.Machine$double.eps)/parscale1))$par
lim2 <- optim(c(1,1),function(x)sum((unlist(do.call(xy_transform,c(list(x=x[1],y=x[2]),transformArgs))) - c(xlim[2],ylim[2]))^2),control=list(reltol=sqrt(.Machine$double.eps)/parscale2))$par
xlim <- c(lim1[1],lim2[1])
ylim <- c(lim1[2],lim2[2])
}
xylim <- cbind(x=c(xlim,rev(xlim)),y=rep(ylim,each=2))
xylim <- rotate(xylim,Angle=-WDmean)
xb <- seq(min(xylim[,1])-10*dx,max(xylim[,1])+10*dx,dx)
yb <- seq(min(xylim[,2])-10*dy,max(xylim[,2])+10*dy,dy)
xm <- xb[-1] - dx/2
ym <- yb[-1] - dy/2
xy <- matrix(0,nrow=length(xm),ncol=length(ym))
# loop over index
for(j in seq_along(index)){
if (verbose) cat(j,"/",length(index),"\n")
Catalogs <- getCatalogs(x,index[j])
CatNames <- Catalogs[,Catalog]
Subset_seed <- Catalogs[, seed]
dummy <- ""
Ustardummy <- -9999
# loop over point sensors
for(i in seq_along(CatNames)){
# i <- 1
xytemp <- matrix(0,nrow=length(xm),ncol=length(ym))
if(dummy!=CatNames[i]|x[index[j],Ustar!=Ustardummy]){
dummy <- CatNames[i]
Catalog <- readCatalog(CatNames[i])
initializeCatalog(x[index[j],], Catalog=Catalog)
uvw <- uvw0(Catalog)
# subset?
if(attr(Catalog,"N0")>N0){
env <- globalenv()
oseed <- env$.Random.seed
set.seed(Subset_seed,kind="L'Ecuyer-CMRG")
takeSub <- sort(sample.int(attr(Catalog,"N0"),N0))
if (is.null(oseed)) {
rm(list = ".Random.seed", envir = env)
} else {
assign(".Random.seed", value = oseed, envir = env)
}
attCat <- attributes(Catalog)
indexNew <- 1:N0
names(indexNew) <- takeSub
Catalog <- Catalog[Traj_ID %in% takeSub,]
Catalog[,":="(Traj_ID=indexNew[as.character(Traj_ID)])]
for(ac in (names(attCat) %w/o% c("names","row.names",".internal.selfref","uvw0")))setattr(Catalog,ac,attCat[[ac]])
uvw <- uvw[takeSub,]
setattr(Catalog,"uvw0",uvw)
HeaderSub <- paste(attr(Catalog,"header"),"\n*** Subset of ",N0," Trajectories ***\n\n",sep="")
class(HeaderSub) <- c("TDhead","character")
setattr(Catalog,"N0",N0)
setattr(Catalog,"header",HeaderSub)
}
if(!is.null(wTDcutoff)) Catalog[wTD<wTDcutoff,wTD:=wTDcutoff]
Catalog[,CE:=2/wTD/N0]
if(use.avg)Catalog[,CE:=mean(CE)]
if(type[1]!="CE"){
if(type[1]=="wCE"){
w0 <- uvw0(Catalog)[,"w0"]
} else {
w0 <- uvw0(Catalog)[,"u0"] - calcU(Ustar, Zo, L, z)
}
Catalog[,CE:=w0[Traj_ID]*CE]
}
if(use.sym){
Catalog <- Catalog[rep(1:.N,2)]
Catalog[1:(.N/2),y:=-y]
Catalog[,CE:=CE/2]
}
}
Ctlg <- copy(Catalog)
rotateCatalog(Ctlg,WD[j]-WDmean)
Ctlg <- Ctlg[,":="(x=x+SPR[i,1],y=y+SPR[i,2],CE=CE/length(CatNames)/length(index))][
x>=xb[1]&x<=xb[length(xb)]&y>=yb[1]&y<=yb[length(yb)]
]
Ctlg[,":="(xtag=findInterval(x,xb, rightmost.closed = TRUE),
ytag=findInterval(y,yb, rightmost.closed = TRUE))]
Cat <- Ctlg[,sum(CE),by=.(xtag,ytag)]
xytemp[Cat[,cbind(xtag,ytag)]] <- Cat[,V1]
if(use.var){
xb2l <- Ctlg[,c(rev(seq(SPR[i,1]-3*dx/2,min(x,SPR[i,1])-10*dx,-2*dx)),seq(SPR[i,1]+dx/2,max(x,SPR[i,1])+10*dx,2*dx))]
yb2l <- Ctlg[,c(rev(seq(SPR[i,2]-3*dy/2,min(y,SPR[i,2])-10*dy,-2*dy)),seq(SPR[i,2]+dy/2,max(y,SPR[i,2])+10*dy,2*dy))]
xb2r <- xb2l + dx
yb2r <- yb2l + dx
Ctlg[,":="(
xtag_ll=findInterval(x,xb2l),ytag_ll=findInterval(y,yb2l)
,xtag_lr=findInterval(x,xb2l),ytag_lr=findInterval(y,yb2r)
,xtag_rl=findInterval(x,xb2r),ytag_rl=findInterval(y,yb2l)
,xtag_rr=findInterval(x,xb2r),ytag_rr=findInterval(y,yb2r)
)]
Cat_ll <- Ctlg[,sum(CE),by=.(xtag_ll,ytag_ll)]
Cat_lr <- Ctlg[,sum(CE),by=.(xtag_lr,ytag_lr)]
Cat_rl <- Ctlg[,sum(CE),by=.(xtag_rl,ytag_rl)]
Cat_rr <- Ctlg[,sum(CE),by=.(xtag_rr,ytag_rr)]
xy_ll <- xy_lr <- xy_rl <- xy_rr <- matrix(0,nrow=length(xb2r)-1,ncol=length(yb2r)-1)
xy_ll[Cat_ll[,cbind(xtag_ll,ytag_ll)]] <- Cat_ll[,V1]
xy_lr[Cat_lr[,cbind(xtag_lr,ytag_lr)]] <- Cat_lr[,V1]
xy_rl[Cat_rl[,cbind(xtag_rl,ytag_rl)]] <- Cat_rl[,V1]
xy_rr[Cat_rr[,cbind(xtag_rr,ytag_rr)]] <- Cat_rr[,V1]
xmil <- findInterval(xm,xb2l,all.inside = TRUE)
ymil <- findInterval(ym,yb2l,all.inside = TRUE)
xmir <- findInterval(xm,xb2r,all.inside = TRUE)
ymir <- findInterval(ym,yb2r,all.inside = TRUE)
xyi_ll <- as.matrix(expand.grid(x=xmil,y=ymil,KEEP.OUT.ATTRS=FALSE))
xyi_rr <- as.matrix(expand.grid(x=xmir,y=ymir,KEEP.OUT.ATTRS=FALSE))
xyi_lr <- as.matrix(expand.grid(x=xmil,y=ymir,KEEP.OUT.ATTRS=FALSE))
xyi_rl <- as.matrix(expand.grid(x=xmir,y=ymil,KEEP.OUT.ATTRS=FALSE))
Mu <- (xy_ll[xyi_ll] + xy_lr[xyi_lr] + xy_rl[xyi_rl] + xy_rr[xyi_rr])/4
Var <- (4*xytemp - Mu)^2
xytemp <- (xytemp*Var + (max(Var)-Var)/4*Mu)/(max(Var))
}
xy <- xy + xytemp/(dx*dy)
}
}
rm(Catalog,Ctlg,Cat)
xy[,c(1,ncol(xy))] <- 0
xy[c(1,nrow(xy)),] <- 0
}
brks <- breaks(xy)
cl <- contourLines(xm,ym,xy,levels=brks)
clRot <- lapply(cl,rotate,Angle=WDmean)
clFac <- as.factor(sapply(clRot,"[[","level"))
uclFac <- unique(clFac)
# transform x/y:
if(!is.null(xy_transform)){
clRot <- lapply(clRot,function(x){
a <- do.call(xy_transform,c(list(x=x$x,y=x$y),transformArgs))
list(level=x$level,x=a[[1]],y=a[[2]])
})
}
if (fill) {
clP <- lapply(clRot,function(x)sp::Polygon(cbind(x$x,x$y)))
clPs <- lapply(uclFac,function(x,y,z,a,b)maptools::checkPolygonsHoles(sp::Polygons(y[z==x],as.character(x)),useSTRtree=a,avoidGEOS=b),y=clP,z=clFac,a=useSTRtree,b=avoidGEOS)
clSp <- sp::SpatialPolygons(clPs,as.integer(uclFac))
# Loesung:
mlt <- switch(axs[1],
"i"=1.08,
1
)
xlim2 <- xlimOriginal - diff(xlimOriginal)*(1-1/mlt)/2;ylim2 <- ylimOriginal - diff(ylimOriginal)*(1-1/mlt)/2
c1 <- sp::Polygon(cbind(c(xlim2[1],xlim2[2],xlim2[2],xlim2[1], xlim2[1]),c(ylim2[1],ylim2[1],ylim2[2],ylim2[2],ylim2[1])))
c2 <- sp::Polygons(list(c1), "sclip")
Pclip <- sp::SpatialPolygons(list(c2))
SpPclip <- rgeos::gIntersection(clSp, Pclip, byid = TRUE)
}
alphachar <- as.hexmode(round(alpha*255))
if(is.null(cpal)){
cpal <- if(type[1]=="CE") ConcPalette(length(brks)) else FluxPalette(length(brks))
} else {
cpal <- cpal(length(brks))
}
if(!add){abline(h=aty,lty="dotted",col="lightgrey");abline(v=atx,lty="dotted",col="lightgrey")}
if (fill) {
fillcol <- paste0(cpal, alphachar)
sp::plot(SpPclip, col = fillcol, border = cpal, lty = lty, lwd = lwd, add = TRUE)
box()
} else {
for (icl in clRot) {
ibreak <- which(icl$level == brks)
lines(icl$x, icl$y,
col = cpal[(ibreak - 1) %% length(cpal) + 1],
lty = lty[(ibreak - 1) %% length(lty) + 1],
lwd = lwd[(ibreak - 1) %% length(lwd) + 1]
)
}
}
mi <- which(xy==max(xy),arr.ind=T)
if(showMax){
maxli <- rotate(cbind(x=xm[mi[1]],y=ym[mi[2]]),Angle=WD+90,Center=origin)+c(SensorPosition[,2],SensorPosition[,3])
points(maxli,pch=20,cex=0.4,col="red")
text(maxli[1],maxli[2],"max.",cex=0.6,pos=4,offset=0.2,col="red")
}
if(showLegend){
if(is.null(lpos))lpos <- c("bottomleft","topleft","topright","bottomright")[floor(WDmean/90)+1]
if(showPerc){
ltex <- sprintf(paste0("%2.",decPlaces,"f%%"),rev(brks)/max(xy)*100)
ltex <- paste0(">",ltex)
if (fill) {
temp <- legend(lpos,legend=rep(" ",length(ltex)),title="% of max.",text.width=strwidth(paste0("00",if(decPlaces>0){paste0(".",paste0(rep("0",decPlaces),collapse=""))}else{""}," %")),fill=paste0(rev(cpal),alphachar),border=rev(cpal),bg=leg.bg.col)
} else {
temp <- legend(lpos, legend = rep(" ", length(ltex)), title = "% of max.",
text.width = strwidth(paste0("00",
if (decPlaces > 0) paste0(".", paste0(rep("0", decPlaces), collapse = "")) else "", " %")),
col = rev(cpal), bg = leg.bg.col, lty = rev(lty), lwd = rev(lwd))
}
text(temp$rect$left + temp$rect$w, temp$text$y,ltex, pos = 2)
} else {
ltex <- signif(rev(brks),sigNums)
ltex <- paste0(">",ltex)
if (fill) {
legend(lpos, legend = ltex, xjust = 0, fill = paste0(rev(cpal), alphachar), border = rev(cpal), bg = leg.bg.col)
} else {
legend(lpos, legend = ltex, xjust = 0, col = rev(cpal), bg = leg.bg.col, lty = rev(lty), lwd = rev(lwd))
}
}
}
if(addWR)addWindrose(WDmean,pos=WRpos,frac=WRfrac,scF=WRscale)
scale <- if(is.null(MyMap)) 1 else MyMap
if(addSB)addScaleBar(SBpos,scale)
wm <- which(xy==max(xy),arr.ind=TRUE)
WDrad <- WDmean/180*pi
out <- structure(list(
breaks=rev(brks),
range.z=range(xy),
max.index = mi,
xy_transform = xy_transform,
transformArgs = transformArgs,
SensorPosition = SensorPosition,
WDmean = WDmean,
xlimOriginal = xlimOriginal,
ylimOriginal = ylimOriginal,
xm = xm,
ym = ym,
xy = xy), class = "footprint"
)
return(invisible(out))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.