File: multihard.R

package info (click to toggle)
r-cran-spatstat.core 2.4-4-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 6,440 kB
  • sloc: ansic: 4,402; sh: 13; makefile: 5
file content (196 lines) | stat: -rw-r--r-- 6,589 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
#
#
#    multihard.R
#
#    $Revision: 1.20 $	$Date: 2021/11/08 07:07:48 $
#
#    The Hard core process
#
#    Hardcore()     create an instance of the Hard Core process
#                      [an object of class 'interact']
#	
#
# -------------------------------------------------------------------
#	

MultiHard <- local({

  # .... multitype hard core potential
  
  MHpotential <- function(d, tx, tu, par) {
     # arguments:
     # d[i,j] distance between points X[i] and U[j]
     # tx[i]  type (mark) of point X[i]
     # tu[i]  type (mark) of point U[j]
     #
     # get matrices of interaction radii
     h <- par$hradii

     # get possible marks and validate
     if(!is.factor(tx) || !is.factor(tu))
	stop("marks of data and dummy points must be factor variables")
     lx <- levels(tx)
     lu <- levels(tu)
     if(length(lx) != length(lu) || any(lx != lu))
	stop("marks of data and dummy points do not have same possible levels")

     if(!identical(lx, par$types))
        stop("data and model do not have the same possible levels of marks")
     if(!identical(lu, par$types))
        stop("dummy points and model do not have the same possible levels of marks")

     # ensure factor levels are acceptable for column names (etc)
     lxname <- make.names(lx, unique=TRUE)
     
     # list all UNORDERED pairs of types to be checked
     # (the interaction must be symmetric in type, and scored as such)
     uptri <- (row(h) <= col(h)) & (!is.na(h))
     mark1 <- (lx[row(h)])[uptri]
     mark2 <- (lx[col(h)])[uptri]
     # corresponding names
     mark1name <- (lxname[row(h)])[uptri]
     mark2name <- (lxname[col(h)])[uptri]
     vname <- apply(cbind(mark1name,mark2name), 1, paste, collapse="x")
     vname <- paste("mark", vname, sep="")
     npairs <- length(vname)
     # list all ORDERED pairs of types to be checked
     # (to save writing the same code twice)
     different <- mark1 != mark2
     mark1o <- c(mark1, mark2[different])
     mark2o <- c(mark2, mark1[different])
     nordpairs <- length(mark1o)
     # unordered pair corresponding to each ordered pair
     ucode <- c(1:npairs, (1:npairs)[different])
     #
     # create numeric array for result
     z <- array(0, dim=c(dim(d), npairs),
                dimnames=list(character(0), character(0), vname))
     # go....
     if(length(z) > 0) {
       # apply the relevant hard core distance to each pair of points
       hxu <- h[ tx, tu ]
       forbid <- (d < hxu)
       forbid[is.na(forbid)] <- FALSE
       # form the potential 
       value <- array(0, dim=dim(d))
       value[forbid] <- -Inf
       # assign value[i,j] -> z[i,j,k] where k is relevant interaction code
       for(i in 1:nordpairs) {
         # data points with mark m1
         Xsub <- (tx == mark1o[i])
         # quadrature points with mark m2
         Qsub <- (tu == mark2o[i])
         # assign
         z[Xsub, Qsub, ucode[i]] <- value[Xsub, Qsub]
       }
     }
     attr(z, "IsOffset") <- rep.int(TRUE, npairs)
     return(z)
   }
   #### end of 'pot' function ####

  # ............ template object ...................
  
  BlankMH <- 
  list(
       name     = "Multitype Hardcore process",
       creator  = "MultiHard",
       family   = "pairwise.family",  # evaluated later
       pot      = MHpotential,
       par      = list(types=NULL, hradii = NULL), # filled in later
       parnames = c("possible types", "hardcore distances"),
       pardesc  = c("vector of possible types",
                    "matrix of hardcore distances"),
       hasInf   = TRUE,
       selfstart = function(X, self) {
         types <- self$par$types
         hradii <- self$par$hradii
         if(!is.null(types) && !is.null(hradii)) return(self)
         if(is.null(types)) types <- levels(marks(X))
         if(is.null(hradii)) {
           marx <- marks(X)
           d <- nndist(X, by=marx)
           h <- aggregate(d, by=list(from=marx), min)
           h <- as.matrix(h[, -1, drop=FALSE])
           m <- table(marx)
           mm <- outer(m, m, pmin)
           hradii <- h * mm/(mm+1)
           dimnames(hradii) <- list(types, types)
         }
         MultiHard(types=types,hradii=hradii)
       },
       init     = function(self) {
         types <- self$par$types
         if(!is.null(types)) {
           h <- self$par$hradii
           nt <- length(types)
           if(!is.null(h)) MultiPair.checkmatrix(h, nt, sQuote("hradii"))
           if(length(types) == 0)
             stop(paste("The", sQuote("types"),
                        "argument should be",
                        "either NULL or a vector of all possible types"))
           if(anyNA(types))
             stop("NA's not allowed in types")
           if(is.factor(types)) {
             types <- levels(types)
           } else {
             types <- levels(factor(types, levels=types))
           }
         }
       },
       update = NULL,  # default OK
       print = function(self) {
         h <- self$par$hradii
         if(waxlyrical('gory')) {
           if(!is.null(h)) splat(nrow(h), "types of points")
           types <- self$par$types
           if(!is.null(types)) {
             splat("Possible types:")
             print(noquote(types))
           } else splat("Possible types:\t not yet determined")
         }
         if(!is.null(h)) {
           splat("Hardcore radii:")
           print(signif(h, getOption("digits")))
         } else splat("Hardcore radii:\t not yet determined") 
         invisible()
       },
       interpret = function(coeffs, self) {
        # there are no regular parameters (woo-hoo!)
         return(NULL)
       },
       valid = function(coeffs, self) {
         return(TRUE)
       },
       project = function(coeffs, self) {
         return(NULL)
       },
       irange = function(self, coeffs=NA, epsilon=0, ...) {
         h <- self$par$hradii
         return(max(0, h, na.rm=TRUE))
       },
       hardcore = function(self, coeffs=NA, epsilon=0, ...) {
         h <- self$par$hradii
         return(h)
       },
       version=NULL # fix later
  )
  class(BlankMH) <- "interact"

  MultiHard <- function(hradii=NULL, types=NULL) {
    if((missing(hradii) || !is.matrix(hradii)) && is.matrix(types)) {
      ## old syntax: (types=NULL, hradii)
      hradii <- types
      types <- NULL
    }
    if(!is.null(hradii)) hradii[hradii == 0] <- NA
    out <- instantiate.interact(BlankMH, list(types=types, hradii = hradii))
    if(!is.null(types))
      dimnames(out$par$hradii) <- list(types, types)
    return(out)
  }

  MultiHard <- intermaker(MultiHard, BlankMH)
  
  MultiHard
})