Project

General

Profile

Download (9.1 KB) Statistics
| Branch: | Revision:
1
# R code to plot latitudinal profiles of (circular) mean flow direction,
2
# along with both RMSE and (circular) correlation coefficients comparing
3
# fused layers with both the raw ASTER and with the Canada DEM
4
#
5
# Jim Regetz
6
# NCEAS
7

    
8
library(raster)
9
library(circular)
10

    
11
datadir <- "/home/regetz/media/temp/terrain/flow"
12

    
13
# create function to recode terraflow SFD values into degrees, with
14
# 0=North and proceeding clockwise (this matches gdaldem's default
15
# azimuth output for aspect calculation)
16
recode <- function(r) {
17
    v <- values(r)
18
    v[v==0] <- NA
19
    v[v==1] <- 90  ## east
20
    v[v==2] <- 135
21
    v[v==4] <- 180  ## south
22
    v[v==8] <- 225
23
    v[v==16] <- 270  ## west
24
    v[v==32] <- 315
25
    v[v==64] <- 0  ## north
26
    v[v==128] <- 45
27
    r[] <- v
28
    return(r)
29
}
30

    
31
# load flow direction rasters, recoding on the fly
32
sfd.aster <- recode(raster(file.path(datadir, "aster_300straddle_sfd.tif")))
33
sfd.srtm <- recode(raster(file.path(datadir, "srtm_150below_sfd.tif")))
34
sfd.uncor <- recode(raster(file.path(datadir, "fused_300straddle_sfd.tif")))
35
sfd.enblend <- recode(raster(file.path(datadir, "fused_300straddle_enblend_sfd.tif")))
36
sfd.bg <- recode(raster(file.path(datadir, "fused_300straddle_blendgau_sfd.tif")))
37
sfd.can <- recode(raster(file.path(datadir, "cdem_300straddle_sfd.tif")))
38

    
39
# extract raster latitudes for later
40
lats300 <- yFromRow(sfd.aster, 1:nrow(sfd.aster))
41
lats150 <- yFromRow(sfd.srtm, 1:nrow(sfd.srtm))
42

    
43
# initialize output pdf device driver
44
pdf("flowdir-assessment.pdf", height=8, width=11.5)
45

    
46
#
47
# plot latitudinal profiles of mean flow direction
48
#
49

    
50
# simple helper function to calculate row-wise means using circular
51
# mean, patterned after circ.mean in the CircStats package
52
rowMeansC <- function(r1, na.rm=TRUE) {
53
    m1 <- as.matrix(r1)
54
    m1[] <- (m1 * pi)/180
55
    sinr <- rowSums(sin(m1), na.rm=na.rm)
56
    cosr <- rowSums(cos(m1), na.rm=na.rm)
57
    cmeans <- atan2(sinr, cosr)
58
    (cmeans * 180)/pi
59
}
60

    
61
par(mfrow=c(2,2), omi=c(1,1,1,1))
62
ylim <- c(-180, 180)
63

    
64
plot(lats300, rowMeansC(sfd.can), type="l", yaxt="n",
65
    xlab="Latitude", ylab="Mean flow direction", ylim=ylim)
66
axis(2, at=c(-180, -90, 0, 90, 180), labels=c("S", "W", "N", "E", "S"))
67
text(min(lats300), min(ylim)+0.5, pos=4, font=3, labels="Original DEMs")
68
lines(lats300, rowMeansC(sfd.aster), col="blue")
69
lines(lats150, rowMeansC(sfd.srtm), col="red")
70
legend("bottomright", legend=c("ASTER", "SRTM", "CDED"), col=c("blue",
71
    "red", "black"), lty=c(1, 1), bty="n")
72
abline(v=60, col="red", lty=2)
73
mtext(expression(paste("Latitudinal profiles of mean flow direction (",
74
    125*degree, "W to ", 100*degree, "W)")), adj=0, line=2, font=2)
75

    
76
#plot(lats300, rowMeans(as.matrix(sfd.uncor), na.rm=TRUE), type="l",
77
#    xlab="Latitude", ylab="Mean flow direction", ylim=ylim)
78
#text(min(lats300), min(ylim)+0.5, pos=4, font=3, labels="uncorrected")
79
#abline(v=60, col="red", lty=2)
80
#mtext(expression(paste("Latitudinal profiles of mean flow direction (",
81
#    125*degree, "W to ", 100*degree, "W)")), adj=0, line=2, font=2)
82

    
83
plot(lats300, rowMeansC(sfd.uncor), type="l", yaxt="n",
84
    xlab="Latitude", ylab="Mean flow direction", ylim=ylim)
85
axis(2, at=c(-180, -90, 0, 90, 180), labels=c("S", "W", "N", "E", "S"))
86
text(min(lats300), min(ylim)+0.5, pos=4, font=3, labels="simple fused")
87
abline(v=60, col="red", lty=2)
88

    
89
plot(lats300, rowMeansC(sfd.enblend), type="l", yaxt="n",
90
    xlab="Latitude", ylab="Mean flow direction", ylim=ylim)
91
axis(2, at=c(-180, -90, 0, 90, 180), labels=c("S", "W", "N", "E", "S"))
92
text(min(lats300), min(ylim)+0.5, pos=4, font=3, labels="multires spline")
93
abline(v=60, col="red", lty=2)
94

    
95
plot(lats300, rowMeansC(sfd.bg), type="l", yaxt="n",
96
    xlab="Latitude", ylab="Mean flow direction", ylim=ylim)
97
axis(2, at=c(-180, -90, 0, 90, 180), labels=c("S", "W", "N", "E", "S"))
98
text(min(lats300), min(ylim)+0.5, pos=4, font=3, labels="gaussian blend")
99
abline(v=60, col="red", lty=2)
100

    
101

    
102

    
103
#
104
# plot latitudinal profiles of RMSE
105
#
106

    
107
# simple helper function to calculate row-wise RMSEs, accounting for the
108
# fact that flow dir values are circular (0-360), so the difference
109
# between e.g. 5 and 355 should only be 10
110
rmse <- function(r1, r2, na.rm=TRUE, use) {
111
    diffs <- abs(as.matrix(r1) - as.matrix(r2))
112
    if (!missing(use)) diffs[!use] <- NA
113
    diffs[] <- ifelse(diffs>180, 360-diffs, diffs)
114
    sqrt(rowMeans(diffs^2, na.rm=na.rm))
115
}
116

    
117
par(mfrow=c(2,3), omi=c(1,1,1,1))
118

    
119
ylim <- c(0, 100)
120

    
121
# ...with respect to ASTER
122
plot(lats300, rmse(sfd.uncor, sfd.aster), type="l", xlab="Latitude",
123
    ylab="RMSE", ylim=ylim)
124
lines(lats150, rmse(crop(sfd.uncor, extent(sfd.srtm)), sfd.srtm), col="blue")
125
legend("topright", legend=c("ASTER", "SRTM"), col=c("black", "blue"),
126
    lty=c(1, 1), bty="n")
127
text(min(lats300), max(ylim)-5, pos=4, font=3, labels="uncorrected")
128
abline(v=60, col="red", lty=2)
129
mtext(expression(paste(
130
    "Flowdir discrepancies with respect to separate ASTER/SRTM components (",
131
    125*degree, "W to ", 100*degree, "W)")), adj=0, line=2, font=2)
132

    
133
plot(lats300, rmse(sfd.enblend, sfd.aster), type="l", xlab="Latitude",
134
    ylab="RMSE", ylim=ylim)
135
lines(lats150, rmse(crop(sfd.enblend, extent(sfd.srtm)), sfd.srtm), col="blue")
136
legend("topright", legend=c("ASTER", "SRTM"), col=c("black", "blue"),
137
    lty=c(1, 1), bty="n")
138
text(min(lats300), max(ylim)-5, pos=4, font=3, labels="exponential ramp")
139
abline(v=60, col="red", lty=2)
140

    
141
plot(lats300, rmse(sfd.bg, sfd.aster), type="l", xlab="Latitude",
142
    ylab="RMSE", ylim=ylim)
143
lines(lats150, rmse(crop(sfd.bg, extent(sfd.srtm)), sfd.srtm), col="blue")
144
legend("topright", legend=c("ASTER", "SRTM"), col=c("black", "blue"),
145
    lty=c(1, 1), bty="n")
146
text(min(lats300), max(ylim)-5, pos=4, font=3, labels="gaussian blend")
147
abline(v=60, col="red", lty=2)
148

    
149
# ...with respect to CDEM
150
plot(lats300, rmse(sfd.uncor, sfd.can), type="l", xlab="Latitude",
151
    ylab="RMSE", ylim=ylim)
152
text(min(lats300), max(ylim)-5, pos=4, font=3, labels="uncorrected")
153
abline(v=60, col="red", lty=2)
154
mtext(expression(paste(
155
    "Flowdir discrepancies with respect to Canada DEM (",
156
    125*degree, "W to ", 100*degree, "W)")), adj=0, line=2, font=2)
157

    
158
plot(lats300, rmse(sfd.enblend, sfd.can), type="l", xlab="Latitude",
159
    ylab="RMSE", ylim=ylim)
160
text(min(lats300), max(ylim)-5, pos=4, font=3, labels="exponential ramp")
161
abline(v=60, col="red", lty=2)
162

    
163
plot(lats300, rmse(sfd.bg, sfd.can), type="l", xlab="Latitude",
164
    ylab="RMSE", ylim=ylim)
165
text(min(lats300), max(ylim)-5, pos=4, font=3, labels="gaussian blend")
166
abline(v=60, col="red", lty=2)
167

    
168

    
169
#
170
# plot latitudinal profiles of correlation coefficients
171
#
172

    
173
# simple helper function to calculate row-wise *circular* correlation
174
# coefficients
175
corByLat <- function(r1, r2, rows) {
176
    if (missing(rows)) {
177
        rows <- 1:nrow(r1)
178
    }
179
    m1 <- circular(as.matrix(r1), units="degrees", rotation="clock")
180
    m2 <- circular(as.matrix(r2), units="degrees", rotation="clock")
181
    sapply(rows, function(row) {
182
        p <- cor.circular(m1[row,], m2[row,])
183
        if (is.null(p)) NA else p
184
        })
185
}
186

    
187
par(mfrow=c(2,3), omi=c(1,1,1,1))
188

    
189
ylim <- c(-1, 1)
190

    
191
# ...with respect to ASTER
192
plot(lats300, corByLat(sfd.uncor, sfd.aster), type="l", xlab="Latitude",
193
    ylab="Circular correlation", ylim=ylim)
194
lines(lats150, corByLat(crop(sfd.uncor, extent(sfd.srtm)), sfd.srtm), col="blue")
195
legend("bottomright", legend=c("ASTER", "SRTM"), col=c("black", "blue"),
196
    lty=c(1, 1), bty="n")
197
text(min(lats300), min(ylim), pos=4, font=3, labels="simple fused")
198
abline(v=60, col="red", lty=2)
199
mtext(expression(paste(
200
    "Flow direction correlations with respect to separate ASTER/SRTM components (",
201
    125*degree, "W to ", 100*degree, "W)")), adj=0, line=2, font=2)
202

    
203
plot(lats300, corByLat(sfd.enblend, sfd.aster), type="l", xlab="Latitude",
204
    ylab="Circular correlation", ylim=ylim)
205
lines(lats150, corByLat(crop(sfd.enblend, extent(sfd.srtm)), sfd.srtm), col="blue")
206
legend("bottomright", legend=c("ASTER", "SRTM"), col=c("black", "blue"),
207
    lty=c(1, 1), bty="n")
208
text(min(lats300), min(ylim), pos=4, font=3, labels="multires spline")
209
abline(v=60, col="red", lty=2)
210

    
211
plot(lats300, corByLat(sfd.bg, sfd.aster), type="l", xlab="Latitude",
212
    ylab="Circular correlation", ylim=ylim)
213
lines(lats150, corByLat(crop(sfd.bg, extent(sfd.srtm)), sfd.srtm), col="blue")
214
legend("bottomright", legend=c("ASTER", "SRTM"), col=c("black", "blue"),
215
    lty=c(1, 1), bty="n")
216
text(min(lats300), min(ylim), pos=4, font=3, labels="gaussian blend")
217
abline(v=60, col="red", lty=2)
218

    
219
# ...with respect to CDEM
220
plot(lats300, corByLat(sfd.uncor, sfd.can), type="l", xlab="Latitude",
221
    ylab="Circular correlation", ylim=ylim)
222
text(min(lats300), min(ylim), pos=4, font=3, labels="simple fused")
223
abline(v=60, col="red", lty=2)
224
mtext(expression(paste(
225
    "Flow direction correlations with respect to Canada DEM (",
226
    125*degree, "W to ", 100*degree, "W)")), adj=0, line=2, font=2)
227

    
228
plot(lats300, corByLat(sfd.enblend, sfd.can), type="l", xlab="Latitude",
229
    ylab="Circular correlation", ylim=ylim)
230
text(min(lats300), min(ylim), pos=4, font=3, labels="multires spline")
231
abline(v=60, col="red", lty=2)
232

    
233
plot(lats300, corByLat(sfd.bg, sfd.can), type="l", xlab="Latitude",
234
    ylab="Circular correlation", ylim=ylim)
235
text(min(lats300), min(ylim), pos=4, font=3, labels="gaussian blend")
236
abline(v=60, col="red", lty=2)
237

    
238
# close pdf device driver
239
dev.off()
(1-1/6)