Revision 64258f2c
Added by Jim Regetz almost 13 years ago
- ID 64258f2c17af7e7d3089bf3e0f267f8b8311adce
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
continued R translation of multiscale smoother