File: spatialProcess.R

package info (click to toggle)
r-cran-fields 16.3.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,972 kB
  • sloc: fortran: 1,021; ansic: 288; sh: 35; makefile: 2
file content (331 lines) | stat: -rw-r--r-- 12,246 bytes parent folder | download
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
#
# 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
spatialProcess <- function(x, y,  weights = rep(1, nrow(x)),   Z = NULL,
                     ZCommon = NULL,
                  mKrig.args = NULL,
                cov.function = NULL, 
                  	cov.args = NULL,
                      parGrid = NULL, 
                      reltol = 1e-4,
                       na.rm = TRUE,
                  	 verbose = FALSE,
                        REML = FALSE, 
            cov.params.start = NULL,
                       gridN = 5,
               profileLambda = FALSE,
               profileARange = FALSE,
               profileGridN  = 15, 
                  gridARange = NULL,
                  gridLambda = NULL,
                     CILevel = .95,
                       iseed = 303, 
         collapseFixedEffect = TRUE,
                           ...) {
 
# Through out this code:  obj is the output list and will be added to throughout the computation
# This device is typical in fields functions where a list is built up in the process of the 
# computation. 
  
#  THE RULES: 
# Being in the cov.params.start list means a parameter will be optimized
# by maximum likelhood. 
# If a  parameter is in the cov.args list it will be fixed at that value
#  
  
# NOTE all the  ... extra arguents are assumed to be for the cov.args list
  GCV<- FALSE # A top level placeholder to add GCV search capability once
# algorithm is stable 
# this default choice is used in the next level functions.
############################################################ 
#### Setting some defaults for the covariance function and parameters
############################################################ 
  

  
# It is also convenient to just add a few arugments of the covariance driectly in the 
# this list collects those.  E.g. spatialProcess( x, y, Covariance="Exponential" )
# will pass this choice along to the default covariance function, stationary.cov
#
  
  extraArgs<- list(...)
  
   if( REML&GCV){
     stop("Cannot optimize for both REML and GCV!")
   }
  
# set defaults based on the model passed. 
# the following function fills in some typical models and 
# just avoids some typing and makes for some clean examples
#   
# note this also creates the initial components for the output list. 
#
   obj<- spatialProcessSetDefaults(x, 
                            cov.function = cov.function, 
                                cov.args = cov.args,
                        cov.params.start = cov.params.start,
                              mKrig.args = mKrig.args,
                               extraArgs = extraArgs,
                                 parGrid = parGrid,
                                   gridN = gridN,
                     collapseFixedEffect =  collapseFixedEffect,
                                 verbose = verbose)
   #
   # obj$CASE 
   # 0 evaluate on passed cov parameters but MLEs for sigma, tau found from
   #   lambda
   #
   # 1 optimize loglikelihood over any parameters specified in 
   #   cov.params.start but not in cov.args
   #
   # 2  grid search over parameters using parGrid and generating starting values for 
   #   for the MLEs 
   #
   # 3 profile over lambda and/or aRange 
   # this is more computationally demanding. 
   
  if( verbose){
    cat(" The CASE:", obj$CASE, fill=TRUE)
    cat("Complete list of components in cov.args: ", "\n",
        names(obj$cov.args),fill=TRUE )
    cat("Complete list of components in mKrig.args: ", "\n",
        names(obj$mKrig.args),fill=TRUE )
  }
   
  if( verbose){
     cat( "Names cov.args:","\n", names( obj$cov.args), fill=TRUE)
     cat( "Names cov.params.start:","\n", names(cov.params.start), fill=TRUE)
     cat( "Names argsFull:","\n", names( obj$cov.argsFull),fill=TRUE  )
   }
   
   
####################################################################  
# CASE 2 grid search for starting values 
####################################################################  
   
  if( (obj$CASE == 2 )  ){
    if( verbose){
      
      cat("*****************************************", fill=TRUE)
      cat("***** Grid search ", fill=TRUE)
      cat("***** Grid search starting values: ", fill=TRUE)
      print(cov.params.start )
      cat("***** parGrid names: " , fill=TRUE)
      print( names( parGrid))
      cat("***** the grid to search:", fill=TRUE)
      print( names( obj$parGrid))
    }
    
    InitialGridSearch<- mKrigMLEGrid(x, y,  
                             weights = weights,
                                   Z = Z, 
                             ZCommon = ZCommon,
                          mKrig.args = mKrig.args,
                        cov.function = obj$cov.function, 
                           cov.args  = obj$cov.args,
                            par.grid = obj$parGrid, 
                              reltol = reltol,
                               na.rm = na.rm,
                             verbose = verbose,
                                REML = REML,
                                 GCV = GCV,
                    cov.params.start = cov.params.start)
  # use grid search to set starting values
    if( all(is.na(InitialGridSearch$summary) )) {
      cat("spatialProcess: Problems with optim in grid search", fill=TRUE)
      cat("returned object includes the likelihood evaluations up to the 
         error", fill=TRUE)
      InitialGridSearch$optimSuccess<- FALSE
      InitialGridSearch$call<- match.call()
      return(InitialGridSearch)
    }
    
    if( verbose){
      cat("results of intitial grid search: ", fill=TRUE)
      print(InitialGridSearch$indMax )
    }
    parNames<- names( obj$parGrid)
    if( is.null( cov.params.start)){
      cov.params.start<- obj$parGrid[InitialGridSearch$indMax,]
      names(cov.params.start )<- parNames
    }
    else{
    cov.params.start[parNames] <- 
       obj$parGrid[InitialGridSearch$indMax, parNames]
    }
 }
   
####################################################################  
# CASES 1 , 2 , 3, 4
#################################################################### 
   if(obj$CASE !=0 ){
     # optimze over all parameters 
     # where starting values are given or if
     # values in cov.args are omitted. 
     obj$cov.params.start<- cov.params.start
     MLEInfo <-mKrigMLEJoint(x, y,  weights = weights, Z = Z, 
                             ZCommon = ZCommon,
                             mKrig.args = obj$mKrig.args,
                             cov.function = obj$cov.function, 
                             cov.args  = obj$cov.args,
                             na.rm = na.rm,
                             reltol=reltol,
                             cov.params.start = cov.params.start,
                             REML = REML,
                             GCV = GCV,
                             hessian = TRUE,
                             verbose = verbose,
                             iseed = iseed)
       
     
   
   if( is.na(MLEInfo$summary[1])){
     cat("spatialProcess: Problems with optim in mKrigMLEJoint ", 
         fill=TRUE)
     cat("returned object includes the likelihood evaluations up to the 
         error", fill=TRUE)
     MLEInfo$optimSuccess<- FALSE
     MLEInfo$call<- match.call()
     return(MLEInfo)
   }
    
  covarianceMLE<-  -1*solve(MLEInfo$optimResults$hessian)
  HessianResults<- diag( covarianceMLE)
   if( any( HessianResults < 0) ) {
       warning("Numerical hessian from optim indicates
                   MLE is not a maximum")
     }
      
   }
   
   
################################################################################
# final fit 
# now fit spatial model with MLE(s) 
# or the value(s) supplied in the call
# reestimate the other parameters for simplicity to get the
# complete mKrig object
####################################################################
   
# if all parameters are fixed -- don't mess with cov.args   
   if( obj$CASE == 0){
     obj$cov.argsFull <-  obj$cov.args
   }
   else{
      dupParameters<- match( names(MLEInfo$pars.MLE ), names(cov.args) )
     if( all( is.na(dupParameters)) ){
       obj$cov.argsFull<- c( obj$cov.args,
                             as.list(MLEInfo$pars.MLE) )
     }
   }
   
  
  
  mKrigObj <- do.call( "mKrig", 
	                c( list(x=x,
	                        y=y,
	                  weights=weights,
	                        Z=Z,
	                  ZCommon=ZCommon),
	                  obj$mKrig.args,
	             list( na.rm=na.rm),
	             list(cov.function = obj$cov.function),
	                  obj$cov.argsFull 
	            	)
             	)

####################################################################
# sort out output object based on the different cases
# also copy some information from the call and within function
# the output list, obj
####################################################################
  obj$GCV    <- GCV
  obj$REML   <- REML
  obj$CILevel<- CILevel
  
  if( obj$CASE==0){
    obj$MLEInfo <- NULL
    obj$MLESummary <- mKrigObj$summary
    obj$InitialGridSearch<- NULL
    obj$parameterCovariance<- NULL
  }
  
  if( obj$CASE==1){
    InitialGridSearch<- NULL
  }
  
####################################################################
#  Fill in all info related to finding MLE (Not CASE 0)
####################################################################
  if( obj$CASE!=0){
    # logical to distinguish from optim failure
    obj$optimSuccess<-TRUE
    #
    obj$InitialGridSearch<- InitialGridSearch
    obj$MLEInfo<- MLEInfo
    obj$MLESummary <- MLEInfo$summary
    # NOTE: covariance for lambda and ARange based on log(lambda) and log(ARange)
    obj$parameterCovariance<- solve(
            -1*MLEInfo$optimResults$hessian)
####################################################################
# Approximate large sample confidence intervals on the transformed scale
# followed by
#	then transforming back to original scale (see MLEInfo$par.transform)
# These are filled with NAs when numerical Hessian is not
# positive definite
####################################################################	
    obj$CITable<- confidenceIntervalMLE(obj, CILevel)
  }
  
  # combine everything into the output list, mKrig components first. 
  obj <- c( mKrigObj,obj)
  # replace call in mKrig  object with the top level one
  # from spatialProcess
  obj$call<- match.call()	
  
  class(obj) <- c( "spatialProcess","mKrig")
  
####################################################################
# Profiling depends on complete spatial process obj 
# which is why this is last
####################################################################	
  
  if (profileLambda) {
    obj$profileSummaryLambda <- profileMLE(obj, "lambda",
                                           parGrid = gridLambda,
                                           gridN = profileGridN
                                           )$summary
  }
  else{
    obj$profileSummaryLambda <- NULL
  }
  if (profileARange) {
    obj$profileSummaryARange <- profileMLE(obj, "aRange",
                                           parGrid = gridARange,
                                           gridN = profileGridN,
                                           )$summary
  }
  else{
    obj$profileSummaryARange <- NULL
  }
  

	return(obj)
}