1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
#
# fields is a package for analysis of spatial data written for
# the R software environment.
# Copyright (C) 2024 Colorado School of Mines
# 1500 Illinois St., Golden, CO 80401
# Contact: Douglas Nychka, douglasnychka@gmail.com,
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with the R software environment if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# or see http://www.r-project.org/Licenses/GPL-2
##END HEADER\
offGridWeights1D<-function(s, gridList, np=2,
mKrigObject=NULL,
Covariance=NULL, covArgs=NULL,
aRange=NULL, sigma2=NULL,
giveWarnings=TRUE,
debug=FALSE
){
#
# function assumes the grid is
# integer locations and 1:m by 1:n
# grid and off grid locations need to be transformed to that scale
#
# also assumes the grid extends two cells beyond any off
# e.g. s coordinates should be between
# 2 and m-3 and 2 and n-3
#
# If mKrigObject (result of fitting model) is given
# extract all the covariance information from it.
# For the Matern family besides aRange and sigma2 is the
# smoothness
if( !is.null( mKrigObject)){
sigma2<- mKrigObject$summary["sigma2"]
aRange<- mKrigObject$summary["aRange"]
Covariance<- mKrigObject$args$Covariance
if( is.null(Covariance)){
Covariance<- "Exponential"
}
covArgs<-mKrigObject$args
# some R arcania -- strip out all arguments used by say stationary.cov
# but not used by the Covariance function
# Do not want to call the covariance function with these extra args.
if( !is.null( covArgs) ){
argNames<- names( as.list( get(Covariance)))
argNames<- argNames[ -length(argNames)]
ind<- match( names(covArgs), argNames)
covArgs[is.na( ind)] <- NULL
}
}
m<- length( gridList$x)
dx<- gridList$x[2]- gridList$x[1]
M<- nrow( s)
# lower left corner of grid box containing the points
s0<- cbind(
trunc( (s[,1]- gridList$x[1] )/dx) + 1
)
# index of locations when 2D array is unrolled
s0Index<- as.integer( s0[,1])
# check for more than one obs in a grid box
tableLoc<- table( s0Index)
allSingle<- all( tableLoc ==1 )
theShift<- (0:(2*np-1)) - (np-1)
xshift<- theShift
nnX<- cbind( xshift)
nnXCoords<- cbind( xshift*dx)
#
# sX
sX<- s0[,1] + matrix( rep( xshift,M),
nrow=M, ncol=(2*np), byrow=TRUE)
if( any( (sX < 1)| (sX>m)) ) {
stop( "sX outside range for grid")
}
# indices of all nearest neighbors for unrolled vector.
# this is an M by (2*np)^2 matrix where indices go from 1 to m*n
# these work for the unrolled 2D array
#
sIndex<- sX
# differences between nn and the off grid locations
# for both coordinates
# convert from integer grid to actual units.
differenceX<- (sX-1)*dx + gridList$x[1] - s[,1]
dAll<- abs(differenceX)
# pairwise distance among nearest neighbors.
dNN<- rdist(nnXCoords, nnXCoords)
# cross covariances
Sigma21Star<- sigma2* do.call(Covariance,
c(list(d = dAll/aRange),
covArgs))
# covariance among nearest neighbors
Sigma11 <- sigma2* do.call(Covariance,
c(list(d = dNN/aRange),
covArgs))
Sigma11Inv <- solve( Sigma11)
# each row of B are the weights used to predict off grid point
B <- Sigma21Star%*%Sigma11Inv
# create spind sparse matrix
# note need to use unrolled indices to refer to grid points
ind<- cbind( rep(1:M, each= (2*np) ), c( t( sIndex)))
ra<- c( t( B))
da<- c( M, m )
spindBigB<- list(ind=ind, ra=ra, da=da )
# now convert to the more efficient spam format
BigB<- spind2spam( spindBigB)
#
# prediction variances
# use cholesky for more stable numerics
cholSigma11Inv<- chol(Sigma11Inv)
# create spind sparse matrix of sqrt variances
# or covariances to simulate prediction error.
w <- Sigma21Star%*%t(cholSigma11Inv)
predictionVariance <- sigma2 - rowSums(w^2)
# easiest case of just one obs in each grid box
# sigma2 - diag(Sigma21Star%*%Sigma11Inv%*%t(Sigma21Star) )
spindObjSE<- list(ind=cbind( 1:M, 1:M),
ra=sqrt(predictionVariance),
da= c( M,M)
)
BigSE<- spind2spam( spindObjSE)
if(allSingle){
duplicateIndex<-NA
}
if( !allSingle){
indDuplicates<- (tableLoc > 1)
if( giveWarnings){
cat("Found", sum(indDuplicates),
"grid box(es) containing more than 1 obs location",
fill=TRUE)
}
duplicateIndex<-names( tableLoc) [indDuplicates]
duplicateIndex<- as.numeric(duplicateIndex)
# duplicateIndex is the unrolled indices for all grid boxes with
# 2 or more observations
# following code is written assuming there are not many of these.
nBox<- length( duplicateIndex)
indDupSE<-NULL
raDupSE<- NULL
for( k in 1:nBox){
theBox<- duplicateIndex[k]
# the obs that are in this box
indBox<- which(s0Index == theBox)
nDup<- length( indBox)
dDup<- rdist( s[indBox,], s[indBox,])
sigmaMarginal<- sigma2* do.call(Covariance,
c(list(d = dDup/aRange),
covArgs))
A<- w[indBox,]
localSE2<- sigmaMarginal - A%*%t(A)
localSE<- t(chol( localSE2 ))
# localSE %*% rnorm(nDup) will generate correct corrected
# prediction errors for obs in this grid box ("theBox")
indTmp<- cbind(rep( indBox, nDup), rep( indBox, each=nDup) )
raTmp<- c(localSE)
indDupSE<- rbind( indDupSE,indTmp)
raDupSE<- c( raDupSE, raTmp)
}
#print( dim(indDupSE ))
#print( length(raDupSE))
BigSE[indDupSE]<- raDupSE
}
if( debug){
return(
list( B= BigB, SE= BigSE,
predictionVariance = predictionVariance,
Sigma11Inv = Sigma11Inv,
Sigma21Star= Sigma21Star,
s0Index = s0Index,
s0 = s0,
gridX = t( (sX-1)*dx + gridList$x[1]),
gridList = gridList,
duplicateIndex= duplicateIndex
)
)
}
else{
return(
list( B = BigB,
SE = BigSE,
predictionVariance = predictionVariance )
)
}
}
|