https://github.com/cran/spatstat
Raw File
Tip revision: 3aca716ce2576a0dab83f08052acd47afed8ee6a authored by Adrian Baddeley on 29 February 2012, 00:00:00 UTC
version 1.25-4
Tip revision: 3aca716
summary.ppm.R
#
#    summary.ppm.R
#
#    summary() method for class "ppm"
#
#    $Revision: 1.51 $   $Date: 2012/01/31 07:52:12 $
#
#    summary.ppm()
#    print.summary.ppm()
#
summary.ppm <- function(object, ..., quick=FALSE) {
  verifyclass(object, "ppm")

  x <- object
  y <- list()
  
  #######  Extract main data components #########################

  QUAD <- object$Q
  DATA <- QUAD$data
  TREND <- x$trend

  INTERACT <- x$interaction
  if(is.null(INTERACT)) INTERACT <- Poisson()
  
  #######  Check version #########################

  mpl.ver <- versionstring.ppm(object)
  int.ver <- versionstring.interact(INTERACT)
  current <- versionstring.spatstat()

  virgin <- min(package_version(c(mpl.ver, int.ver)))

  y$antiquated <- antiquated <- (virgin <= package_version("1.5"))
  y$old        <- old        <- (virgin < majorminorversion(current))

  y$version    <- as.character(virgin)
                
  ####### Determine type of model ############################
  
  y$entries <- list()
  y$no.trend <- identical.formulae(TREND, NULL) || identical.formulae(TREND, ~1)
  y$trendvar <- trendvar <- variablesinformula(TREND)
  y$stationary <- y$no.trend || all(trendvar == "marks")

  y$poisson <- is.poisson.interact(INTERACT)

  y$marked <- is.marked.ppp(DATA)
  y$multitype <- is.multitype.ppp(DATA)
  y$marktype <- if(y$multitype) "multitype" else
                if(y$marked) "marked" else "unmarked"

  if(y$marked) y$entries$marks <- marks(DATA)

  y$name <- paste(
          if(y$stationary) "Stationary " else "Nonstationary ",
          if(y$poisson) {
            if(y$multitype) "multitype "
            else if(y$marked) "marked "
            else ""
          },
          INTERACT$name,
          sep="")

  ######  Fitting algorithm ########################################

  y$method <- x$method
  
  y$problems <- x$problems

  y$fitter <- x$fitter
  if(y$fitter %in% c("glm", "gam"))
    y$converged <- x$internal$glmfit$converged

  ######  Coefficients were changed after fit? #####################
  
  y$projected <- identical(x$projected, TRUE)
  y$changedcoef <- y$projected || (y$method != "mpl")

  ######  Extract fitted model coefficients #########################

  y$entries$coef <- COEFS <- x$coef

  y$entries$Vnames <- Vnames <- x$internal$Vnames
  y$entries$IsOffset <- x$internal$IsOffset

  ###### Extract fitted interaction and summarise  #################
  
  FITIN <- fitin(x)
  y$interaction <- summary(FITIN)

  # Exit here if quick=TRUE
    
  if(identical(quick, TRUE)) {
    class(y) <- "summary.ppm"
    return(y)
  }
  

  ######  Does it have external covariates?  ####################

  if(!antiquated) {
    covars <- x$covariates
    y$has.covars <- !is.null(covars) && (length(covars) > 0)
    y$covnames <- names(covars)
    used <- (y$trendvar %in% names(covars))
    y$covars.used <- y$trendvar[used]
    y$uses.covars <- any(used)
    # describe covariates
    covtype <- function(x) {
      if(is.im(x)) "im" else
      if(inherits(x, "distfun")) "distfun" else
      if(is.function(x)) "function" else
      if(is.owin(x)) "owin" else
      if(is.numeric(x) && length(x) == 1) "number" else "unknown"
    }
    y$covar.type <- ctype <- unlist(lapply(covars, covtype))
    y$covar.descrip <- y$covar.type
    # are there any functions?
    y$has.funcs <- any(isfun <- (ctype == "function"))
    # do covariates depend on additional arguments?
    if(y$has.funcs) {
      y$covfunargs <- x$covfunargs
      funs <- covars[isfun]
      fdescrip <- function(f) {
        alist <- paste(names(formals(f)), collapse=", ")
        paste("function(", alist, ")", sep="")
      }
      y$covar.descrip[isfun] <- unlist(lapply(funs, fdescrip))
      # find any extra arguments (after args 1 & 2) explicitly named
      xargs <- function(f) {
        ar <- names(formals(f))[-(1:2)]
        return(ar[ar != "..."])
      }
      fargs <- lapply(funs, xargs)
      nxargs <- unlist(lapply(fargs, length))
      y$has.xargs <- any(nxargs > 0)
      if(y$has.xargs) {
        # identify which function arguments are fixed in the call
        fmap <- data.frame(Covariate=rep(names(funs), nxargs),
                                 Argument=unlist(fargs))
        fmap$Given <- (fmap$Argument %in% names(y$covfunargs))
        y$xargmap <- fmap
      }
    } 
  } else {
    # Antiquated format
    # Interpret the function call instead
    callexpr <- parse(text=x$call)
    callargs <- names(as.list(callexpr[[1]]))
    # Data frame of covariates was called 'data' in versions up to 1.4-x
    y$has.covars <- !is.null(callargs) && !is.na(pmatch("data", callargs))
    # conservative guess
    y$uses.covars <- y$has.covars
    y$covfunargs <- NULL
  }
    
  ######  Arguments in call ####################################
  
  y$args <- x[c("call", "correction", "rbord")]
  
  #######  Main data components #########################

  y$entries <- append(list(quad=QUAD,
                           data=DATA,
                           interaction=INTERACT),
                      y$entries)

  ####### Summarise data ############################

  y$data <- summary.ppp(DATA, checkdup=FALSE)
  y$quad <- summary.quad(QUAD, checkdup=FALSE)

  if(is.character(quick) && (quick == "no prediction"))
    return(y)
  
  ######  Trend component #########################

  y$trend <- list()

  y$trend$name <- if(y$poisson) "Intensity" else "Trend"

  y$trend$formula <- if(y$no.trend) NULL else TREND

  if(y$poisson && y$no.trend) {
    # uniform Poisson process
    y$trend$value <- lambda <- exp(COEFS[[1]])
    y$trend$label <- switch(y$marktype,
                            unmarked="Uniform intensity",
                            multitype="Uniform intensity for each mark level",
                            marked="Uniform intensity in product space",
                            "")
  } else if(y$stationary) {
    # stationary
    switch(y$marktype,
           unmarked={
             # stationary non-poisson non-marked
             y$trend$label <- "First order term"
             y$trend$value <- c(beta=exp(COEFS[[1]]))
           },
           multitype={
             # stationary, multitype
             mrk <- marks(DATA)
             y$trend$label <-
               if(y$poisson) "Intensities" else "First order terms"
             # Use predict.ppm to evaluate the fitted intensities
             lev <- factor(levels(mrk), levels=levels(mrk))
             nlev <- length(lev)
             marx <- list(x=rep(0, nlev), y=rep(0, nlev), marks=lev)
             betas <- predict(x, locations=marx, type="trend")
             names(betas) <- paste("beta_", as.character(lev), sep="")
             y$trend$value <- betas
           },
           marked={
             # stationary, marked
             y$trend$label <- "Fitted intensity coefficients"
             y$trend$value <- blankcoefnames(COEFS)
           })
  } else {
    # not stationary 
    y$trend$label <- "Fitted coefficients for trend formula"
    # extract trend terms without trying to understand them much
    if(is.null(Vnames)) 
      trendbits <- COEFS
    else {
      agree <- outer(names(COEFS), Vnames, "==")
      whichbits <- apply(!agree, 1, all)
      trendbits <- COEFS[whichbits]
    }
    y$trend$value <- blankcoefnames(trendbits)
  }
  
  # ----- parameters with SE --------------------------
  if(y$poisson && (length(COEFS) > 0)) {
    # compute standard errors
    se <- x$internal$se
    if(is.null(se)) {
      vc <- vcov(x, matrix.action="silent")
      if(!is.null(vc))
        se <- sqrt(diag(vc))
    }
    if(!is.null(se)) {
      two <- qnorm(0.975)
      lo <- COEFS - two * se
      hi <- COEFS + two * se
      pval <- 2 * pnorm(abs(COEFS)/se, lower.tail=FALSE)
      psig <- cut(pval, c(0,0.001, 0.01, 0.05, 1),
                  labels=c("***", "**", "*", " "))
      notapplic <- names(COEFS) %in% c("(Intercept)", "log(lambda)")
      psig[notapplic] <- " "
      # table of coefficient estimates with SE and 95% CI
      y$coefs.SE.CI <- data.frame(Estimate=COEFS, S.E.=se, Ztest=psig,
                                  CI95.lo=lo, CI95.hi=hi)
    }
  }
  
  class(y) <- "summary.ppm"
  return(y)
}

coef.summary.ppm <- function(object, ...) {
  object$coefs.SE.CI
}

print.summary.ppm <- function(x, ...) {

  if(x$old)
    warning("Model was fitted by an older version of spatstat")
  
  if(is.null(x$args)) {
    # this is the quick version
    cat(paste(x$name, "\n"))
    return(invisible(NULL))
  }

  # otherwise - full details
  cat("Point process model\n")
  methodchosen <-
    if(is.null(x$method))
      "unspecified method"
    else 
      switch(x$method,
             mpl={
               if(!x$poisson) {
                 "maximum pseudolikelihood (Berman-Turner approximation)"
               } else {
                 # Poisson process
                 if(x$fitter == "exact") "maximum likelihood" else
                 "maximum likelihood (Berman-Turner approximation)"
               } 
             },
             ho="Huang-Ogata method (approximate maximum likelihood)",
             paste("unrecognised method", sQuote(x$method)))
  cat(paste("Fitting method:", methodchosen, "\n"))
  howfitted <- switch(x$fitter,
                      exact= "analytically",
                      gam  = "using gam()",
                      glm  = "using glm()",
                      ho   = NULL,
                      paste("using unrecognised fitter", sQuote(x$fitter)))
  if(!is.null(howfitted)) cat(paste("Model was fitted", howfitted, "\n"))
  if(x$fitter %in% c("glm", "gam")) {
    if(x$converged) cat("Algorithm converged\n")
    else cat("*** Algorithm did not converge ***\n")
  }
  if(x$projected)
    cat("Fit was projected to obtain a valid point process model\n")

  cat("Call:\n")
  print(x$args$call)

  if(x$old) 
    cat(paste("** Executed by old spatstat version", x$version, " **\n"))
  
  cat(paste("Edge correction:", dQuote(x$args$correction), "\n"))
  if(x$args$correction == "border")
    cat(paste("\t[border correction distance r =", x$args$rbord,"]\n"))

  cat("\n----------------------------------------------------\n")

  # print summary of quadrature scheme
  print(x$quad)
  
  cat("\n----------------------------------------------------\n")
  cat("FITTED MODEL:\n\n")

  # This bit is currently identical to print.ppm()
  # except for a bit more fanfare
  # and the inclusion of the 'gory details' bit
  
  notrend <-    x$no.trend
  stationary <- x$stationary
  poisson <-    x$poisson
  markeddata <- x$marked
  multitype  <- x$multitype
        
  markedpoisson <- poisson && markeddata

  # ----------- Print model type -------------------
        
  cat(x$name)
  cat("\n")

  if(markeddata) mrk <- x$entries$marks
  if(multitype) {
    cat("Possible marks: \n")
    cat(paste(levels(mrk)))
  }

  # ----- trend --------------------------

  cat(paste("\n\n ---- ", x$trend$name, ": ----\n\n", sep=""))

  if(!notrend) {
    cat("Trend formula: ")
    print(x$trend$formula)
    if(x$uses.covars) 
      cat(paste("Model depends on external",
                ngettext(length(x$covars.used), "covariate", "covariates"),
                commasep(sQuote(x$covars.used)), "\n"))
  }
  if(x$has.covars) {
    if(notrend || !x$uses.covars)
      cat("Model object contains external covariates\n")
    if(!is.null(cd <- x$covar.descrip)) {
      # print description of each covariate
      cat("\nCovariates provided:\n")
      namescd <- names(cd)
      for(i in seq_along(cd))
        cat(paste("\t", namescd[i], ": ", cd[i], "\n", sep=""))
    }
    if(!is.null(cfa <- x$covfunargs) && length(cfa) > 0) {
      cat("Covariate function arguments (covfunargs) provided:\n")
      namescfa <- names(cfa)
      for(i in seq_along(cfa)) {
        cat(paste(namescfa[i], "= "))
        cfai <- cfa[[i]]
        if(is.numeric(cfai) && length(cfai) == 1) {
          cat(paste(cfai, "\n"))
        } else print(cfa[[i]])
      }
    }
  }

  cat(paste("\n", x$trend$label, ":\n", sep=""))
  
  tv <- x$trend$value
  if(!is.list(tv))
    print(tv)
  else 
    for(i in seq_along(tv))
      print(tv[[i]])

  # table of coefficient estimates with SE and 95% CI
  if(!is.null(cose <- x$coefs.SE.CI)) {
    cat("\n")
    print(cose)
  }
  
  # ---- Interaction ----------------------------

  if(!poisson) {
    cat("\n\n ---- Interaction: -----\n\n")
    print(x$interaction)
  }

  ####### Gory details ###################################
  cat("\n\n----------- gory details -----\n")
  COEFS <- x$entries$coef
  
  cat("\nFitted regular parameters (theta): \n")
  print(COEFS)

  cat("\nFitted exp(theta): \n")
  print(exp(unlist(COEFS)))

  ##### Warnings issued #######

  probs <- x$problems
  if(!is.null(probs) && is.list(probs) && (length(probs) > 0)) 
    lapply(probs,
           function(a) {
             if(is.list(a) && !is.null(p <- a$print))
               cat(paste("Problem:\n", p, "\n\n"))
           })
          
  return(invisible(NULL))
}

no.trend.ppm <- function(x) {
  summary.ppm(x, quick=TRUE)$no.trend
}

is.stationary <- function(x) {
  UseMethod("is.stationary")
}

is.poisson <- function(x) {
  UseMethod("is.poisson")
}

is.stationary.ppm <- function(x) {
  TREND <- x$trend
  if(is.null(TREND) || identical.formulae(TREND, ~1))
    return(TRUE)
  if(all(variablesinformula(TREND) == "marks"))
    return(TRUE)
  return(FALSE)
}

is.poisson.ppm <- function(x) {
  stopifnot(is.ppm(x))
  y <- x$interaction
  if(is.null(y)) y <- Poisson()
  is.poisson.interact(y)
}

is.marked.ppm <- function(X, ...) {
  summary.ppm(X, quick=TRUE)$marked
}

is.multitype.ppm <- function(X, ...) {
  summary.ppm(X, quick=TRUE)$multitype
}

blankcoefnames <- function(x) {
  # remove name labels from ppm coefficients
  # First decide whether there are 'labels within labels'
  unlabelled <- unlist(lapply(x,
                              function(z) { is.null(names(z)) } ))
  if(all(unlabelled))
    value <- unlist(x)
  else {
    value <- list()
    for(i in seq_along(x))
      value[[i]] <- if(unlabelled[i]) unlist(x[i]) else x[[i]]
  }
  return(value)
} 
back to top