Project

General

Profile

« Previous | Next » 

Revision 2d654eeb

Added by Jim Regetz over 12 years ago

  • ID 2d654eeb2af00c495409328ac2130ae32c580e76

initial R translation of multiscale smoother

View differences:

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