Revision 56d752cf6d1a8e2775e1acc46482c206cfd5b269 authored by Adrian Baddeley on 14 March 2012, 07:09:51 UTC, committed by cran-robot on 14 March 2012, 07:09:51 UTC
1 parent a4d492a
Raw File
Kest.R
#
#	Kest.R		Estimation of K function
#
#	$Revision: 5.82 $	$Date: 2012/02/29 05:06:36 $
#
#
# -------- functions ----------------------------------------
#	Kest()		compute estimate of K
#                       using various edge corrections
#
#
# -------- standard arguments ------------------------------	
#	X		point pattern (of class 'ppp')
#
#	r		distance values at which to compute K	
#
# -------- standard output ------------------------------
#      A data frame (class "fv") with columns named
#
#	r:		same as input
#
#	trans:		K function estimated by translation correction
#
#	iso:		K function estimated by Ripley isotropic correction
#
#	theo:		K function for Poisson ( = pi * r ^2 )
#
#	border:		K function estimated by border method
#			using standard formula (denominator = count of points)
#
#       bord.modif:	K function estimated by border method
#			using modified formula 
#			(denominator = area of eroded window
#
# ------------------------------------------------------------------------

"Lest" <- function(X, ...) {
  K <- Kest(X, ...)
  L <- eval.fv(sqrt(K/pi))
  # handle variance estimates
  if(any(varcols <- colnames(K) %in% c("rip", "ls"))) {
    r <- with(L, .x)
    L[,varcols] <- as.data.frame(K)[,varcols]/(2 * pi * r)^2
    # fix 0/0
    n <- npoints(X)
    A <- area.owin(as.owin(X))
    if(any(colnames(K) == "rip"))
      L[r == 0, "rip"] <- (2 * A/(n-1)^2)/(4 * pi)
    if(any(colnames(K) == "ls"))
      L[r == 0, "ls"]  <- (2 * A/(n * (n-1)))/(4 * pi)
  }
  # relabel the fv object
  L <- rebadge.fv(L, quote(L(r)), "L", names(K), new.labl=attr(K, "labl"))
  #
  return(L)  
}

"Kest"<-
function(X, ..., r=NULL, breaks=NULL, 
         correction=c("border", "isotropic", "Ripley", "translate"),
         nlarge=3000, domain=NULL, var.approx=FALSE,
         ratio=FALSE)
{
  verifyclass(X, "ppp")
  nlarge.given <- !missing(nlarge) && !is.null(nlarge)
  rfixed <- !is.null(r) || !is.null(breaks)
  npts <- npoints(X)
  W <- X$window
  area <- area.owin(W)
  lambda <- npts/area
  lambda2 <- (npts * (npts - 1))/(area^2)

  if(!is.null(domain)) {
    # estimate based on contributions from a subdomain
    domain <- as.owin(domain)
    if(!is.subset.owin(domain, X$window))
      stop(paste(dQuote("domain"),
                 "is not a subset of the window of X"))
    # trick Kdot() into doing it
    indom <- factor(inside.owin(X$x, X$y, domain), levels=c(FALSE,TRUE))
    Kd <- Kdot(X %mark% indom, i="TRUE",
               r=r, breaks=breaks, correction=correction,
               ratio=ratio)
    # relabel and exit
    Kd <- rebadge.fv(Kd, quote(K(r)), "K")
    return(Kd)
  }

  rmaxdefault <- rmax.rule("K", W, lambda)        
  breaks <- handle.r.b.args(r, breaks, W, rmaxdefault=rmaxdefault)
  r <- breaks$r
  rmax <- breaks$max

  # choose correction(s)
  correction.given <- !missing(correction) && !is.null(correction)
  if(is.null(correction))
    correction <- c("border", "isotropic", "Ripley", "translate")
  correction <- pickoption("correction", correction,
                           c(none="none",
                             border="border",
                             "bord.modif"="bord.modif",
                             isotropic="isotropic",
                             Ripley="isotropic",
                             translate="translate",
                             best="best"),
                           multi=TRUE)
  best.wanted <- ("best" %in% correction)
  correction <- implemented.for.K(correction, W$type, correction.given)
  
  # recommended range of r values
  alim <- c(0, min(rmax, rmaxdefault))

  ###########################################
  # Efficient code for border method
  # Usable only if r values are evenly spaced from 0 to rmax
  # Invoked automatically if number of points is large

  can.do.fast <- breaks$even
  large.n    <- (npts >= nlarge)
  demand.best <- correction.given && best.wanted
  large.n.trigger <- large.n && !correction.given
  fastcorrections <- c("border", "bord.modif", "none")
  fastdefault     <- "border"
  correction.fast   <- all(correction %in% fastcorrections)
  will.do.fast <- can.do.fast && (correction.fast || large.n.trigger)
  asked <- correction.fast || (nlarge.given && large.n.trigger)
  if(asked && !can.do.fast)
    warning("r values not evenly spaced - cannot use efficient code")
  if(will.do.fast) {
    # determine correction(s)
    ok <- correction %in% fastcorrections
    correction <- if(any(ok)) correction[ok] else fastdefault
    bord <- any(correction %in% c("border", "bord.modif"))
    none <- any(correction =="none")
    if(!all(ok)) {
      # some corrections were overridden; notify user
      corx <- c(if(bord) "border correction estimate" else NULL,
                if(none) "uncorrected estimate" else NULL)
      corx <- paste(corx, collapse=" and ")
      message(paste("number of data points exceeds",
                    nlarge, "- computing", corx , "only"))
    }
    # restrict r values to recommended range, unless specifically requested
    if(!rfixed) 
      r <- seq(from=0, to=alim[2], length.out=length(r))
    if(bord)
      Kb <- Kborder.engine(X, max(r), length(r), correction, ratio=ratio)
    if(none)
      Kn <- Knone.engine(X, max(r), length(r), ratio=ratio)
    if(bord && none) 
      return(cbind.fv(Kb, Kn[, names(Kn) != "theo"]))
    if(bord) return(Kb)
    if(none) return(Kn) 
  }

  ###########################################
  # Slower code
  ###########################################
        
        
  # this will be the output data frame
  K <- data.frame(r=r, theo= pi * r^2)
  desc <- c("distance argument r", "theoretical Poisson %s")
  K <- fv(K, "r", quote(K(r)),
          "theo", , alim, c("r","%s[pois](r)"), desc, fname="K")

  # save numerator and denominator?
  if(ratio) {
    denom <- lambda2 * area
    numK <- eval.fv(denom * K)
    denK <- eval.fv(denom + K * 0)
    attributes(numK) <- attributes(denK) <- attributes(K)
    attr(numK, "desc")[2] <- "numerator for theoretical Poisson %s"
    attr(denK, "desc")[2] <- "denominator for theoretical Poisson %s"
  }
  
  # identify all close pairs
  rmax <- max(r)
  close <- closepairs(X, rmax)
  DIJ <- close$d
  XI <- ppp(close$xi, close$yi, window=W, check=FALSE)
  
  if(any(correction == "none")) {
    # uncorrected! For demonstration purposes only!
    wh <- whist(DIJ, breaks$val)  # no weights
    numKun <- cumsum(wh)
    denKun <- lambda2 * area
    # uncorrected estimate of K
    Kun <- numKun/denKun
    K <- bind.fv(K, data.frame(un=Kun), "hat(%s)[un](r)",
                 "uncorrected estimate of %s",
                 "un")
    if(ratio) {
      # save numerator and denominator
      numK <- bind.fv(numK, data.frame(un=numKun), "hat(%s)[un](r)",
                 "numerator of uncorrected estimate of %s",
                 "un")
      denK <- bind.fv(denK, data.frame(un=denKun), "hat(%s)[un](r)",
                 "denominator of uncorrected estimate of %s",
                 "un")
    }
  }
  
  if(any(correction == "border" | correction == "bord.modif")) {
  # border method
  # Compute distances to boundary
    b <- bdist.points(X)
    I <- close$i
    bI <- b[I]
  # apply reduced sample algorithm
    RS <- Kount(DIJ, bI, b, breaks)
    if(any(correction == "bord.modif")) {
      # modified border correction
      denom.area <- eroded.areas(W, r)
      numKbm <- RS$numerator
      denKbm <- lambda2 * denom.area
      Kbm <- numKbm/denKbm
      K <- bind.fv(K, data.frame(bord.modif=Kbm), "hat(%s)[bordm](r)",
                   "modified border-corrected estimate of %s",
                   "bord.modif")
      if(ratio) {
        # save numerator and denominator
        numK <- bind.fv(numK, data.frame(bord.modif=numKbm),
                        "hat(%s)[bordm](r)",
                        "numerator of modified border-corrected estimate of %s",
                        "bord.modif")
        denK <- bind.fv(denK, data.frame(bord.modif=denKbm),
                        "hat(%s)[bordm](r)",
                        "denominator of modified border-corrected estimate of %s",
                        "bord.modif")
      }
    }
    if(any(correction == "border")) {
      numKb <- RS$numerator
      denKb <- lambda * RS$denom.count
      Kb <- numKb/denKb
      K <- bind.fv(K, data.frame(border=Kb), "hat(%s)[bord](r)",
                   "border-corrected estimate of %s",
                   "border")
      if(ratio) {
        numK <- bind.fv(numK, data.frame(border=numKb), "hat(%s)[bord](r)",
                        "numerator of border-corrected estimate of %s",
                        "border")
        denK <- bind.fv(denK, data.frame(border=denKb), "hat(%s)[bord](r)",
                        "denominator of border-corrected estimate of %s",
                        "border")
      }
    }
  }

  if(any(correction == "translate")) {
    # translation correction
    XJ <- ppp(close$xj, close$yj, window=W, check=FALSE)
    edgewt <- edge.Trans(XI, XJ, paired=TRUE)
    wh <- whist(DIJ, breaks$val, edgewt)
    numKtrans <- cumsum(wh)
    denKtrans <- lambda2 * area
    Ktrans <- numKtrans/denKtrans
    h <- diameter(W)/2
    Ktrans[r >= h] <- NA
    K <- bind.fv(K, data.frame(trans=Ktrans), "hat(%s)[trans](r)",
                 "translation-corrected estimate of %s",
                 "trans")
    if(ratio) {
      numK <- bind.fv(numK, data.frame(trans=numKtrans), "hat(%s)[trans](r)",
                      "numerator of translation-corrected estimate of %s",
                      "trans")
      denK <- bind.fv(denK, data.frame(trans=denKtrans), "hat(%s)[trans](r)",
                      "denominator of translation-corrected estimate of %s",
                      "trans")
    }
  }
  if(any(correction == "isotropic")) {
    # Ripley isotropic correction
    edgewt <- edge.Ripley(XI, matrix(DIJ, ncol=1))
    wh <- whist(DIJ, breaks$val, edgewt)
    numKiso <- cumsum(wh)
    denKiso <- lambda2 * area
    Kiso <- numKiso/denKiso
    h <- diameter(W)/2
    Kiso[r >= h] <- NA
    K <- bind.fv(K, data.frame(iso=Kiso), "hat(%s)[iso](r)",
                 "Ripley isotropic correction estimate of %s",
                 "iso")
    if(ratio) {
      numK <- bind.fv(numK, data.frame(iso=numKiso), "hat(%s)[iso](r)",
                      "numerator of Ripley isotropic correction estimate of %s",
                      "iso")
      denK <- bind.fv(denK, data.frame(iso=denKiso), "hat(%s)[iso](r)",
                      "denominator of Ripley isotropic correction estimate of %s",
                      "iso")
    }
  }
  #
  if(var.approx) {
    # Compute variance approximations 
    A <- area
    P <- perimeter(W)
    n <- npts
    # Ripley asymptotic approximation
    rip <- 2 * ((A/(n-1))^2) * (pi * r^2/A + 0.96 * P * r^3/A^2
                                + 0.13 * (n/A) * P * r^5/A^2)
    K <- bind.fv(K, data.frame(rip=rip),
                 "vR(r)", 
                 "Ripley approximation to var(%s) under CSR",
                 "iso")
    if(W$type == "rectangle") {
      # Lotwick-Silverman
      a1r <- (0.21 * P * r^3 + 1.3 * r^4)/A^2
      a2r <- (0.24 * P * r^5 + 2.62 * r^6)/A^3
      # contains correction to typo on p52 of Diggle 2003
      # cf Lotwick & Silverman 1982 eq (5)
      br <- (pi * r^2/A) * (1 - pi * r^2/A) +
        (1.0716 * P * r^3 + 2.2375 * r^4)/A^2
      ls <- (A^2) * (2 * br - a1r + (n-2) * a2r)/(n*(n-1))
      # add column 
      K <- bind.fv(K, data.frame(ls=ls), "vLS(r)",
                 "Lotwick-Silverman approx to var(%s) under CSR",
                 "iso")
    }
  }
  # default plot will display all edge corrections
  attr(K, "fmla") <- . ~ r
  nama <- rev(colnames(K))
  nama <- nama[!(nama %in% c("r", "rip", "ls"))]
  fvnames(K, ".") <- nama
  #
  unitname(K) <- unitname(X)
  #
  if(ratio) {
    # finish up numerator & denominator
    attr(numK, "fmla") <- attr(denK, "fmla") <- . ~ r
    fvnames(numK, ".") <-  fvnames(denK, ".") <- nama
    unitname(numK) <- unitname(denK) <- unitname(K)
    # tack on to result
    K <- rat(K, numK, denK, check=FALSE)
  }
  return(K)
}

################################################################  
#############  SUPPORTING ALGORITHMS ###########################
################################################################  

Kount <- function(dIJ, bI, b, breaks) {
  #
  # "internal" routine to compute border-correction estimate of K or Kij
  #
  # dIJ:  vector containing pairwise distances for selected I,J pairs
  # bI:   corresponding vector of boundary distances for I
  # b:    vector of ALL distances to window boundary
  #
  # breaks : breakpts object
  #

  stopifnot(length(dIJ) == length(bI))
  
  # determine which distances d_{ij} were observed without censoring
  uncen <- (dIJ <= bI)
  # histogram of noncensored distances
  nco <- whist(dIJ[uncen], breaks$val)
  # histogram of censoring times for noncensored distances
  ncc <- whist(bI[uncen], breaks$val)
  # histogram of censoring times (yes, this is a different total size)
  cen <- whist(b, breaks$val)
  # count censoring times beyond rightmost breakpoint
  uppercen <- sum(b > max(breaks$val))
  # go
  RS <- reduced.sample(nco, cen, ncc, show=TRUE, uppercen=uppercen)
  # extract results
  numerator <- RS$numerator
  denom.count <- RS$denominator
  # check
  if(length(numerator) != breaks$ncells)
    stop("internal error: length(numerator) != breaks$ncells")
  if(length(denom.count) != breaks$ncells)
    stop("internal error: length(denom.count) != breaks$ncells")
  
  return(list(numerator=numerator, denom.count=denom.count))
}

#### interface to C code for border method

Kborder.engine <- function(X, rmax, nr=100,
                           correction=c("border", "bord.modif"),
                           weights=NULL, ratio=FALSE) 
{
  verifyclass(X, "ppp")
  npts <- npoints(X)
  W <- as.owin(X)

  area <- area.owin(W)
  lambda <- npts/area
  lambda2 <- (npts * (npts - 1))/(area^2)

  if(missing(rmax))
    rmax <- diameter(W)/4
  r <- seq(from=0, to=rmax, length.out=nr)

  # this will be the output data frame
  Kdf <- data.frame(r=r, theo= pi * r^2)
  desc <- c("distance argument r", "theoretical Poisson %s")
  Kfv <- fv(Kdf, "r", quote(K(r)),
          "theo", , c(0,rmax), c("r","%s[pois](r)"), desc, fname="K")

  if(ratio) {
    # save numerator and denominator
    denom <- lambda2 * area
    numK <- eval.fv(denom * Kfv)
    denK <- eval.fv(denom + Kfv * 0)
    attributes(numK) <- attributes(denK) <- attributes(Kfv)
    numK <- rebadge.fv(numK, tags="theo",
                       new.desc="numerator for theoretical Poisson %s")
    denK <- rebadge.fv(denK, tags="theo",
                       new.desc="denominator for theoretical Poisson %s")
  }
  
  ####### start computing ############
  # sort in ascending order of x coordinate
  orderX <- order(X$x)
  Xsort <- X[orderX]
  x <- Xsort$x
  y <- Xsort$y
  
  # boundary distances
  b <- bdist.points(Xsort)

  # call the C code
  DUP <- spatstat.options("dupC")
  
  if(is.null(weights)) {
    # determine whether the numerator can be stored as an integer
    bigint <- .Machine$integer.max
    if(npts < sqrt(bigint)) {
      # yes - use faster integer arithmetic
      res <- .C("KborderI",
                nxy=as.integer(npts),
                x=as.double(x),
                y=as.double(y),
                b=as.double(b),
                nr=as.integer(nr),
                rmax=as.double(rmax),
                numer=as.integer(integer(nr)),
                denom=as.integer(integer(nr)),
                DUP=DUP,
                PACKAGE="spatstat")
    } else {
      # no - need double precision storage
      res <- .C("KborderD",
                nxy=as.integer(npts),
                x=as.double(x),
                y=as.double(y),
                b=as.double(b),
                nr=as.integer(nr),
                rmax=as.double(rmax),
                numer=as.double(numeric(nr)),
                denom=as.double(numeric(nr)),
                DUP=DUP,
                PACKAGE="spatstat")
    }
    if("bord.modif" %in% correction) {
      denom.area <- eroded.areas(W, r)
      numKbm <- res$numer
      denKbm <- lambda2 * denom.area
      bm <- numKbm/denKbm
      Kfv <- bind.fv(Kfv, data.frame(bord.modif=bm), "hat(%s)[bordm](r)",
                   "modified border-corrected estimate of %s",
                   "bord.modif")
      if(ratio) {
        # save numerator and denominator
        numK <- bind.fv(numK, data.frame(bord.modif=numKbm),
                        "hat(%s)[bordm](r)",
                        "numerator of modified border-corrected estimate of %s",
                        "bord.modif")
        denK <- bind.fv(denK, data.frame(bord.modif=denKbm),
                        "hat(%s)[bordm](r)",
                        "denominator of modified border-corrected estimate of %s",
                        "bord.modif")
      }
    }
    if("border" %in% correction) {
      numKb <- res$numer
      denKb <- lambda * res$denom
      bord <- numKb/denKb
      Kfv <- bind.fv(Kfv, data.frame(border=bord), "hat(%s)[bord](r)",
                   "border-corrected estimate of %s",
                   "border")
      if(ratio) {
        numK <- bind.fv(numK, data.frame(border=numKb),
                        "hat(%s)[bord](r)",
                        "numerator of border-corrected estimate of %s",
                        "border")
        denK <- bind.fv(denK, data.frame(border=denKb),
                        "hat(%s)[bord](r)",
                        "denominator of border-corrected estimate of %s",
                        "border")
      }
    }
  } else {
    # weighted version
    if(is.numeric(weights)) {
      if(length(weights) != X$n)
        stop("length of weights argument does not match number of points in X")
    } else {
      wim <- as.im(weights, W)
      weights <- wim[X, drop=FALSE]
      if(any(is.na(weights)))
        stop("domain of weights image does not contain all points of X")
    }
    weights.Xsort <- weights[orderX]
    res <- .C("Kwborder",
              nxy=as.integer(npts),
              x=as.double(x),
              y=as.double(y),
              w=as.double(weights.Xsort),
              b=as.double(b),
              nr=as.integer(nr),
              rmax=as.double(rmax),
              numer=as.double(numeric(nr)),
              denom=as.double(numeric(nr)),
              DUP=DUP,
              PACKAGE="spatstat")
    if("border" %in% correction) {
      bord <- res$numer/res$denom
      Kfv <- bind.fv(Kfv, data.frame(border=bord), "hat(%s)[bord](r)",
                     "border-corrected estimate of %s",
                     "border")
      if(ratio) {
        numK <- bind.fv(numK, data.frame(border=res$numer),
                        "hat(%s)[bord](r)",
                        "numerator of border-corrected estimate of %s",
                        "border")
        denK <- bind.fv(denK, data.frame(border=res$denom),
                        "hat(%s)[bord](r)",
                        "denominator of border-corrected estimate of %s",
                        "border")
      }
    }
    if("bord.modif" %in% correction) {
      numKbm <- res$numer
      denKbm <- eroded.areas(W, r)
      bm <- numKbm/denKbm
      Kfv <- bind.fv(Kfv, data.frame(bord.modif=bm), "hat(%s)[bordm](r)",
                     "modified border-corrected estimate of %s",
                     "bord.modif")
      if(ratio) {
        # save numerator and denominator
        numK <- bind.fv(numK, data.frame(bord.modif=numKbm),
                        "hat(%s)[bordm](r)",
                        "numerator of modified border-corrected estimate of %s",
                        "bord.modif")
        denK <- bind.fv(denK, data.frame(bord.modif=denKbm),
                        "hat(%s)[bordm](r)",
                        "denominator of modified border-corrected estimate of %s",
                        "bord.modif")
      }
    }
  }
  ##
  # default is to display them all
  attr(Kfv, "fmla") <- . ~ r
  unitname(Kfv) <- unitname(X)
  if(ratio) {
    # finish off numerator and denominator
    attr(numK, "fmla") <- attr(denK, "fmla") <- . ~ r
    unitname(denK) <- unitname(numK) <- unitname(X)
    # tack on to result
    Kfv <- rat(Kfv, numK, denK, check=FALSE)
  }
  return(Kfv)
}

Knone.engine <- function(X, rmax, nr=100,
                         weights=NULL, ratio=FALSE) 
{
  verifyclass(X, "ppp")
  npts <- npoints(X)
  W <- as.owin(X)

  area <- area.owin(W)
  lambda <- npts/area
  lambda2 <- (npts * (npts - 1))/(area^2)
  denom <- lambda2 * area

  if(missing(rmax))
    rmax <- diameter(W)/4
  r <- seq(from=0, to=rmax, length.out=nr)

  # this will be the output data frame
  Kdf <- data.frame(r=r, theo= pi * r^2)
  desc <- c("distance argument r", "theoretical Poisson %s")
  Kfv <- fv(Kdf, "r", quote(K(r)),
          "theo", , c(0,rmax), c("r","%s[pois](r)"), desc, fname="K")

  if(ratio) {
    # save numerator and denominator
    numK <- eval.fv(denom * Kfv)
    denK <- eval.fv(denom + Kfv * 0)
    attributes(numK) <- attributes(denK) <- attributes(Kfv)
    numK <- rebadge.fv(numK, tags="theo",
                       new.desc="numerator for theoretical Poisson %s")
    denK <- rebadge.fv(denK, tags="theo",
                       new.desc="denominator for theoretical Poisson %s")
  }
  
  ####### start computing ############
  # sort in ascending order of x coordinate
  orderX <- order(X$x)
  Xsort <- X[orderX]
  x <- Xsort$x
  y <- Xsort$y
  
  # call the C code
  DUP <- spatstat.options("dupC")
  
  if(is.null(weights)) {
    # determine whether the numerator can be stored as an integer
    bigint <- .Machine$integer.max
    if(npts < sqrt(bigint)) {
      # yes - use faster integer arithmetic
      res <- .C("KnoneI",
                nxy=as.integer(npts),
                x=as.double(x),
                y=as.double(y),
                nr=as.integer(nr),
                rmax=as.double(rmax),
                numer=as.integer(integer(nr)),
                DUP=DUP,
                PACKAGE="spatstat")
    } else {
      # no - need double precision storage
      res <- .C("KnoneD",
                nxy=as.integer(npts),
                x=as.double(x),
                y=as.double(y),
                nr=as.integer(nr),
                rmax=as.double(rmax),
                numer=as.double(numeric(nr)),
                DUP=DUP,
                PACKAGE="spatstat")
    }

    numKun <- res$numer
    denKun <- denom # = lambda2 * area
    Kun <- numKun/denKun
  } else {
    # weighted version
    if(is.numeric(weights)) {
      if(length(weights) != X$n)
        stop("length of weights argument does not match number of points in X")
    } else {
      wim <- as.im(weights, W)
      weights <- wim[X, drop=FALSE]
      if(any(is.na(weights)))
        stop("domain of weights image does not contain all points of X")
    }
    weights.Xsort <- weights[orderX]
    res <- .C("Kwnone",
              nxy=as.integer(npts),
              x=as.double(x),
              y=as.double(y),
              w=as.double(weights.Xsort),
              nr=as.integer(nr),
              rmax=as.double(rmax),
              numer=as.double(numeric(nr)),
              DUP=DUP,
              PACKAGE="spatstat")
    numKun <- res$numer
    denKun <- sum(weights)
    Kun <- numKun/denKun
  }

  # tack on to fv object
  Kfv <- bind.fv(Kfv, data.frame(un=Kun), "hat(%s)[un](r)",
                 "uncorrected estimate of %s",
                 "un")
  if(ratio) {
    numK <- bind.fv(numK, data.frame(un=numKun),
                    "hat(%s)[un](r)",
                    "numerator of uncorrected estimate of %s",
                    "un")
    denK <- bind.fv(denK, data.frame(un=denKun),
                    "hat(%s)[un](r)",
                    "denominator of uncorrected estimate of %s",
                    "un")
  }
  ##
  # default is to display them all
  attr(Kfv, "fmla") <- . ~ r
  unitname(Kfv) <- unitname(X)
  if(ratio) {
    # finish off numerator and denominator
    attr(numK, "fmla") <- attr(denK, "fmla") <- . ~ r
    unitname(denK) <- unitname(numK) <- unitname(X)
    # tack on to result
    Kfv <- rat(Kfv, numK, denK, check=FALSE)
  }
  return(Kfv)
}

     

rmax.rule <- function(fun="K", W, lambda) {
  verifyclass(W, "owin")
  switch(fun,
         K = {
           # Ripley's Rule
           ripley <- min(diff(W$xrange), diff(W$yrange))/4
           # Count at most 1000 neighbours per point
           rlarge <- if(!missing(lambda)) sqrt(1000 /(pi * lambda)) else Inf
           rmax <- min(rlarge, ripley)
         },
         F = ,
         G = ,
         J = {
           # rule of thumb
           rdiam  <- diameter(W)/2
           # Poisson process has F(rlarge) = 1 - 10^(-5)
           rlarge <-
             if(!missing(lambda)) sqrt(log(1e5)/(pi * lambda)) else Inf
           rmax <- min(rlarge, rdiam)
         },
         stop(paste("Unrecognised function type", sQuote(fun)))
         )
  return(rmax)
}
           
    
implemented.for.K <- function(correction, windowtype, explicit) {
  pixels <- (windowtype == "mask")
  if(any(correction == "best")) {
    # select best available correction
    correction <- if(!pixels) "isotropic" else "translate"
  } else {
    # available selection of edge corrections depends on window
    if(pixels) {
      iso <- (correction == "isotropic") 
      if(any(iso)) {
        whinge <- "Isotropic correction not implemented for binary masks"
        if(explicit) {
          if(all(iso)) stop(whinge) else warning(whinge)
        }
        correction <- correction[!iso]
      }
    }
  }
  return(correction)
}
back to top