@@ -24,31 +24,34 @@ source("setup.R")
24
24
::::::::::::::::::::::::::::::::::::::::::::::::::
25
25
26
26
``` {r load-libraries, echo=FALSE, results="hide", message=FALSE, warning=FALSE}
27
- library(raster)
28
- library(rgdal)
27
+ library(terra)
29
28
library(ggplot2)
30
29
library(dplyr)
31
30
```
32
31
33
32
``` {r load-data, echo=FALSE}
34
33
# Learners will have these data loaded from earlier episode
35
34
# DSM data for Harvard Forest
36
- DSM_HARV <- raster("data/NEON-DS-Airborne-Remote-Sensing/HARV/DSM/HARV_dsmCrop.tif")
35
+ DSM_HARV <-
36
+ rast("data/NEON-DS-Airborne-Remote-Sensing/HARV/DSM/HARV_dsmCrop.tif")
37
37
38
38
DSM_HARV_df <- as.data.frame(DSM_HARV, xy = TRUE)
39
39
40
40
# DTM data for Harvard Forest
41
- DTM_HARV <- raster("data/NEON-DS-Airborne-Remote-Sensing/HARV/DTM/HARV_dtmCrop.tif")
41
+ DTM_HARV <-
42
+ rast("data/NEON-DS-Airborne-Remote-Sensing/HARV/DTM/HARV_dtmCrop.tif")
42
43
43
44
DTM_HARV_df <- as.data.frame(DTM_HARV, xy = TRUE)
44
45
45
46
# DSM data for SJER
46
- DSM_SJER <- raster("data/NEON-DS-Airborne-Remote-Sensing/SJER/DSM/SJER_dsmCrop.tif")
47
+ DSM_SJER <-
48
+ rast("data/NEON-DS-Airborne-Remote-Sensing/SJER/DSM/SJER_dsmCrop.tif")
47
49
48
50
DSM_SJER_df <- as.data.frame(DSM_SJER, xy = TRUE)
49
51
50
52
# DTM data for SJER
51
- DTM_SJER <- raster("data/NEON-DS-Airborne-Remote-Sensing/SJER/DTM/SJER_dtmCrop.tif")
53
+ DTM_SJER <-
54
+ rast("data/NEON-DS-Airborne-Remote-Sensing/SJER/DTM/SJER_dtmCrop.tif")
52
55
53
56
DTM_SJER_df <- as.data.frame(DTM_SJER, xy = TRUE)
54
57
```
@@ -58,26 +61,27 @@ DTM_SJER_df <- as.data.frame(DTM_SJER, xy = TRUE)
58
61
## Things You'll Need To Complete This Episode
59
62
60
63
See the [ lesson homepage] ( . ) for detailed information about the software,
61
- data, and other prerequisites you will need to work through the examples in this episode.
64
+ data, and other prerequisites you will need to work through the examples in
65
+ this episode.
62
66
63
67
64
68
::::::::::::::::::::::::::::::::::::::::::::::::::
65
69
66
- We often want to combine values of and perform calculations on rasters to create
67
- a new output raster. This episode covers how to subtract one raster from
68
- another using basic raster math and the ` overlay ()` function. It also covers how
69
- to extract pixel values from a set of locations - for example a buffer region
70
- around plot locations at a field site.
70
+ We often want to combine values of and perform calculations on rasters to
71
+ create a new output raster. This episode covers how to subtract one raster from
72
+ another using basic raster math and the ` lapp ()` function. It also covers
73
+ how to extract pixel values from a set of locations - for example a buffer
74
+ region around plot locations at a field site.
71
75
72
76
## Raster Calculations in R
73
77
74
78
We often want to perform calculations on two or more rasters to create a new
75
- output raster. For example, if we are interested in mapping the heights of trees
76
- across an entire field site, we might want to calculate the difference between
77
- the Digital Surface Model (DSM, tops of trees) and the
78
- Digital Terrain Model (DTM, ground level). The resulting dataset is referred to
79
- as a Canopy Height Model (CHM) and represents the actual height of trees,
80
- buildings, etc. with the influence of ground elevation removed.
79
+ output raster. For example, if we are interested in mapping the heights of
80
+ trees across an entire field site, we might want to calculate the difference
81
+ between the Digital Surface Model (DSM, tops of trees) and the Digital Terrain
82
+ Model (DTM, ground level). The resulting dataset is referred to as a Canopy
83
+ Height Model (CHM) and represents the actual height of trees, buildings, etc.
84
+ with the influence of ground elevation removed.
81
85
82
86
![ ] ( fig/dc-spatial-raster/lidarTree-height.png ) {alt='Source: National Ecological Observatory Network (NEON)'}
83
87
@@ -93,26 +97,25 @@ buildings, etc. with the influence of ground elevation removed.
93
97
94
98
### Load the Data
95
99
96
- For this episode, we will use the DTM and DSM from the
97
- NEON Harvard Forest Field site and San Joaquin Experimental
98
- Range,
99
- which we already have loaded from previous episodes.
100
+ For this episode, we will use the DTM and DSM from the NEON Harvard Forest
101
+ Field site and San Joaquin Experimental Range, which we already have loaded
102
+ from previous episodes.
100
103
101
104
::::::::::::::::::::::::::::::::::::::: challenge
102
105
103
106
## Exercise
104
107
105
- Use the ` GDALinfo ()` function to view information about the DTM and
106
- DSM data files. Do the two rasters have the same or different CRSs
107
- and resolutions? Do they both have defined minimum and maximum values?
108
+ Use the ` describe ()` function to view information about the DTM and DSM data
109
+ files. Do the two rasters have the same or different CRSs and resolutions? Do
110
+ they both have defined minimum and maximum values?
108
111
109
112
::::::::::::::: solution
110
113
111
114
## Solution
112
115
113
116
``` {r}
114
- GDALinfo ("data/NEON-DS-Airborne-Remote-Sensing/HARV/DTM/HARV_dtmCrop.tif")
115
- GDALinfo ("data/NEON-DS-Airborne-Remote-Sensing/HARV/DSM/HARV_dsmCrop.tif")
117
+ describe ("data/NEON-DS-Airborne-Remote-Sensing/HARV/DTM/HARV_dtmCrop.tif")
118
+ describe ("data/NEON-DS-Airborne-Remote-Sensing/HARV/DSM/HARV_dsmCrop.tif")
116
119
```
117
120
118
121
:::::::::::::::::::::::::
@@ -150,7 +153,7 @@ We can calculate the difference between two rasters in two different ways:
150
153
or for more efficient processing - particularly if our rasters are large and/or
151
154
the calculations we are performing are complex:
152
155
153
- - using the ` overlay ()` function.
156
+ - using the ` lapp ()` function.
154
157
155
158
## Raster Math \& Canopy Height Models
156
159
@@ -172,7 +175,7 @@ We can now plot the output CHM.
172
175
``` {r harv-chm-plot}
173
176
ggplot() +
174
177
geom_raster(data = CHM_HARV_df ,
175
- aes(x = x, y = y, fill = layer )) +
178
+ aes(x = x, y = y, fill = HARV_dsmCrop )) +
176
179
scale_fill_gradientn(name = "Canopy Height", colors = terrain.colors(10)) +
177
180
coord_quickmap()
178
181
```
@@ -182,17 +185,18 @@ Canopy Height Model (CHM).
182
185
183
186
``` {r create-hist}
184
187
ggplot(CHM_HARV_df) +
185
- geom_histogram(aes(layer ))
188
+ geom_histogram(aes(HARV_dsmCrop ))
186
189
```
187
190
188
- Notice that the range of values for the output CHM is between 0 and 30
189
- meters. Does this make sense for trees in Harvard Forest?
191
+ Notice that the range of values for the output CHM is between 0 and 30 meters.
192
+ Does this make sense for trees in Harvard Forest?
190
193
191
194
::::::::::::::::::::::::::::::::::::::: challenge
192
195
193
196
## Challenge: Explore CHM Raster Values
194
197
195
- It's often a good idea to explore the range of values in a raster dataset just like we might explore a dataset that we collected in the field.
198
+ It's often a good idea to explore the range of values in a raster dataset just
199
+ like we might explore a dataset that we collected in the field.
196
200
197
201
1 . What is the min and maximum value for the Harvard Forest Canopy Height Model (` CHM_HARV ` ) that we just created?
198
202
2 . What are two ways you can check this range of data for ` CHM_HARV ` ?
@@ -208,34 +212,35 @@ It's often a good idea to explore the range of values in a raster dataset just l
208
212
` na.rm = TRUE ` .
209
213
210
214
``` {r}
211
- min(CHM_HARV_df$layer , na.rm = TRUE)
212
- max(CHM_HARV_df$layer , na.rm = TRUE)
215
+ min(CHM_HARV_df$HARV_dsmCrop , na.rm = TRUE)
216
+ max(CHM_HARV_df$HARV_dsmCrop , na.rm = TRUE)
213
217
```
214
218
215
219
2 ) Possible ways include:
216
220
217
221
- Create a histogram
218
- - Use the ` min() ` and ` max ()` functions.
222
+ - Use the ` min() ` , ` max() ` , and ` range ()` functions.
219
223
- Print the object and look at the ` values ` attribute.
220
224
221
225
3 )
222
226
``` {r chm-harv-hist}
223
227
ggplot(CHM_HARV_df) +
224
- geom_histogram(aes(layer ))
228
+ geom_histogram(aes(HARV_dsmCrop ))
225
229
```
226
230
227
231
4 )
228
232
``` {r chm-harv-hist-green}
229
233
ggplot(CHM_HARV_df) +
230
- geom_histogram(aes(layer ), colour="black",
234
+ geom_histogram(aes(HARV_dsmCrop ), colour="black",
231
235
fill="darkgreen", bins = 6)
232
236
```
233
237
234
238
5 )
235
239
``` {r chm-harv-raster}
236
240
custom_bins <- c(0, 10, 20, 30, 40)
237
241
CHM_HARV_df <- CHM_HARV_df %>%
238
- mutate(canopy_discrete = cut(layer, breaks = custom_bins))
242
+ mutate(canopy_discrete = cut(HARV_dsmCrop,
243
+ breaks = custom_bins))
239
244
240
245
ggplot() +
241
246
geom_raster(data = CHM_HARV_df , aes(x = x, y = y,
@@ -248,7 +253,7 @@ ggplot() +
248
253
249
254
::::::::::::::::::::::::::::::::::::::::::::::::::
250
255
251
- ## Efficient Raster Calculations: Overlay Function
256
+ ## Efficient Raster Calculations
252
257
253
258
Raster math, like we just did, is an appropriate approach to raster calculations
254
259
if:
@@ -258,48 +263,43 @@ if:
258
263
259
264
However, raster math is a less efficient approach as computation becomes more
260
265
complex or as file sizes become large.
261
- The ` overlay() ` function is more efficient when:
262
266
263
- 1 . The rasters we are using are larger in size.
264
- 2 . The rasters are stored as individual files.
265
- 3 . The computations performed are complex.
266
-
267
- The ` overlay() ` function takes two or more rasters and applies a function to
267
+ The ` lapp() ` function takes two or more rasters and applies a function to
268
268
them using efficient processing methods. The syntax is
269
269
270
- ` outputRaster <- overlay(raster1, raster2, fun=functionName) `
270
+ ` outputRaster <- lapp(x, fun=functionName) `
271
+
272
+ In which raster can be either a SpatRaster or a SpatRasterDataset which is an
273
+ object that holds rasters. See ` help(sds) ` .
271
274
272
275
::::::::::::::::::::::::::::::::::::::::: callout
273
276
274
277
## Data Tip
275
278
276
- If the rasters are stacked and stored
277
- as ` RasterStack ` or ` RasterBrick ` objects in R, then we should use ` calc() ` .
278
- ` overlay() ` will not work on stacked rasters.
279
-
279
+ To create a SpatRasterDataset, we call the function ` sds ` which can take a list
280
+ of raster objects (each one created by calling ` rast ` ).
280
281
281
282
::::::::::::::::::::::::::::::::::::::::::::::::::
282
283
283
284
Let's perform the same subtraction calculation that we calculated above using
284
- raster math, using the ` overlay ()` function.
285
+ raster math, using the ` lapp ()` function.
285
286
286
287
::::::::::::::::::::::::::::::::::::::::: callout
287
288
288
289
## Data Tip
289
290
290
- A custom function consists of a defined
291
- set of commands performed on a input object. Custom functions are particularly
292
- useful for tasks that need to be repeated over and over in the code. A
293
- simplified syntax for writing a custom function in R is:
291
+ A custom function consists of a defined set of commands performed on a input
292
+ object. Custom functions are particularly useful for tasks that need to be
293
+ repeated over and over in the code. A simplified syntax for writing a custom
294
+ function in R is:
294
295
` function_name <- function(variable1, variable2) { WhatYouWantDone, WhatToReturn} `
295
296
296
297
297
298
::::::::::::::::::::::::::::::::::::::::::::::::::
298
299
299
300
``` {r raster-overlay}
300
- CHM_ov_HARV <- overlay(DSM_HARV,
301
- DTM_HARV,
302
- fun = function(r1, r2) { return( r1 - r2) })
301
+ CHM_ov_HARV <- lapp(sds(list(DSM_HARV, DTM_HARV)),
302
+ fun = function(r1, r2) { return( r1 - r2) })
303
303
```
304
304
305
305
Next we need to convert our new object to a data frame for plotting with
@@ -314,12 +314,12 @@ Now we can plot the CHM:
314
314
``` {r harv-chm-overlay}
315
315
ggplot() +
316
316
geom_raster(data = CHM_ov_HARV_df,
317
- aes(x = x, y = y, fill = layer )) +
317
+ aes(x = x, y = y, fill = HARV_dsmCrop )) +
318
318
scale_fill_gradientn(name = "Canopy Height", colors = terrain.colors(10)) +
319
319
coord_quickmap()
320
320
```
321
321
322
- How do the plots of the CHM created with manual raster math and the ` overlay ()`
322
+ How do the plots of the CHM created with manual raster math and the ` lapp ()`
323
323
function compare?
324
324
325
325
## Export a GeoTIFF
@@ -334,12 +334,13 @@ contains (CHM data) and for where (HARVard Forest). The `writeRaster()` function
334
334
by default writes the output file to your working directory unless you specify a
335
335
full file path.
336
336
337
- We will specify the output format ("GTiff"), the no data value (` NAflag = -9999 ` . We will also tell R to overwrite any data that is already in
338
- a file of the same name.
337
+ We will specify the output format ("GTiff"), the no data value ` NAflag = -9999 ` .
338
+ We will also tell R to overwrite any data that is already in a file of the same
339
+ name.
339
340
340
341
``` {r write-raster, eval=FALSE}
341
342
writeRaster(CHM_ov_HARV, "CHM_HARV.tiff",
342
- format ="GTiff",
343
+ filetype ="GTiff",
343
344
overwrite=TRUE,
344
345
NAflag=-9999)
345
346
```
@@ -348,7 +349,7 @@ writeRaster(CHM_ov_HARV, "CHM_HARV.tiff",
348
349
349
350
The function arguments that we used above include:
350
351
351
- - ** format :** specify that the format will be ` GTiff ` or GeoTIFF.
352
+ - ** filetype :** specify that the format will be ` GTiff ` or GeoTIFF.
352
353
- ** overwrite:** If TRUE, R will overwrite any existing file with the same
353
354
name in the specified directory. USE THIS SETTING WITH CAUTION!
354
355
- ** NAflag:** set the GeoTIFF tag for ` NoDataValue ` to -9999, the National
@@ -358,9 +359,9 @@ The function arguments that we used above include:
358
359
359
360
## Challenge: Explore the NEON San Joaquin Experimental Range Field Site
360
361
361
- Data are often more interesting and powerful when we compare them across various
362
- locations. Let's compare some data collected over Harvard Forest to data
363
- collected in Southern California. The
362
+ Data are often more interesting and powerful when we compare them across
363
+ various locations. Let's compare some data collected over Harvard Forest to
364
+ data collected in Southern California. The
364
365
[ NEON San Joaquin Experimental Range (SJER) field site] ( https://www.neonscience.org/field-sites/field-sites-map/SJER )
365
366
located in Southern California has a very different ecosystem and climate than
366
367
the
@@ -387,12 +388,10 @@ keep track of data from different sites!
387
388
388
389
## Answers
389
390
390
- 1 ) Use the ` overlay() ` function to subtract the two rasters \& create
391
- the CHM.
391
+ 1 ) Use the ` lapp() ` function to subtract the two rasters \& create the CHM.
392
392
393
393
``` {r}
394
- CHM_ov_SJER <- overlay(DSM_SJER,
395
- DTM_SJER,
394
+ CHM_ov_SJER <- lapp(sds(list(DSM_SJER, DTM_SJER)),
396
395
fun = function(r1, r2){ return(r1 - r2) })
397
396
```
398
397
@@ -406,7 +405,7 @@ Create a histogram to check that the data distribution makes sense:
406
405
407
406
``` {r sjer-chm-overlay-hist}
408
407
ggplot(CHM_ov_SJER_df) +
409
- geom_histogram(aes(layer ))
408
+ geom_histogram(aes(SJER_dsmCrop ))
410
409
```
411
410
412
411
2 ) Create a plot of the CHM:
@@ -415,7 +414,7 @@ ggplot(CHM_ov_SJER_df) +
415
414
ggplot() +
416
415
geom_raster(data = CHM_ov_SJER_df,
417
416
aes(x = x, y = y,
418
- fill = layer )
417
+ fill = SJER_dsmCrop )
419
418
) +
420
419
scale_fill_gradientn(name = "Canopy Height",
421
420
colors = terrain.colors(10)) +
@@ -426,7 +425,7 @@ ggplot(CHM_ov_SJER_df) +
426
425
427
426
``` {r}
428
427
writeRaster(CHM_ov_SJER, "chm_ov_SJER.tiff",
429
- format = "GTiff",
428
+ filetype = "GTiff",
430
429
overwrite = TRUE,
431
430
NAflag = -9999)
432
431
```
@@ -437,10 +436,10 @@ writeRaster(CHM_ov_SJER, "chm_ov_SJER.tiff",
437
436
438
437
``` {r compare-chm-harv-sjer}
439
438
ggplot(CHM_HARV_df) +
440
- geom_histogram(aes(layer ))
439
+ geom_histogram(aes(HARV_dsmCrop ))
441
440
442
441
ggplot(CHM_ov_SJER_df) +
443
- geom_histogram(aes(layer ))
442
+ geom_histogram(aes(SJER_dsmCrop ))
444
443
```
445
444
446
445
:::::::::::::::::::::::::
@@ -452,7 +451,7 @@ ggplot(CHM_ov_SJER_df) +
452
451
:::::::::::::::::::::::::::::::::::::::: keypoints
453
452
454
453
- Rasters can be computed on using mathematical functions.
455
- - The ` overlay ()` function provides an efficient way to do raster math.
454
+ - The ` lapp ()` function provides an efficient way to do raster math.
456
455
- The ` writeRaster() ` function can be used to write raster data to a file.
457
456
458
457
::::::::::::::::::::::::::::::::::::::::::::::::::
0 commit comments