Revision 2d654eeb
Added by Jim Regetz almost 13 years ago
- ID 2d654eeb2af00c495409328ac2130ae32c580e76
terrain/research/oregon/arcgis/v2/multiscalesmooth9a_clean.R | ||
---|---|---|
1 |
# run in GRID, not ARC |
|
2 |
# &run .aml ingrid sd prob bbox |
|
3 |
# sd 0.0001 prob 0.05 |
|
4 |
# |
|
5 |
# 9a - limit to 4 steps, see if that has any significant deterioration of smoothing performance. Should fix |
|
6 |
# the problem with islands and headlands - turns out also need to remove water except |
|
7 |
# for one cell adjacent to land, and give that a higher uncertainty. See cluster_multiscalesmooth9a_clean_216 |
|
8 |
# |
|
9 |
# Version 9: |
|
10 |
# Focus on implementing identical algorithm to directsmooth2 using multiscale method i.e. aggregating by factor of 3 |
|
11 |
# from already aggregated data, rather than from original resolution each time. |
|
12 |
# |
|
13 |
# Version 8: |
|
14 |
# WARNING: have not yet checked that the additional weighting of the gaussian smoothing is not messing with |
|
15 |
# the calculations of variance etc. |
|
16 |
# Replaced simple 3x3 aggregation with gaussian smoothing |
|
17 |
# Kernel is chosen to give appropriate level of smoothing and produce a fairly accurate approximation of the smoothed |
|
18 |
# surface by interpolation of the coarser scale smoothed values |
|
19 |
# Details in gaussian.xls on john's laptop |
|
20 |
# |
|
21 |
# Version 7: |
|
22 |
# Further reworking of how the final values are selected - a mean is a candidate if its associated variance |
|
23 |
# is less than the mean sample uncertainty, and the mean with the lowest variance among the candidates is the chosen one. |
|
24 |
# Implement that in the nested sense by taking the lowest group variance divided by the chi^2 value, and its associated mean variance, |
|
25 |
# and if that is lower than the data point variance the |
|
26 |
# |
|
27 |
# approximate critical value of chi^2/N with N degrees of freedom at 5% level as 1 + 2.45/sqrt(N) + 0.55/N |
|
28 |
# for 1% level use 1 + 3.4/sqrt(N) + 2.4/N |
|
29 |
# |
|
30 |
# Version 6: |
|
31 |
# Done from scratch after careful working through of theory. |
|
32 |
# ingrid is the (potentially sparse) grid of data to be smoothed and |
|
33 |
# interpolated, which can be of different extent to the output |
|
34 |
# (resolution is assumed to be the same, could adapt this to relax that) |
|
35 |
# |
|
36 |
# var can be a constant or a grid |
|
37 |
# |
|
38 |
# bbox can be either a grid name or the 'xmin ymin xmax ymax' parameters |
|
39 |
# for setwindow |
|
40 |
|
|
41 |
library(raster) |
|
42 |
|
|
43 |
&args ingrid sd prob bbox:rest |
|
44 |
|
|
45 |
#&type NB - using standard deviation as noise specification now, not variance! |
|
46 |
|
|
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) |
|
163 |
|
|
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 |
|
|
199 |
# result is hs[0], with variance vs[0] |
|
200 |
|
|
201 |
kill bboxgrid |
Also available in: Unified diff
initial R translation of multiscale smoother