Project

General

Profile

« Previous | Next » 

Revision 3afd1c7b

Added by Jim Regetz over 13 years ago

  • ID 3afd1c7bc5f5d40aa1acfd0d7ffbaf41bc8efca4

split the dem-fusion code snippets into separate script files

View differences:

terrain/dem/boundary-assembly.sh
1
# GDAL commands for assembling SRTM and ASTER DEM tiles associated with
2
# the 60N Canada boundary analysis, and resampling into the desired 3"
3
# (~90m) resolution even-boundary grid.
4
#
5
# These commands generate strips of elevation data (GeoTIFFs) along a
6
# 40-degree longitudinal extent matching (at least one of) Rick Reeves'
7
# mosaicked CDEM grids. The strips extend 150 pixels south of 60N and
8
# (in case of ASTER only) 150 pixels north of 60N, which should provide
9
# a sufficient but not excessive latitudinal range for fixing and
10
# assessing boundary artifacts.
11
#
12
# Note:
13
#   Working with the original ASTERs yields this warning from GDAL:
14
#     Warning 1: TIFFReadDirectoryCheckOrder:Invalid TIFF directory;
15
#     tags are not sorted in ascending order
16
#   I then ran gdal_translate on several of the offending ASTERs, then
17
#   repeated the vrt/warp on those -- now without warnings. However, the
18
#   output data was the same as when I operated on the original files
19
#   (with warnings), so for the moment I'm just going to ignore the
20
#   warnings.
21
#
22
# Jim Regetz
23
# NCEAS
24
# Created on 08-Jun-2011
25

  
26
# at the time of script creation, these paths were correct on vulcan
27
export ASTDIR="/home/reeves/active_work/EandO/asterGdem"
28
export SRTMDIR="/home/reeves/active_work/EandO/CgiarSrtm/SRTM_90m_ASCII_4_1"
29

  
30
# SRTM (also convert to 16bit integer)
31
gdalbuildvrt srtm.vrt $SRTMDIR/srtm_*_01.asc
32
gdalwarp -ot Int16 -te -136 59.875 -96 60 -ts 48000 150 -r bilinear \
33
  srtm.vrt srtm_150below.tif
34

  
35
# ASTER
36
gdalbuildvrt aster.vrt $ASTDIR/ASTGTM_N59*W*_dem.tif \
37
  $ASTDIR/ASTGTM_N60*W*_dem.tif
38
gdalwarp -te -136 59.875 -96 60 -ts 48000 150 -r bilinear \
39
  aster.vrt aster_150below.tif
40
gdalwarp -te -136 60 -96 60.125 -ts 48000 150 -r bilinear \
41
  aster.vrt aster_150above.tif
42

  
43
# note that the top 150 rows of this one are, somewhat surprisingly,
44
# slightly different from the above!
45
# gdalwarp -te -136 59.875 -96 60.125 -ts 48000 300 -r bilinear \
46
#   aster.vrt aster_300straddle.tif
47
#
48
# and this yields an even different set of values
49
# gdalbuildvrt aster_N60.vrt $ASTDIR/ASTGTM_N60*W*_dem.tif
50
# gdalwarp -te -136 60 -96 60.125 -ts 48000 150 -r bilinear \
51
#   aster_N60.vrt aster_150above.tif
52

  
terrain/dem/boundary-correction.R
1
# R script to apply several kinds of boundary corrections to ASTER/SRTM
2
# elevation values near the 60N boundary in Canada, and write out new
3
# GeoTIFFs.
4
#
5
# Jim Regetz
6
# NCEAS
7
# Created on 08-Jun-2011
8

  
9
library(raster)
10

  
11
# load relevant SRTM and ASTER data
12
srtm.south <- raster("srtm_150below.tif")
13
aster.south <- raster("aster_150below.tif")
14
aster.north <- raster("aster_150above.tif")
15

  
16
# create difference raster for area of overlap
17
delta.south <- srtm.south - aster.south
18

  
19
#
20
# OPTION 1
21
#
22

  
23
# smooth to the north, by calculating the deltas _at_ the boundary,
24
# ramping them down to zero with increasing distance from the border,
25
# and adding them to the north ASTER values
26

  
27
# create simple grid indicating distance (in units of pixels) north from
28
# boundary, starting at 1 (this is used for both option 1 and option 2)
29
aster.north.matrix <- as.matrix(aster.north)
30
ydistN <- nrow(aster.north.matrix) + 1 - row(aster.north.matrix)
31

  
32
# 1b. linear ramp north from SRTM edge
33
# -- Rick is doing this --
34

  
35
# 2b. exponential ramp north from SRTM edge
36
# -- Rick is also doing this, but here it is... --
37
r <- -0.045
38
w <- exp(ydistN*r)
39
aster.north.smooth <- aster.north
40
aster.north.smooth[] <- values(aster.north) + as.integer(round(t(w) *
41
    as.matrix(delta.south)[1,]))
42
writeRaster(aster.north.smooth, file="aster_150above_rampexp.tif")
43

  
44
#
45
# OPTION 2
46
#
47

  
48
# smooth to the north, by first using LOESS with values south of 60N to
49
# model deltas as a function of observed ASTER, then applying the model
50
# to predict pixel-wise deltas north of 60N, then ramping these
51
# predicted deltas to zero with increasing distance from the border, and
52
# adding them to the associated ASTER values
53

  
54
# first fit LOESS on a random subsample of data
55
# note: doing all the data takes too long, and even doing 50k points
56
#       seems to be too much for calculating SEs during predict step
57
set.seed(99)
58
samp <- sample(ncell(aster.south), 10000)
59
sampdata <- data.frame(delta=values(delta.south)[samp],
60
    aster=values(aster.south)[samp])
61
lo.byaster <- loess(delta ~ aster, data=sampdata)
62

  
63
# now create ASTER prediction grid north of 60N
64
# TODO: deal with NAs in data (or make sure they are passed through
65
#       properly in the absence of explicit treatment)?
66
aster.north.pdelta <- aster.north
67
aster.north.pdelta[] <- predict(lo.byaster, values(aster.north))
68
# for actual north ASTER values that exceed the max value used to fit
69
# LOESS, just use the prediction associated with the maximum
70
aster.north.pdelta[aster.north<min(sampdata$aster)] <- predict(lo.byaster,
71
    data.frame(aster=min(sampdata$aster)))
72
# for actual north ASTER value less than the min value used to fit
73
# LOESS, just use the prediction associated with the minimum
74
aster.north.pdelta[aster.north>max(sampdata$aster)] <- predict(lo.byaster,
75
    data.frame(aster=max(sampdata$aster)))
76

  
77
# 2a: exponential distance-weighting of LOESS predicted deltas
78
r <- -0.045
79
w <- exp(r*ydistN)
80
aster.north.smooth <- aster.north
81
aster.north.smooth[] <- values(aster.north) + as.integer(round(t(w *
82
    as.matrix(aster.north.pdelta))))
83
writeRaster(aster.north.smooth, file="aster_150above_predexp.tif")
84

  
85
# 2b: gaussian distance-weighting of LOESS predicted deltas
86
r <- -0.001  # weight drops to 0.5 at ~26 cells, ie 2.4km at 3" res
87
w <- exp(r*ydistN^2)
88
aster.north.smooth <- aster.north
89
aster.north.smooth[] <- values(aster.north) + as.integer(round(t(w *
90
    as.matrix(aster.north.pdelta))))
91
writeRaster(aster.north.smooth, file="aster_150above_predgau.tif")
92

  
93
#
94
# OPTION 3
95
#
96

  
97
# smooth to the south, now by simply taking pixel-wise averages of the
98
# observed SRTM and ASTER using a distance-based weighting function such
99
# that the relative contribution of ASTER decays to zero over a few km
100

  
101
# create simple grid indicating distance (in units of pixels) south from
102
# boundary, starting at 1
103
aster.south.matrix <- as.matrix(aster.south)
104
ydistS <- row(aster.south.matrix)
105

  
106
# 3a: gaussian weighting function
107
r <- -0.001  # weight drops to 0.5 at ~26 cells, or 2.4km at 3" res
108
w <- exp(-0.001*ydistS^2)
109
aster.south.smooth <- aster.south
110
aster.south.smooth[] <- values(srtm.south) - as.integer(round(t(w *
111
    as.matrix(delta.south))))
112
aster.south.smooth[aster.south.smooth<0] <- 0
113
writeRaster(aster.south.smooth, file="dem_150below_blendgau.tif")
114

  
terrain/dem/boundary-fusion.sh
1
# GDAL commands to produced fused DEMs in the vicinity of the 60N Canada
2
# boundary, using several "boundary-corrected" variants as well as the
3
# original uncorrected DEMs.
4
#
5
# Jim Regetz
6
# NCEAS
7

  
8
# uncorrected fused layer
9
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
10
  srtm_150below.tif aster_150above.tif fused_300straddle.tif
11

  
12
# exponential ramp of boundary delta to the north
13
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
14
  srtm_150below.tif aster_150above_rampexp.tif fused_300straddle_rampexp.tif
15

  
16
# exponential blend of predicted deltas to the north
17
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
18
  srtm_150below.tif aster_150above_predexp.tif fused_300straddle_predexp.tif
19

  
20
# gaussian blend of predicted deltas to the north
21
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
22
  srtm_150below.tif aster_150above_predgau.tif fused_300straddle_predgau.tif
23

  
24
# gaussian blend of SRTM/ASTER to the south
25
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
26
  dem_150below_blendgau.tif aster_150above.tif fused_300straddle_blendgau.tif
terrain/dem/boundary-hillshade.sh
1
# GDAL commands to generate hillshade images using the different fused
2
# DEMs we've produced in the 60N Canada boundary region.
3
#
4
# Also included below is a bit of R code to generate a PNG of quick
5
# hillshade visuals of two 1-degree wide swaths (one in the more
6
# mountainous west, and one in the flatter east) spanning the 60N
7
# boundary in Canada, for several different fused layers.
8
#
9
# Jim Regetz
10
# NCEAS
11

  
12
export DEMDIR=~/media/temp/terrain/dem
13
export HSDIR=~/media/temp/terrain/hillshade
14

  
15
gdaldem hillshade -s 111120 $DEMDIR/fused_300straddle.tif \
16
  $HSDIR/fused_300straddle_h.tif
17
gdaldem hillshade -s 111120 $DEMDIR/fused_300straddle_rampexp.tif \
18
  $HSDIR/fused_300straddle_rampexp_h.tif
19
gdaldem hillshade -s 111120 $DEMDIR/fused_300straddle_predexp.tif \
20
  $HSDIR/fused_300straddle_predexp_h.tif
21
gdaldem hillshade -s 111120 $DEMDIR/fused_300straddle_predgau.tif \
22
  $HSDIR/fused_300straddle_predgau_h.tif
23
gdaldem hillshade -s 111120 $DEMDIR/fused_300straddle_blendgau.tif \
24
  $HSDIR/fused_300straddle_blendgau_h.tif
25
gdaldem hillshade -s 111120 $DEMDIR/fused_300straddle_enblend.tif \
26
  $HSDIR/fused_300straddle_enblend_h.tif
27

  
28
# Use R to generate a PDF with some visuals 
29

  
30
echo '
31
  library(raster)
32
  hsdir <- "/home/regetz/media/temp/terrain/hillshade"
33
  
34
  h.uncor <- raster(file.path(hsdir, "fused_300straddle_h.tif"))
35
  h.re <- raster(file.path(hsdir, "fused_300straddle_rampexp_h.tif"))
36
  h.enblend <- raster(file.path(hsdir, "fused_300straddle_enblend_h.tif"))
37
  h.bg <- raster(file.path(hsdir, "fused_300straddle_blendgau_h.tif"))
38
  
39
  window1 <- extent(-135, -134, 59.875, 60.125)
40
  window2 <- extent(-118, -117, 59.875, 60.125)
41
  
42
  png("boundary-hillshade.png", height=10, width=7.5, units="in", res=600)
43
  par(mfrow=c(4,2), mar=c(2,2,3,0))
44
  plot(crop(h.uncor, window1), legend=FALSE)
45
  mtext("Simple fuse (hillshade)", adj=0, cex=0.8)
46
  plot(crop(h.uncor, window2), legend=FALSE)
47
  plot(crop(h.re, window1), legend=FALSE)
48
  mtext("North exponential ramp (hillshade)", adj=0, cex=0.8)
49
  plot(crop(h.re, window2), legend=FALSE)
50
  plot(crop(h.enblend, window1), legend=FALSE)
51
  mtext("Multiresolution spline (hillshade)", adj=0, cex=0.8)
52
  plot(crop(h.enblend, window2), legend=FALSE)
53
  plot(crop(h.bg, window1), legend=FALSE)
54
  mtext("Gaussian weighted average (hillshade)", adj=0, cex=0.8)
55
  plot(crop(h.bg, window2), legend=FALSE)
56
  dev.off()
57
' | Rscript --vanilla -
terrain/dem/dem-fusion.txt
1
# Snippets of GDAL commands and R code for processing DEMs
2
# Jim Regetz
3
# Created on 08-Jun-2011
4
#
5
# Note: Working with the original ASTERs yields this warning from GDAL:
6
#    Warning 1: TIFFReadDirectoryCheckOrder:Invalid TIFF directory;
7
#    tags are not sorted in ascending order
8
#
9
# I first ran gdal_translate on each of the ASTERs, then repeated the
10
# vrt/warp on those (without warnings), but the output was the same as
11
# when I operated on the original files (with warnings), so for the
12
# moment I'm just going to ignore the warnings?
13

  
14
#=======================================================================
15
# bash -- resample source DEMs into desired grids near the 60N boundary
16
#=======================================================================
17

  
18
# generate strips of data along a 40-degree longitudinal extent matching
19
# (at least one of) Rick's mosaicked CDEM grids; strips extend 150
20
# pixels south of border and (in case of aster) north of border
21

  
22
# these are currently correct on vulcan
23
export ASTDIR="/home/reeves/active_work/EandO/asterGdem"
24
export SRTMDIR="/home/reeves/active_work/EandO/CgiarSrtm/SRTM_90m_ASCII_4_1"
25

  
26
# SRTM (also convert to 16bit integer)
27
gdalbuildvrt srtm.vrt $SRTMDIR/srtm_*_01.asc
28
gdalwarp -ot Int16 -te -136 59.875 -96 60 -ts 48000 150 -r bilinear \
29
  srtm.vrt srtm_150below.tif
30

  
31
# ASTER
32
gdalbuildvrt aster.vrt $ASTDIR/ASTGTM_N59*W*_dem.tif \
33
  $ASTDIR/ASTGTM_N60*W*_dem.tif
34
gdalwarp -te -136 59.875 -96 60 -ts 48000 150 -r bilinear \
35
  aster.vrt aster_150below.tif
36
gdalwarp -te -136 60 -96 60.125 -ts 48000 150 -r bilinear \
37
  aster.vrt aster_150above.tif
38

  
39
# note that the top 150 rows of this one are, somewhat surprisingly,
40
# slightly different from the above!
41
# gdalwarp -te -136 59.875 -96 60.125 -ts 48000 300 -r bilinear \
42
#   aster.vrt aster_300straddle.tif
43
#
44
# and this yields an even different set of values
45
# gdalbuildvrt aster_N60.vrt $ASTDIR/ASTGTM_N60*W*_dem.tif
46
# gdalwarp -te -136 60 -96 60.125 -ts 48000 150 -r bilinear \
47
#   aster_N60.vrt aster_150above.tif
48

  
49
#=======================================================================
50
# R -- apply several kinds of boundary fixes and write out new GeoTIFFs
51
#=======================================================================
52

  
53
library(raster)
54

  
55
# load relevant SRTM and ASTER data
56
srtm.south <- raster("srtm_150below.tif")
57
aster.south <- raster("aster_150below.tif")
58
aster.north <- raster("aster_150above.tif")
59

  
60
# create difference raster for area of overlap
61
delta.south <- srtm.south - aster.south
62

  
63
#
64
# OPTION 1
65
#
66

  
67
# smooth to the north, by calculating the deltas _at_ the boundary,
68
# ramping them down to zero with increasing distance from the border,
69
# and adding them to the north ASTER values
70

  
71
# create simple grid indicating distance (in units of pixels) north from
72
# boundary, starting at 1 (this is used for both option 1 and option 2)
73
aster.north.matrix <- as.matrix(aster.north)
74
ydistN <- nrow(aster.north.matrix) + 1 - row(aster.north.matrix)
75

  
76
# 1b. linear ramp north from SRTM edge
77
# -- Rick is doing this --
78

  
79
# 2b. exponential ramp north from SRTM edge
80
# -- Rick is also doing this, but here it is... --
81
r <- -0.045
82
w <- exp(ydistN*r)
83
aster.north.smooth <- aster.north
84
aster.north.smooth[] <- values(aster.north) + as.integer(round(t(w) *
85
    as.matrix(delta.south)[1,]))
86
writeRaster(aster.north.smooth, file="aster_150above_rampexp.tif")
87

  
88
#
89
# OPTION 2
90
#
91

  
92
# smooth to the north, by first using LOESS with values south of 60N to
93
# model deltas as a function of observed ASTER, then applying the model
94
# to predict pixel-wise deltas north of 60N, then ramping these
95
# predicted deltas to zero with increasing distance from the border, and
96
# adding them to the associated ASTER values
97

  
98
# first fit LOESS on a random subsample of data
99
# note: doing all the data takes too long, and even doing 50k points
100
#       seems to be too much for calculating SEs during predict step
101
set.seed(99)
102
samp <- sample(ncell(aster.south), 10000)
103
sampdata <- data.frame(delta=values(delta.south)[samp],
104
    aster=values(aster.south)[samp])
105
lo.byaster <- loess(delta ~ aster, data=sampdata)
106

  
107
# now create ASTER prediction grid north of 60N
108
# TODO: deal with NAs in data (or make sure they are passed through
109
#       properly in the absence of explicit treatment)?
110
aster.north.pdelta <- aster.north
111
aster.north.pdelta[] <- predict(lo.byaster, values(aster.north))
112
# for actual north ASTER values that exceed the max value used to fit
113
# LOESS, just use the prediction associated with the maximum
114
aster.north.pdelta[aster.north<min(sampdata$aster)] <- predict(lo.byaster,
115
    data.frame(aster=min(sampdata$aster)))
116
# for actual north ASTER value less than the min value used to fit
117
# LOESS, just use the prediction associated with the minimum
118
aster.north.pdelta[aster.north>max(sampdata$aster)] <- predict(lo.byaster,
119
    data.frame(aster=max(sampdata$aster)))
120

  
121
# 2a: exponential distance-weighting of LOESS predicted deltas
122
r <- -0.045
123
w <- exp(r*ydistN)
124
aster.north.smooth <- aster.north
125
aster.north.smooth[] <- values(aster.north) + as.integer(round(t(w *
126
    as.matrix(aster.north.pdelta))))
127
writeRaster(aster.north.smooth, file="aster_150above_predexp.tif")
128

  
129
# 2b: gaussian distance-weighting of LOESS predicted deltas
130
r <- -0.001  # weight drops to 0.5 at ~26 cells, ie 2.4km at 3" res
131
w <- exp(r*ydistN^2)
132
aster.north.smooth <- aster.north
133
aster.north.smooth[] <- values(aster.north) + as.integer(round(t(w *
134
    as.matrix(aster.north.pdelta))))
135
writeRaster(aster.north.smooth, file="aster_150above_predgau.tif")
136

  
137
#
138
# OPTION 3
139
#
140

  
141
# smooth to the south, now by simply taking pixel-wise averages of the
142
# observed SRTM and ASTER using a distance-based weighting function such
143
# that the relative contribution of ASTER decays to zero over a few km
144

  
145
# create simple grid indicating distance (in units of pixels) south from
146
# boundary, starting at 1
147
aster.south.matrix <- as.matrix(aster.south)
148
ydistS <- row(aster.south.matrix)
149

  
150
# 3a: gaussian weighting function
151
r <- -0.001  # weight drops to 0.5 at ~26 cells, or 2.4km at 3" res
152
w <- exp(-0.001*ydistS^2)
153
aster.south.smooth <- aster.south
154
aster.south.smooth[] <- values(srtm.south) - as.integer(round(t(w *
155
    as.matrix(delta.south))))
156
aster.south.smooth[aster.south.smooth<0] <- 0
157
writeRaster(aster.south.smooth, file="dem_150below_blendgau.tif")
158

  
159

  
160
#=======================================================================
161
# bash -- fuse DEMS, generate hillshade
162
#=======================================================================
163

  
164
#
165
# create simple fused layers
166
#
167

  
168
# uncorrected fused layer
169
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
170
  srtm_150below.tif aster_150above.tif fused_300straddle.tif
171

  
172
# exponential ramp of boundary delta to the north
173
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
174
  srtm_150below.tif aster_150above_rampexp.tif fused_300straddle_rampexp.tif
175

  
176
# exponential blend of predicted deltas to the north
177
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
178
  srtm_150below.tif aster_150above_predexp.tif fused_300straddle_predexp.tif
179

  
180
# gaussian blend of predicted deltas to the north
181
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
182
  srtm_150below.tif aster_150above_predgau.tif fused_300straddle_predgau.tif
183

  
184
# gaussian blend of SRTM/ASTER to the south
185
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
186
  dem_150below_blendgau.tif aster_150above.tif fused_300straddle_blendgau.tif
187

  
188
#
189
# hillshade the different fused DEMs created above
190
#
191

  
192
gdaldem hillshade -s 111120 fused_300straddle.tif fused_300straddle_hs.tif
193
gdaldem hillshade -s 111120 fused_300straddle_rampexp.tif fused_300straddle_rampexp_hs.tif
194
gdaldem hillshade -s 111120 fused_300straddle_predexp.tif fused_300straddle_predexp_hs.tif
195
gdaldem hillshade -s 111120 fused_300straddle_predgau.tif fused_300straddle_predgau_hs.tif
196
gdaldem hillshade -s 111120 fused_300straddle_blendgau.tif fused_300straddle_blendgau_hs.tif
197

  
198

  
199
#=======================================================================
200
# R -- generate some quick hillshade visuals of a 1-degree wide swath
201
#=======================================================================
202

  
203
library(raster)
204

  
205
uncorrected <- raster("fused_300straddle_h.tif")
206
rampexp <- raster("fused_300straddle_rampexp_h.tif")
207
blendgau <- raster("fused_300straddle_blendgau_h.tif")
208

  
209
window <- extent(-135, -134, 59.875, 60.125)
210

  
211
png("boundary-hillshade.png", height=10, width=7.5, units="in", res=600)
212
par(mfrow=c(3,1), mar=c(2,4,4,2))
213
plot(crop(uncorrected, window), main="uncorrected (hillshade)")
214
plot(crop(rampexp, window), main="north exponential ramp (hillshade)")
215
plot(crop(blendgau, window), main="south gaussian blend (hillshade)")
216
dev.off()

Also available in: Unified diff