Project

General

Profile

« Previous | Next » 

Revision 64258f2c

Added by Jim Regetz over 12 years ago

  • ID 64258f2c17af7e7d3089bf3e0f267f8b8311adce

continued R translation of multiscale smoother

View differences:

terrain/research/oregon/arcgis/v2/multiscalesmooth9a_clean.R
40 40

  
41 41
library(raster)
42 42

  
43
&args ingrid sd prob bbox:rest
44

  
45 43
#&type NB - using standard deviation as noise specification now, not variance!
46 44

  
47
function(ingrid, sd, prob, bbox) {
48
# ingrid: grid to smooth
49
# sd: stdev
50
# prob: prob
51
# bbox: optional extent object used to subset ingrid
52

  
53
# set up chisq parameters
54
chisqa <- 2.807 - 0.6422 * log10(prob) - 3.410 * prob^0.3411
55
chisqb <- -5.871 - 3.675 * log10(prob) + 4.690 * prob^0.3377
56
#&type chisq parameters %chisqa% %chisqb%
57

  
58
# snap bbox to ingrid
59
bboxgrid <- alignExtent(bbox, ingrid)
60
# then union this with the ingrid extent
61
workgrid <- unionExtent(ingrid, bbox.aligned)
62
setwindow workgrid
63

  
64
# naming:
65
#  h - the value being smoothed/interpolated
66
#  vg - total variance of group of data, or of individual measurement
67
#  v_bg - variance between groups
68
#  v_wg - variance within groups
69
#  wa - weighting for aggregation, based on total variance
70
#  vm - variance of the calculated mean
71
#  mv - mean of finer scale variances
72
#  n - effective number of measurements
73

  
74

  
75
# NB - only calculating sample variances here, not variances of estimated means.
76
# Also note that v0_bg is an uncertainty, not a sample variance
77
# and v1_bg is total variances, but both are labelled as "between-group" to simplify the smoothing
78

  
79
h[0] <- ingrid
80
v[0] <- calc(h[0], function(x) ifelse(!is.na(x), sd^2, NA))
81
vg[0] = v[0]
82
w[0] <- calc(v[0], function(x) ifelse(is.na(x), 0, 1/x))
83
wsq[0] = w[0]^2
84
n[0] <- calc(h[0], function(x) ifelse(!is.na(x), 1, 0))
85

  
86
bigvar <- cellStats(v[0], max)
87

  
88
setcell minof
89

  
90
# aggregate to broader scales
91
i <- 1
92
done <- FALSE
93

  
94
while(!done) {
95

  
96
  j <- i-1
97

  
98
  message("Aggregate from ", j, " to ", i)
99

  
100
  cell3  <- xres(h[j]) * 3
101
  nx0 <- round(xmin(h[0] / cell3 - 0.5)
102
  ny0 <- round(ymin(h[0] / cell3 - 0.5)
103
  nx1 <- round(xmax(h[0] / cell3 + 0.5)
104
  ny1 <- round(ymax(h[0] / cell3 + 0.5)
105
  x0 <- (nx0 - 0.5) * cell3
106
  y0 <- (ny0 - 0.5) * cell3
107
  x1 <- (nx1 + 0.5) * cell3
108
  y1 <- (ny1 + 0.5) * cell3
109
  setwindow x0 y0 x1 y1
110
 #todo:
111
 #  w? <- expand(w?, 1)
112

  
113
  w[i] = aggregate(w[j], 3, sum)
114
  wsq[i] = aggregate(wsq[j], 3, sum)
115
  n[i] = aggregate(n[j], 3, sum)
116
  neff = w[i] * w[i] / wsq[i]
117
  h[i] = aggregate(w[j] * h[j], 3, sum) / w[i]
118
  vbg = aggregate(w[j] * sqr(h[j] - h[i]), 3, sum) / w[i]
119
  if (i==1) {
120
      vwg = n[i] - n[i] # zero, but with window and cell size set for us
121
  } else {
122
      vwg = aggregate(w[j] * vg[j], 3, sum) / w[i]
123
  }
124
  vg[i] = vbg + vwg
125
  vm = 1 / w[i]
126
  mv = n[i] / w[i]
127

  
128
  chisq = 1 + chisqa / sqrt(neff - 1) + chisqb / (neff - 1)
129
  v[i] = con(vg[i] / chisq < mv, vm, vg[i])
130

  
131
  # remove everything except h[i] and v[i]
132
  kill w[j]
133
  kill wsq[j]
134
  kill n[j]
135
  kill vg[j]
136

  
137
  if (i==4) done <- TRUE
138

  
139
  i <- i + 1
140
}
141

  
142

  
143
maxstep <- i - 1
144
bigvar  <- bigvar * 10
145

  
146
kill w[maxstep]
147
kill wsq[maxstep]
148
kill n[maxstep]
149
kill vg[maxstep]
150

  
151
# smooth, refine and combine each layer in turn
152

  
153

  
154
copy h[maxstep] hs[maxstep]
155
copy v[maxstep] vs[maxstep]
156
kill h[maxstep]
157
kill v[maxstep]
158
setcell hs[maxstep]
159
setwindow hs[maxstep]
160

  
161

  
162
circle2 <- matrix(c(0,1,1,0, 1,1,1,1, 1,1,1,1, 0,1,1,0), nrow=4)
45
multiscalesmooth <- function(ingrid, sd=0.0001 , prob=0.05, bbox) {
46
    # ingrid: grid to smooth
47
    # sd: stdev
48
    # prob: prob
49
    # bbox: optional extent object used to subset ingrid
50

  
51
    # set up chisq parameters
52
    chisqa <- 2.807 - 0.6422 * log10(prob) - 3.410 * prob^0.3411
53
    chisqb <- -5.871 - 3.675 * log10(prob) + 4.690 * prob^0.3377
54
    message("chisq parameters: (", chisqa, ", ", chisqb, ")")
55

  
56
    # subset ingrid if desired
57
    if (!missing(bbox)) {
58
        ingrid <- crop(ingrid, bbox)
59
    }
60

  
61
    # set number of levels of aggregation
62
    NUM.LEVELS <- 4
63
    # set aggregation factor
64
    AGG.FACTOR <- 3
65

  
66
    # naming:
67
    #  h - the value being smoothed/interpolated
68
    #  vg - total variance of group of data, or of individual measurement
69
    #  v_bg - variance between groups
70
    #  v_wg - variance within groups
71
    #  wa - weighting for aggregation, based on total variance
72
    #  vm - variance of the calculated mean
73
    #  mv - mean of finer scale variances
74
    #  n - effective number of measurements
75

  
76
    # NB - only calculating sample variances here, not variances of estimated means.
77
    # Also note that v0_bg is an uncertainty, not a sample variance
78
    # and v1_bg is total variances, but both are labelled as "between-group" to simplify the smoothing
79

  
80
    # expand grid to accommodate integer number of cells at coarsest
81
    # level, by adding roungly equal number of cells on either side
82
    # (with on extra on top/right if an odd number of cells needs to be
83
    # added)
84
    max.size <- AGG.FACTOR^NUM.LEVELS
85
    addx <- if (0 < (extra<-ncol(ingrid)%%max.size)) {
86
            (max.size-extra)/2
87
        } else {
88
            0
89
        }
90
    addy <- if (0 < (extra<-nrow(ingrid)%%max.size)) {
91
            (max.size-extra)/2
92
        } else {
93
            0
94
        }
95
    h <- list(expand(ingrid, extent(
96
        xmin(ingrid)-floor(addx)*xres(ingrid),
97
        xmax(ingrid)+ceiling(addx)*xres(ingrid),
98
        ymin(ingrid)-floor(addy)*yres(ingrid),
99
        ymax(ingrid)+ceiling(addy)*yres(ingrid)
100
        )))
101
    v <- list(calc(h[[1]], function(x) ifelse(!is.na(x), sd^2, NA)))
102

  
103
    vg = v[[1]]
104
    w <- calc(v[[1]], function(x) ifelse(is.na(x), 0, 1/x))
105
    wsq = w^2
106
    n <- calc(h[[1]], function(x) ifelse(!is.na(x), 1, 0))
107

  
108
    bigvar <- cellStats(v[[1]], max)
109

  
110
    #setcell minof
111

  
112
    # aggregate to broader scales
113
    for (i in 1+seq.int(NUM.LEVELS)) {
114

  
115
        message("Aggregate from ", i-1, " to ", i)
116

  
117
        vg.prev <- vg
118
        w.prev <- w
119
        wsq.prev <- wsq
120
        n.prev <- n
121

  
122
        w <- aggregate(w.prev, 3, sum)
123
        wsq <- aggregate(wsq.prev, 3, sum)
124
        n <- aggregate(n.prev, 3, sum)
125
        neff <- w^2 / wsq
126
        h[[i]] <- aggregate(w.prev * h[[i-1]], 3, sum) / w
127
        hdiff <- h[[i-1]] - disaggregate(h[[i]], 3)
128
        vbg <- aggregate(w.prev * hdiff^2, 3, sum) / w
129
        if (i==1) {
130
            vwg <- n - n # zero, but with window and cell size set for us
131
        } else {
132
            vwg <- aggregate(w.prev * vg.prev, 3, sum) / w
133
        }
134
        vg <- vbg + vwg
135
        vm <- 1 / w
136
        mv <- n / w
137

  
138
        chisq <- 1 + chisqa / sqrt(neff - 1) + chisqb / (neff - 1)
139
        v[[i]] <- overlay(vg, chisq, mv, vm,
140
            fun=function(vg, chisq, mv, vm) ifelse(vg/chisq < mv, vm, vg))
141

  
142
    }
143

  
144
    bigvar  <- bigvar * 10
145

  
146
    #copy h[NUM.LEVELS] hs[NUM.LEVELS]
147
    #copy v[NUM.LEVELS] vs[NUM.LEVELS]
148
    #kill h[NUM.LEVELS]
149
    #kill v[NUM.LEVELS]
150
    #setcell hs[NUM.LEVELS]
151
    #setwindow hs[NUM.LEVELS]
152

  
153
    # smooth, refine and combine each layer in turn
154
    #hs <- h[[NUM.LEVELS+1]]
155
    #vs <- v[[NUM.LEVELS+1]]
156
    hs <- h
157
    vs <- v
158
    #todo: is this the same as circle with radius 2 in arc???
159
    #circle2 <- matrix(c(0,1,0, 1,1,1, 0,1,0), nrow=3)
160
    circle2 <- matrix(c(0,0,1,0,0, 0,1,1,1,0, 1,1,1,1,1, 0,1,1,1,0, 0,0,1,0,0), nrow=5)
161
    circle2[circle2==0] <- NA
162

  
163
    for (j in 1+rev(seq.int(NUM.LEVELS))) {
164

  
165
        message("Refine from ", j, " to ", j-1)
166

  
167
        # for the first stage where the coarser grid is refined and smoothed, set window to the coarse grid
168
        #setcell h[j-1]
169
        #setwindow maxof
170

  
171
        # create smoothed higher resolution versions of h and v_bg, hopefully with no nulls!
172
        # [suppressing warnings to avoid .couldBeLonLat complaints]
173
        suppressWarnings({
174
            hs.tmp <- disaggregate(focal(hs[[j]], w=circle2, fun=mean,
175
                pad=TRUE, padValue=NA, na.rm=TRUE), 3)
176
            vs.tmp <- disaggregate(focal(vs[[j]], w=circle2, fun=mean,
177
               pad=TRUE, padValue=NA, na.rm=TRUE), 3)
178
        })
179

  
180
        # create no-null version of finer h and v
181
        h_c <- calc(h[[j-1]], function(x) ifelse(is.na(x), 0, x))
182
        v_c <- calc(v[[j-1]], function(x) ifelse(is.na(x), bigvar, x))
183

  
184
        # combine two values using least variance
185
        hs[[j-1]] <- (h_c/v_c + hs.tmp/vs.tmp ) / (1/v_c + 1/vs.tmp)
186
        vs[[j-1]] <- 1 / (1/v_c + 1/vs.tmp)
187

  
188
#todo: mimic all the AML setwindow/setcell stuff???
189
#        hs[[j-1]] <- expand(hs[[j-1]], 4)
190
#        vs[[j-1]] <- expand(vs[[j-1]], 4)
191

  
192
    }
193

  
194
    result <- crop(stack(hs[[1]], vs[[1]]), extent(ingrid))
195
    layerNames(result) <- c("hs", "vs")
196
    return(result)
163 197

  
164
for (j in maxstep:1) {
165
  i <- j-1
166

  
167
  message("Refine from ", j, " to ", i)
168

  
169
  # for the first stage where the coarser grid is refined and smoothed, set window to the coarse grid
170
  setcell h[i]
171
  setwindow maxof
172

  
173
  # create smoothed higher resolution versions of h and v_bg, hopefully with no nulls!
174
  hs[j][i] = focal(hs[j], w=circle2, mean)
175
  vs[j][i] = focal(vs[j], w=circle2, mean)
176

  
177
  setcell h[i]
178
  cellsize <- xres(h[i])
179
  setwindow [xmin(bboxgrid) - 4 * cellsize] [ymin(bboxgrid) - 4 * cellsize] [xmax(bboxgrid) + 4 * cellsize] [ymax(bboxgrid) + 4 * cellsize] h[i]
180

  
181
  # create no-null version of finer h and v
182
  h_c = con(isnull(h[i]), 0, h[i])
183
  v_c = con(isnull(v[i]), bigvar, v[i])
184

  
185
  # combine two values using least variance
186
  hs[i] = (h_c / v_c + hs[j][i] / vs[j][i] ) / (1.0 / v_c + 1.0 / vs[j][i])
187
  vs[i] = 1 / (1.0 / v_c + 1.0 / vs[j][i])
188

  
189
  kill v_c
190
  kill h_c
191
  kill v[i]
192
  kill h[i]
193
  kill vs[j][i]
194
  kill hs[j][i]
195
  kill hs[j]
196
  kill vs[j]
197 198
}
198

  
199
# result is hs[0], with variance vs[0]
200

  
201
kill bboxgrid

Also available in: Unified diff