Skip to content

Commit 2461571

Browse files
committed
Lesson 4 updated by replacing calls to raster and rgdal packages with calls to terra package. #368 #363
1 parent c67c61a commit 2461571

File tree

1 file changed

+77
-78
lines changed

1 file changed

+77
-78
lines changed

episodes/04-raster-calculations-in-r.Rmd

Lines changed: 77 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,34 @@ source("setup.R")
2424
::::::::::::::::::::::::::::::::::::::::::::::::::
2525

2626
```{r load-libraries, echo=FALSE, results="hide", message=FALSE, warning=FALSE}
27-
library(raster)
28-
library(rgdal)
27+
library(terra)
2928
library(ggplot2)
3029
library(dplyr)
3130
```
3231

3332
```{r load-data, echo=FALSE}
3433
# Learners will have these data loaded from earlier episode
3534
# 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")
3737
3838
DSM_HARV_df <- as.data.frame(DSM_HARV, xy = TRUE)
3939
4040
# 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")
4243
4344
DTM_HARV_df <- as.data.frame(DTM_HARV, xy = TRUE)
4445
4546
# 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")
4749
4850
DSM_SJER_df <- as.data.frame(DSM_SJER, xy = TRUE)
4951
5052
# 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")
5255
5356
DTM_SJER_df <- as.data.frame(DTM_SJER, xy = TRUE)
5457
```
@@ -58,26 +61,27 @@ DTM_SJER_df <- as.data.frame(DTM_SJER, xy = TRUE)
5861
## Things You'll Need To Complete This Episode
5962

6063
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.
6266

6367

6468
::::::::::::::::::::::::::::::::::::::::::::::::::
6569

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.
7175

7276
## Raster Calculations in R
7377

7478
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.
8185

8286
![](fig/dc-spatial-raster/lidarTree-height.png){alt='Source: National Ecological Observatory Network (NEON)'}
8387

@@ -93,26 +97,25 @@ buildings, etc. with the influence of ground elevation removed.
9397

9498
### Load the Data
9599

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.
100103

101104
::::::::::::::::::::::::::::::::::::::: challenge
102105

103106
## Exercise
104107

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?
108111

109112
::::::::::::::: solution
110113

111114
## Solution
112115

113116
```{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")
116119
```
117120

118121
:::::::::::::::::::::::::
@@ -150,7 +153,7 @@ We can calculate the difference between two rasters in two different ways:
150153
or for more efficient processing - particularly if our rasters are large and/or
151154
the calculations we are performing are complex:
152155

153-
- using the `overlay()` function.
156+
- using the `lapp()` function.
154157

155158
## Raster Math \& Canopy Height Models
156159

@@ -172,7 +175,7 @@ We can now plot the output CHM.
172175
```{r harv-chm-plot}
173176
ggplot() +
174177
geom_raster(data = CHM_HARV_df ,
175-
aes(x = x, y = y, fill = layer)) +
178+
aes(x = x, y = y, fill = HARV_dsmCrop)) +
176179
scale_fill_gradientn(name = "Canopy Height", colors = terrain.colors(10)) +
177180
coord_quickmap()
178181
```
@@ -182,17 +185,18 @@ Canopy Height Model (CHM).
182185

183186
```{r create-hist}
184187
ggplot(CHM_HARV_df) +
185-
geom_histogram(aes(layer))
188+
geom_histogram(aes(HARV_dsmCrop))
186189
```
187190

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?
190193

191194
::::::::::::::::::::::::::::::::::::::: challenge
192195

193196
## Challenge: Explore CHM Raster Values
194197

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.
196200

197201
1. What is the min and maximum value for the Harvard Forest Canopy Height Model (`CHM_HARV`) that we just created?
198202
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
208212
`na.rm = TRUE`.
209213

210214
```{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)
213217
```
214218

215219
2) Possible ways include:
216220

217221
- Create a histogram
218-
- Use the `min()` and `max()` functions.
222+
- Use the `min()`, `max()`, and `range()` functions.
219223
- Print the object and look at the `values` attribute.
220224

221225
3)
222226
```{r chm-harv-hist}
223227
ggplot(CHM_HARV_df) +
224-
geom_histogram(aes(layer))
228+
geom_histogram(aes(HARV_dsmCrop))
225229
```
226230

227231
4)
228232
```{r chm-harv-hist-green}
229233
ggplot(CHM_HARV_df) +
230-
geom_histogram(aes(layer), colour="black",
234+
geom_histogram(aes(HARV_dsmCrop), colour="black",
231235
fill="darkgreen", bins = 6)
232236
```
233237

234238
5)
235239
```{r chm-harv-raster}
236240
custom_bins <- c(0, 10, 20, 30, 40)
237241
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))
239244
240245
ggplot() +
241246
geom_raster(data = CHM_HARV_df , aes(x = x, y = y,
@@ -248,7 +253,7 @@ ggplot() +
248253

249254
::::::::::::::::::::::::::::::::::::::::::::::::::
250255

251-
## Efficient Raster Calculations: Overlay Function
256+
## Efficient Raster Calculations
252257

253258
Raster math, like we just did, is an appropriate approach to raster calculations
254259
if:
@@ -258,48 +263,43 @@ if:
258263

259264
However, raster math is a less efficient approach as computation becomes more
260265
complex or as file sizes become large.
261-
The `overlay()` function is more efficient when:
262266

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
268268
them using efficient processing methods. The syntax is
269269

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)`.
271274

272275
::::::::::::::::::::::::::::::::::::::::: callout
273276

274277
## Data Tip
275278

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`).
280281

281282
::::::::::::::::::::::::::::::::::::::::::::::::::
282283

283284
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.
285286

286287
::::::::::::::::::::::::::::::::::::::::: callout
287288

288289
## Data Tip
289290

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:
294295
`function_name <- function(variable1, variable2) { WhatYouWantDone, WhatToReturn}`
295296

296297

297298
::::::::::::::::::::::::::::::::::::::::::::::::::
298299

299300
```{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) })
303303
```
304304

305305
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:
314314
```{r harv-chm-overlay}
315315
ggplot() +
316316
geom_raster(data = CHM_ov_HARV_df,
317-
aes(x = x, y = y, fill = layer)) +
317+
aes(x = x, y = y, fill = HARV_dsmCrop)) +
318318
scale_fill_gradientn(name = "Canopy Height", colors = terrain.colors(10)) +
319319
coord_quickmap()
320320
```
321321

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()`
323323
function compare?
324324

325325
## Export a GeoTIFF
@@ -334,12 +334,13 @@ contains (CHM data) and for where (HARVard Forest). The `writeRaster()` function
334334
by default writes the output file to your working directory unless you specify a
335335
full file path.
336336

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.
339340

340341
```{r write-raster, eval=FALSE}
341342
writeRaster(CHM_ov_HARV, "CHM_HARV.tiff",
342-
format="GTiff",
343+
filetype="GTiff",
343344
overwrite=TRUE,
344345
NAflag=-9999)
345346
```
@@ -348,7 +349,7 @@ writeRaster(CHM_ov_HARV, "CHM_HARV.tiff",
348349

349350
The function arguments that we used above include:
350351

351-
- **format:** specify that the format will be `GTiff` or GeoTIFF.
352+
- **filetype:** specify that the format will be `GTiff` or GeoTIFF.
352353
- **overwrite:** If TRUE, R will overwrite any existing file with the same
353354
name in the specified directory. USE THIS SETTING WITH CAUTION!
354355
- **NAflag:** set the GeoTIFF tag for `NoDataValue` to -9999, the National
@@ -358,9 +359,9 @@ The function arguments that we used above include:
358359

359360
## Challenge: Explore the NEON San Joaquin Experimental Range Field Site
360361

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
364365
[NEON San Joaquin Experimental Range (SJER) field site](https://www.neonscience.org/field-sites/field-sites-map/SJER)
365366
located in Southern California has a very different ecosystem and climate than
366367
the
@@ -387,12 +388,10 @@ keep track of data from different sites!
387388

388389
## Answers
389390

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.
392392

393393
```{r}
394-
CHM_ov_SJER <- overlay(DSM_SJER,
395-
DTM_SJER,
394+
CHM_ov_SJER <- lapp(sds(list(DSM_SJER, DTM_SJER)),
396395
fun = function(r1, r2){ return(r1 - r2) })
397396
```
398397

@@ -406,7 +405,7 @@ Create a histogram to check that the data distribution makes sense:
406405

407406
```{r sjer-chm-overlay-hist}
408407
ggplot(CHM_ov_SJER_df) +
409-
geom_histogram(aes(layer))
408+
geom_histogram(aes(SJER_dsmCrop))
410409
```
411410

412411
2) Create a plot of the CHM:
@@ -415,7 +414,7 @@ ggplot(CHM_ov_SJER_df) +
415414
ggplot() +
416415
geom_raster(data = CHM_ov_SJER_df,
417416
aes(x = x, y = y,
418-
fill = layer)
417+
fill = SJER_dsmCrop)
419418
) +
420419
scale_fill_gradientn(name = "Canopy Height",
421420
colors = terrain.colors(10)) +
@@ -426,7 +425,7 @@ ggplot(CHM_ov_SJER_df) +
426425

427426
```{r}
428427
writeRaster(CHM_ov_SJER, "chm_ov_SJER.tiff",
429-
format = "GTiff",
428+
filetype = "GTiff",
430429
overwrite = TRUE,
431430
NAflag = -9999)
432431
```
@@ -437,10 +436,10 @@ writeRaster(CHM_ov_SJER, "chm_ov_SJER.tiff",
437436

438437
```{r compare-chm-harv-sjer}
439438
ggplot(CHM_HARV_df) +
440-
geom_histogram(aes(layer))
439+
geom_histogram(aes(HARV_dsmCrop))
441440
442441
ggplot(CHM_ov_SJER_df) +
443-
geom_histogram(aes(layer))
442+
geom_histogram(aes(SJER_dsmCrop))
444443
```
445444

446445
:::::::::::::::::::::::::
@@ -452,7 +451,7 @@ ggplot(CHM_ov_SJER_df) +
452451
:::::::::::::::::::::::::::::::::::::::: keypoints
453452

454453
- 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.
456455
- The `writeRaster()` function can be used to write raster data to a file.
457456

458457
::::::::::::::::::::::::::::::::::::::::::::::::::

0 commit comments

Comments
 (0)