Skip to content

Commit

Permalink
added accuracy assesment scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
mldesroc committed Apr 11, 2024
1 parent 5a81fef commit 39c2455
Show file tree
Hide file tree
Showing 4 changed files with 531 additions and 0 deletions.
149 changes: 149 additions & 0 deletions scripts/create_loss_layer.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
library(terra)
library(dplyr)
library(tidyr)


######################### data setup #########################
lt_data_dir <- file.path("rasters/lt_nbr_ftv_1985_2021_combo6")
lt_name <- "lt_nbr_1985_2021_combo6"
ftv_file_name <- "lt_nbr_ftv_1985_2021_combo6"
vertex_file_name <- "lt_nbr_is_vertex_1985_2021_combo6"
dir.create(paste0(lt_data_dir, "/ftv_tiles"))
dir.create(paste0(lt_data_dir, "/vertex_tiles"))
dir.create(paste0(lt_data_dir, "/masked_ftv"))
dir.create(paste0(lt_data_dir, "/losses"))

######################### merge tiles function #########################
#ftv stacks from LT are often very large, and as such are split into several tiles. This function will stitch those tiles back together
#if you have a single ftv file, you can skip this step
#requires gdal installation
merge_tiles <- function(source_dir, dest_file, pattern = ".*tif") {
vrt_file <- gsub("(tiff|tif)", "vrt", dest_file)

files <- list.files(source_dir, full.names = TRUE, pattern = pattern)
index_file <- file.path(source_dir, "files.txt")
writeLines(files, index_file)
system(
glue::glue("gdalbuildvrt {vrt_file} -input_file_list {index_file}")
)
system(
glue::glue(
paste(
"gdal_translate -co COMPRESS=DEFLATE -co PREDICTOR=3 -co TILED=YES",
"-co BIGTIFF=YES {vrt_file} {dest_file}"
)
)
)
unlink(index_file)
unlink(vrt_file)
return(dest_file)
}

merge_tiles(lt_data_dir, paste0(lt_data_dir, "/", ftv_file_name, "_all.tif"), pattern = "lt_nbr_ftv.*tif" )


######################### retile ftv and vertex layers #########################
# load merged ftv and vertex layers
ftv <- terra::rast(paste0(lt_data_dir, "/", ftv_file_name, "_all.tif"))
names(ftv) <- 1985:2022
is_vertex <- terra::rast(paste0(lt_data_dir, "/", vertex_file_name, ".tif"))
names(is_vertex) <- 1985:2022


#analysis requires much smaller tiles, can adjust size of tiles based on processing ability of your computer
tile_grid <- terra::rast(
extent = terra::ext(ftv),
ncols = 30,
nrows = 30
)

terra::makeTiles(
ftv,
tile_grid,
path.expand(paste0(lt_data_dir, '/ftv_tiles/ftv_', ".tif")),
overwrite = TRUE
)

terra::makeTiles(
is_vertex,
tile_grid,
path.expand(paste0(lt_data_dir, '/vertex_tiles/is_vertex_', ".tif")),
overwrite = TRUE
)

######################### mask smoothed ftv traj with vertices #########################
#removing pixels that are not breakpoints in spectral trajectory
vertex_files <- list.files(paste0(lt_data_dir,"/vertex_tiles/"), pattern = "is_vertex_.*.tif", full.names = TRUE)
ftv_files <- list.files(paste0(lt_data_dir,"/ftv_tiles/"), pattern = "ftv_.*.tif", full.names = TRUE)

lapply(1:length(ftv_files), \(i) {
message(paste0("Working on iteration ", i))
vertex_file <- vertex_files[i]
ftv_file <- ftv_files[i]
index <- stringr::str_split(gsub(pattern = "\\.tif", "", basename(vertex_file)), "_")[[1]] |> tail(1)
masked_ftv <- file.path(paste0(lt_data_dir,"/masked_ftv/masked_ftv_", index, ".tif"))

if (!file.exists(masked_ftv)){
terra::mask(terra::rast(ftv_file), terra::rast(vertex_file), maskvalues = 0, filename = masked_ftv)
}
})

######################### create all loss layer #########################
#using masked ftv to identify decreasing segments
#value of previous vertex greater than value of current vertex

detect_loss <- function(model, data, ...){
# Collect these for later
years <- names(data)

# Build a place holder data.frame
results_container <- data.frame(
matrix(nrow = nrow(data), ncol = length(years))
)
names(results_container) <- years

# Compute magnitudes for loss vertices, with > 1 segment
data <- data |>
mutate(id = 1:nrow(data)) |> # keep track of pixel order
pivot_longer(-id, names_to = "year") |>
mutate(year = as.numeric(year) + 1) |> # LT defaults adds a year to the vertex date to assign year of disturbance
group_by(id) |>
filter(!is.na(value)) |>
filter(n() > 2) |>
mutate(change = value - lead(value)) |>
filter(change > 0) |>
select(-value) |>
ungroup() |>
pivot_wider(names_from = "year", values_from = "change")

# Pad the results, filling in the years that don't have disturbances
fill_years <- setdiff(years, names(data))
fill_cols <- lapply(fill_years, \(fy) {
return(rep(NA, nrow(data)))
})
names(fill_cols) <- fill_years
data <- bind_cols(data, fill_cols) |>
dplyr::relocate(all_of(years))

# Insert results in the correct location
results_container[data$id, ] <- data |> select(-id)
return(results_container)
}

#use loss funtction to create loss tiles
masked_ftvs <- list.files(paste0(lt_data_dir, "/masked_ftv/"), full.names = TRUE)
lapply(masked_ftvs, \(masked_file) {
index <- stringr::str_split(gsub(pattern = "\\.tif", "", basename(masked_file)), "_")[[1]] |> tail(1)
losses <- file.path(paste0(lt_data_dir,"/losses/losses", index , ".tif"))

if (!file.exists(losses)){
terra::predict(terra::rast(masked_file), list(), detect_loss, filename = losses)
}
})

#merge loss tiles into new loss.tif
merge_tiles(paste0(lt_data_dir, "/losses"), paste0(lt_data_dir,"/losses/", lt_name,"_all_losses.tif"), pattern = "*.tif" )
all_losses <- rast("rasters/lt_nbr_rt1_1985-2022/losses/rt1_1985_2022_all_losses.tif")
names(all_losses) <- 1985:2022
all_losses <- subset(all_losses, 6:38) #remove pre 1990 years, optional step
writeRaster(all_losses, paste0(lt_data_dir,"/losses/", lt_name,"_all_losses.tif"), overwrite = TRUE)
59 changes: 59 additions & 0 deletions scripts/harvest_brick.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
library(terra)
######################## set up########################
years <- 1990:2021 #study years
harvest_directory <- file.path("../GIS_Files/harvest_rasters")
dir.create(paste0(harvest_directory, "/harv_layers"))
harv_records <- vect("../GIS_Files/albers_combined_harv_records.gpkg")
#need study area bounds
harv_boundaries <- vect("../GIS_Files/combined_tract_boundaries.gpkg")

crs <- labrador.client::get_cafri_crs()


######################## rasterize harvests ########################
harv_records$value <- 1 #dummy value for creating harvest raster

#use your LT output as reference raster here, want harvest layer to have same extent
ref_raster <- rast("rasters/combo12_all_losses2.tif")[[1]]
values(ref_raster) <- NA

lapply(1:length(years), \(i) {
message(paste0("Working on iteration ", i))

harv_subset <- terra::subset(harv_records,
(years[i] >= harv_records$start_date & years[i] <= harv_records$end_date)
| as.integer(harv_records$start_date) + 1 == years[i]
| as.integer(harv_records$end_date) + 1== years[i]
| as.integer(harv_records$start_date) - 1 == years [i]
| as.integer(harv_records$end_date) - 1 == years[i] )

harv_file <- file.path(paste0(harvest_directory, "/harv_layers/harv_layer_", years[i], ".tif"))
harv_exists <- file.exists(harv_file)

if (!harv_exists & nrow(harv_subset) != 0){
terra::rasterize(harv_subset, ref_raster, field = "value", filename = harv_file)
} else if (!harv_exists){
writeRaster(ref_raster, filename = harv_file)
}
})

######################## combine havrvest rasters into single harvest brick layer ########################
rasters <- list.files(paste0(harvest_directory, "/harv_layers/"), full.names = TRUE)
harv_raster <- rast(rasters)
names(harv_raster) <- years
harv_raster[is.na(harv_raster)] <- 0
writeRaster(harv_raster, paste0(harvest_directory,"/harvest_brick.tif"), overwrite = TRUE)
harv_raster <- rast(paste0(harvest_directory,"/harvest_brick.tif"))

######################## mask harvest brick with study area boundaries ########################
#terra throws a fit if the crs info doesn't match exactly, just making the labels match here, its the same crs
crs(harvest_rast) <- crs

#dummy value for making raster
harv_boundaries$rast_value <- 1
harv_boundaries <- rasterize(harv_boundaries, harv_raster, field = "rast_value")
#areas outside harvests set to NA
harv_raster <- mask(harv_raster, harv_boundaries)

writeRaster(harv_raster, paste0(harvest_directory,"/harvest_brick.tif"), overwrite = TRUE)
rast
Loading

0 comments on commit 39c2455

Please sign in to comment.