https://github.com/cran/RandomFields
Revision a88578bf75299850a5f3ff3efba8d520c28d6a81 authored by Martin Schlather on 26 April 2005, 00:00:00 UTC, committed by Gabor Csardi on 26 April 2005, 00:00:00 UTC
1 parent b2f6358
Raw File
Tip revision: a88578bf75299850a5f3ff3efba8d520c28d6a81 authored by Martin Schlather on 26 April 2005, 00:00:00 UTC
version 1.2.10
Tip revision: a88578b
modelling.R


Kriging <- function(krige.method, x, y=NULL, z=NULL, T=NULL,
                    grid, gridtriple=FALSE,
                    model, param, given, data, trend,            
                    pch=".", return.variance=FALSE, internal=FALSE) {
  krige.methodlist <- c("S", "O")
  krige.method.nr <- pmatch(krige.method, krige.methodlist)
  is.matrix.data <- is.matrix(data) && (ncol(data)>1)
  if (internal) {
    ## do not check the user's input
    ## model must be given in the PrepareModel form
    ## grid must be false
    stopifnot(!grid)
    stopifnot(missing(param))
    pm <- model
    xdim <- ncol(x)
    tgiven <-  t(given)
    nd <- nrow(given)
  } else {
    if (is.na(krige.method.nr))
      stop(paste("kriging method not identifiable from the list.",
                 "Possible values are", paste(krige.methodlist, collapse=",")))
    x <- CheckXT(x=x, y=y, z=z, T=T, grid=grid, gridtriple=gridtriple)
    y <- z <- NULL
    pm <- PrepareModel(model=model, param=param,
                       timespacedim=x$spacedim + x$Time,
                       trend=trend)

    data <- as.matrix(data)
    given <- as.matrix(given)
    xdim <- ncol(given)

    if (pm$timespacedim!= xdim)
      stop("dimensions of the kriged points and the given points do not match")  
    stopifnot(pm$timespacedim == ncol(x$x) + !is.null(x$T)) ## program wrong
    
    nd <- nrow(given)
    pos <- integer(nd)
    ## lexicographical ordering of vectors --- necessary to check
    ## whether any location is given twice, but with different value of
    ## the data
    .C("Ordering", as.double(t(given)), as.integer(nd), as.integer(xdim), pos,
       PACKAGE="RandomFields", DUP=FALSE)
    pos <- pos + 1
    
    given <- given[pos, , drop=FALSE]
    data <- data[pos, , drop=FALSE]
    
    ## are locations given twice with different data values?
    dup <- c(FALSE, apply(abs(given[-nd, , drop=FALSE] -
                              given[-1, , drop=FALSE]), 1, sum))
    if (any(dup <- c(FALSE, apply(abs(given[-1, , drop=FALSE] -
                                      given[-nd, , drop=FALSE]), 1, sum)==0))) {
      if (any(data[dup, ] != data[c(dup[-1], FALSE), ]))
        stop("duplicated conditioning points with different data values")
      given <- given[!dup, , drop=FALSE]
      data <- data[!dup, , drop=FALSE]  
    }

    tgiven <-  t(given)
    nd <- nrow(given)
    
    if (grid) {
      zz <- cbind(x$x, x$T)
      eval(parse(text=paste("dimension <- c(",
                   paste(paste("length(seq(", zz[1,], ",", zz[2,], ",",
                               zz[3,], "))"), collapse=","),
                   ")")))
      ## `x' will be used in apply within kriging
      if ( (l <- ncol(zz))==1 ) x <- matrix(seq(zz[1], zz[2], zz[3]), ncol=1)
      else {
        text <- paste("x <- as.matrix(expand.grid(",
                      paste("seq(zz[1,", 1:l,
                            "],zz[2,", 1:l,
                            "],zz[3,", 1:l, "])", collapse=","),
                      "))")
        eval(parse(text=text))
      }
    } else x <- x$x
  } 

 
  error <- integer(1)
  
if (FALSE) if (RFparameters()$Print>3) str(list("InitUncheckedCovFct",
     as.integer(pm$covnr),
     as.double(pm$param),
     as.integer(length(pm$param)),
     as.integer(pm$timespacedim),
     as.integer(xdim),
     as.integer(length(pm$covnr)),
     as.integer(pm$anisotropy),
     as.integer(pm$op),
     as.integer(RFparameters()$PracticalRange),
     error, PACKAGE="RandomFields", DUP=FALSE))
  
   .C("InitUncheckedCovFct",
     as.integer(pm$covnr),
     as.double(pm$param),
     as.integer(length(pm$param)),
     as.integer(pm$timespacedim),
     as.integer(xdim),
     as.integer(length(pm$covnr)),
     as.integer(pm$anisotropy),
     as.integer(pm$op),
     as.integer(RFparameters()$PracticalRange),
     error, PACKAGE="RandomFields", DUP=FALSE);
  if (error) stop(" Error in definition of covariance function")


  
  covmatrix <- double(nd * nd)
  
if (FALSE) if (RFparameters()$Print>3){
  print(t(matrix(.C("vectordist", as.double(given),
                   as.integer(dim(given)),
                   vd=double(xdim * nd * (nd - 1)/2), as.integer(FALSE),
                   PACKAGE="RandomFields")$vd, ncol=xdim)))
  print(sqrt(apply(t(matrix(.C("vectordist", as.double(given),
                   as.integer(dim(given)),
                   vd=double(xdim * nd * (nd - 1)/2), as.integer(FALSE),
                   PACKAGE="RandomFields")$vd, ncol=xdim))^2, 2, sum)))
  print(list("UncheckedCovMatrix",
       t(matrix(.C("vectordist", as.double(given),
                   as.integer(dim(given)),
                   vd=double(xdim * nd * (nd - 1)/2), as.integer(FALSE),
                   PACKAGE="RandomFields")$vd, ncol=xdim)),
     nd, covmatrix, PACKAGE="RandomFields", DUP=FALSE))
}
  
  .C("UncheckedCovMatrix",
       t(matrix(.C("vectordist", as.double(given),
                   as.integer(dim(given)),
                   vd=double(xdim * nd * (nd - 1)/2), as.integer(FALSE),
                   PACKAGE="RandomFields")$vd, ncol=xdim)),
     nd, covmatrix, PACKAGE="RandomFields", DUP=FALSE)
  dim(covmatrix) <- c(nd, nd)
  given <- NULL
    
  nn <- as.integer(ncol(tgiven))

if (FALSE)if (RFparameters()$Print>3)   print(c(krige.method.nr, return.variance))
  
  switch(krige.method.nr,
         {
           ## simple kriging
           stopifnot(is.null(pm$trend))
           res <- double(nrow(x) * ncol(data))
           if (return.variance) {
             if (!(is.matrix(try(invcov <- solve(covmatrix)))))
               stop("covmatrix is singular")
             sigma2 <- double(nrow(x))
             .C("simpleKriging2", as.double(tgiven), as.double(x),
                as.double(data-pm$mean), as.double(invcov),
                as.integer(nrow(x)), nn, as.integer(ncol(x)),
                as.integer(ncol(data)), as.double(pm$mean),
                res, sigma2,
                PACKAGE="RandomFields", DUP=FALSE)           
           } else {
             if (!(is.matrix(try(invcov <- solve(covmatrix, data-pm$mean))))) 
               stop("covmatrix is singular")
             .C("simpleKriging", as.double(tgiven), as.double(x),
                as.double(invcov), as.integer(nrow(x)), nn, as.integer(ncol(x)),
                as.integer(ncol(data)), as.double(pm$mean), res,
                PACKAGE="RandomFields", DUP=FALSE)
           }
           res <- matrix(res, nrow=ncol(data))
         }, {
           ## ordinary kriging
           stopifnot(is.null(pm$trend))
           covmatrix <- rbind(cbind(covmatrix,1), c(rep(1,nd),0))
           res <- double(nrow(x) * ncol(data))    
           if (return.variance) {
             if (!(is.matrix(try(invcov <- solve(covmatrix)))))
               stop("covmatrix is singular") 
             sigma2 <- double(nrow(x))
             .C("ordinaryKriging2", as.double(tgiven), as.double(x),
                as.double(data), as.double(invcov),
                as.integer(nrow(x)), nn, as.integer(ncol(x)),
                as.integer(ncol(data)), res, sigma2,
                PACKAGE="RandomFields", DUP=FALSE)
           } else {
             if (!(is.matrix(try(invcov <- solve(covmatrix,
                                                 rbind(as.matrix(data), 0)))))) 
               stop("covmatrix is singular")
             res <- double(nrow(x) * ncol(data))

if (FALSE) if (RFparameters()$Print>3) {
   print(list("ordinaryKriging", as.double(tgiven), as.double(x),
                as.double(invcov),
                as.integer(nrow(x)), nn, as.integer(ncol(x)),
                as.integer(ncol(data)), res,
                PACKAGE="RandomFields", DUP=FALSE))
   print("eigen(cov)")
             str(covmatrix)
   print(covmatrix)
   print(eigen(covmatrix))
   print(RFparameters()$Practical)
 }
             
             .C("ordinaryKriging", as.double(tgiven), as.double(x),
                as.double(invcov),
                as.integer(nrow(x)), nn, as.integer(ncol(x)),
                as.integer(ncol(data)), res,
                PACKAGE="RandomFields", DUP=FALSE)
           }
           res <- matrix(res, nrow=ncol(data))
         }, {
           ## universal kriging
           stopifnot(!is.null(trend))
           stop("not programmed yet")
         }
         ) # switch
  if (pch!="") cat("\n")
  ncol.data <- ncol(data)
  x <- data <- NULL

  if (is.matrix.data) {
    if (grid) res <- array(t(res), dim=c(dimension, ncol.data))
    else res <- t(res)
  } else {
    if (grid) res <- array(res, dim=dimension)
    ## else res <- res
  }
  return(if (return.variance) 
         list(estim=res, var=if (grid) array(sigma2, dim=dimension) else sigma2)
  else res)
}


CondSimu <- function(krige.method, x, y=NULL, z=NULL, T=NULL,
                     grid, gridtriple=FALSE,
                     model, param, method=NULL,
                     given, data, trend,
                     n=1, register=0, 
                     err.model=NULL, err.param=NULL, err.method=NULL,
                     err.register=1, 
                     tol=1E-5, pch=".",
                     paired=FALSE,
                     na.rm=FALSE
                     ) {
  op.list <- c("+","*")  
  if (is.character(method) && (!is.na(pmatch(method, c("S","O")))))
    stop("Sorry. The parameters of the function `CondSimu' as been redefined. Use `krige.method' instead of `method'. See help(CondSimu) for details")

  x  <- CheckXT(x, y, z, T, grid, gridtriple)
  pm <- PrepareModel(model, param, x$spacedim + x$Time, trend, method=method)
  y <- z <- NULL   
  total <- x$total

  krige.mean <- 0 ## pm$mean + err$mean ??
  krige.trend <- pm$trend
  if (!is.null(krige.trend)) stop("not programmed yet")

  if (!is.null(err.model)) {
    err <- PrepareModel(err.model, err.param,x$spacedim+x$Time,method=err.method)
    if (xor(pm$anisotropy, err$anisotropy))
      stop("both, the data model and the error model must be either istropic or anisotropic")

    if (xor(is.null(pm$method), is.null(err$method)))
      stop("the simulation method must be defined for the data model and the error model or for none of them")
    if (((length(err$cov)>1 &&
          err$cov!=.C("GetModelNr", "nugget", 1, nr=integer(1),
            PACKAGE="RandomFields")$nr
          ) || err$timespacedim>1)
        && (err$timespacedim != pm$timespacedim))
      stop("time-space dimensions do not match") 
    if (!is.null(err$trend)) stop("trend for the error term not allowed")
    
    krige <- convert.to.readable(list(covnr=c(pm$covnr, err$covnr),
                                     param=c(pm$param, err$param),
                                     anisotropy = pm$anisotropy,
                                     op = c(pm$op, pmatch("+", op.list) - 1,
                                       err$op),
                                     mean = krige.mean,  
                                     trend = krige.trend,
                                     method = c(pm$method, err$method),
                                     timespacedim = pm$timespacedim
                                     )
                                )
  } else krige <-convert.to.readable(list(covnr=pm$covnr,
                                     param=pm$param,
                                     anisotropy = pm$anisotropy,
                                     op = pm$op,
                                     mean = krige.mean,  
                                     trend = krige.trend, 
                                     method = pm$method,
                                     timespacedim = pm$timespacedim
                                     )
                                )

  simu.grid <- grid
  given <- as.matrix(given)
  if (nrow(given)!=length(data)) {
    cat("dimension of 'given' does not match 'data'")
    return(NA)
  }
  if (na.rm && any(data.idx <- is.na(data))) {
    data <- data[data.idx]
    given <- given[data.idx, , drop=FALSE]
  }
  
  txt <- "kriging in space time dimensions>3 where not all the point ly on a grid is not possible yet"
  ## if 4 dimensional then the last coordinates should ly on a grid

  ## now check whether and if so, which of the given points belong to the
  ## points where conditional simulation takes place
  if (grid) {
    zz <-  cbind(x$x, x$T)
    ind <- 1 + (t(given) - zz[1, ]) / zz[3, ]
    index <-  round(ind)
    endpoints <- 1 + floor((zz[2, ] - zz[1, ]) / zz[3, ])
    outside.grid <- apply((abs(ind-index)>tol) | (index<1) |
                          (index>endpoints), 2, any)   
    if (any(outside.grid)) {
      ## at least some data points are not on the grid
      ## simulate as if there is no grid
      simu.grid <- FALSE
      l <- ncol(zz)
      if (l>3) stop(txt)
      if (l==1) xx <- matrix(seq(x$x[1], x$x[2], x$x[3]), nrow=1)
      else  eval(parse(text=paste("xx <-  t(as.matrix(expand.grid(",
                         paste("seq(zz[1,", 1:l,
                               "],zz[2,", 1:l,
                               "],zz[3,", 1:l, "])", collapse=","),
                         ")))")))
      eval(parse(text=paste("ll <- c(",
                   paste("length(seq(zz[1,", 1:l, "],zz[2,", 1:l, "],zz[3,", 1:l,
                         "]))",
                         collapse=","),
                   ")")))

      new.index <- rep(0,ncol(index))
      ## data points that are on the grid, must be registered,
      ## so that they can be used as conditioning points of the grid
      if (!all(outside.grid)) {
        new.index[!outside.grid] <- 1 +
          apply((index[, !outside.grid, drop=FALSE]-1) *
                cumprod(c(1, ll[-length(ll)])), 2, sum)
      }
      index <- new.index
      new.index <- NULL
    } else {
      ## data points are all lying on the grid     
      z <- GaussRF(x=x$x, T=x$T,  grid=TRUE, model=model, param=param,
                   method=method, n=n, register=register,
                   gridtriple=TRUE, paired=paired)
      ## for all the other cases of simulation see, below
      index <- t(index)
    }
  } else {
    xx <- t(as.matrix(x$x)) ## not a grid
    
    if (!is.null(x$T)) {
      if (ncol(xx) > 2) stop(txt)
      T <- seq(x$T[1], x$T[2], x$T[3])
      ## multiple the xx structure by length of T,
      ## then add first component of T to first part ... last component of T
      ## to last part
      xx <- rbind(matrix(xx, nrow=nrow(xx), ncol=ncol(xx) * length(T)),
                  as.vector(t(matrix(T, nrow=length(T),ncol(xx)))))
    }
    
    ## the next step can be pretty time consuming!!!
    ## to.do: programme it in C
    ##
    ## identification of the points that are given twice, as points to
    ## be simulated and as data points (up to a tolerance distance !)
    ## this is important in case of nugget effect, since otherwise
    ## the user will be surprised not to get the value of the data at
    ## that point
    one2ncol.xx <- 1:ncol(xx)
    index <- apply(as.matrix(given), 1, function(z){
      i <- one2ncol.xx[apply(abs(xx - z), 2, sum) < tol]
      if (length(i)==0) return(0)
      if (length(i)==1) return(i)
      return(NA)
    })
  }  
  
  if (!simu.grid) {
    ## otherwise the simulation has already been performed (see above)
    tol <- tol * nrow(xx)
    if (any(is.na(index)))
      stop("identification of the given data points is not unique - `tol' too large?")
    if (any(notfound <- (index==0))) {
      index[notfound] <- (ncol(xx) + 1) : (ncol(xx) + sum(notfound))
    }
    xx <- rbind(t(xx), given[notfound, , drop=FALSE])
    z <- GaussRF(x=xx, grid=FALSE, model=model, param=param,
                 method=method, n=n, register=register, paired=paired)
    xx <- NULL
  }
  if (is.null(z)) stop("random fields simulation failed")
  
  if (n==1) {
    ## z values at the `given' locations
    zgiven <- z[index]
    z <- z[1:total]
  } else {
    ## this is a bit more complicated since index is either a vector or
    ## a matrix of dimension dim(z)-1
    zgiven <- matrix(apply(z, length(dim(z)), function(m) m[index]), ncol=n)
    z <- as.vector(apply(z, length(dim(z)), function(m) m[1:total]))
  }
  
  if (!is.null(err.model)) {
     error <- GaussRF(given, grid=FALSE, model=err.model, param=err.param,
                      method=err.method, n=n, register=err.register,
                      paired=paired)
     if (is.null(error)) stop("error field simulation failed")
     zgiven <- zgiven + as.vector(error)
     error <- NULL
   }

  # zgiven is matrix  
  z +  Kriging(krige.method=krige.method,
              x=x$x, grid=grid,
              model=krige,
              given=given,data=as.vector(data)-zgiven,
              gridtriple=TRUE, pch=pch)
}
  
back to top