## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 8, fig.height = 7, fig.ext = "png" ) eval_chunks <- Sys.getenv("COPERNICUS_DATA_VIGNETTE") != "" ## ----setup, message=FALSE----------------------------------------------------- library(CopernicusDataspace) library(dplyr) library(jsonlite) library(sf) library(stars) ## ----data-download, eval=eval_chunks------------------------------------------ # if (dse_has_s3_secret()) { # ## Define the area of interest: # bbox <- st_bbox(c(xmin = 4.66, # ymin = 52.842, # xmax = 7.15, # ymax = 53.62), crs = 4326) # # ## Assume that we have already located the asset below within our # ## area of interest: # id <- "S1A_IW_GRDH_1SDV_20241125T055820_20241125T055845_056707_06F55C_12F9_COG" # # ## And it's from this collection: # cllctn <- "sentinel-1-grd" # # ## Get the URI for the manifest.safe file. This is the preferred entry # ## point into the data. It contains all bands and all meta-information # ## (like accurate Ground Control Points): # uri_safe <- dse_stac_get_uri(id, "safe_manifest", cllctn) # # ## Translate the URI into a virtual system indicator (VSI), such that # ## the stars package can interact with it: # vsi_safe <- dse_s3_uri_to_vsi(uri_safe) # # ## Set up the S3 credentials such that the stars package (and its # ## underpinning GDAL library) will recognise them. # dse_s3_set_gdal_options() # # ## Create a stars proxy object from the VSI. No data is downloaded # ## yet. But you can set up lazy data manipulations with tidyverse. # proxy <- read_stars(vsi_safe, proxy = TRUE) # } ## ----meta-info, eval=eval_chunks---------------------------------------------- # ## Use `gdal_info` to retrieve the raster information # json_info <- # gdal_utils("info", vsi_safe, options = c("-json"), quiet = TRUE) |> # fromJSON() # # ## Get the ground control points for the specific raster. # ## You will need it for subsetting the proxy. # gcp <- # st_as_sf(json_info$gcps$gcpList, coords= c("x", "y"), crs = # st_crs(json_info$gcps$coordinateSystem$wkt)) # # ## A plot showing where the raster's GCPs are, and where the bbox lies # par(mar = c(1, 1, 1, 1)) # plot(gcp["pixel"] |> st_geometry(), main = "Ground Control Points", col = NA) # plot(gcp["pixel"], add = TRUE) # plot(bbox |> st_as_sfc() |> st_geometry(), border = "red", add = TRUE) # # ## Determine which raster indices are within the bbox # ## of our area of interest: # gcp_crop <- # st_crop(gcp, # st_transform(bbox |> # st_as_sfc() |> # st_buffer(units::as_units(1, "km")), # st_crs(json_info$gcps$coordinateSystem$wkt))) # # dim_x <- st_get_dimension_values(proxy, "x") |> sort() # dim_x <- which(dim_x >= min(gcp_crop$pixel) & dim_x <= max(gcp_crop$pixel)) # dim_y <- st_get_dimension_values(proxy, "y") |> sort() # dim_y <- which(dim_y >= min(gcp_crop$line) & dim_y <= max(gcp_crop$line)) ## ----echo=FALSE--------------------------------------------------------------- knitr::include_graphics("../man/figures/read-data-gcp.png") ## ----data-mask, eval=eval_chunks---------------------------------------------- # masked_proxy <- # proxy[,dim_x, dim_y,] |> # st_apply(c("x", "y"), \(x) { # ## From json_info$bands we know that band 1=VH and 2=VV # ## We want VH but only when VV >= 30: # ifelse(x[2] >= 30, x[1], NA) # }) # # ## Store the masked file: # masked_file <- tempfile(fileext = ".tif") # write_stars(masked_proxy, masked_file, chunk_size = c(1024, 1024), # NA_value = -9999) ## ----data-read-masked, eval=eval_chunks--------------------------------------- # masked <- read_stars(masked_file) # plot(masked, main = "masked") ## ----echo=FALSE--------------------------------------------------------------- knitr::include_graphics("../man/figures/read-data-masked.png") ## ----data-add-gcp, eval=eval_chunks------------------------------------------- # ## The masked file has lost original GCP information # ## So create a reference file where we explicitly add the GCP info # ref_file <- tempfile(fileext = ".tif") # # ## Update GCP info for selected raster indices: # gcp <- # json_info$gcps$gcpList |> # mutate(pixel = pixel - min(dim_x) - 1, # line = line - min(dim_y) - 1) |> # filter(line >= 0 & pixel >= 0) # opts <- # cbind("-gcp", as.matrix(gcp[, c("pixel", "line", "x", "y", "x")])) |> # apply(1, c) |> c() # # ## Create reference file with GCP info # gdal_utils( # "translate", # source = masked_file, # destination = ref_file, # options = c(opts, # "-a_srs", json_info$gcps$coordinateSystem$wkt, # "-a_nodata", "-9999") ## missing values # ) ## ----data-warp, eval=eval_chunks---------------------------------------------- # ## Warp the masked file to a fixed raster with meaningful CRS # ## (In this case UTM31 with 10x10m cells) # warped_file <- tempfile(fileext = ".tif") # # gdal_utils( # "warp", # source = ref_file, # destination = warped_file, # options = c( # "-t_srs", "EPSG:32631", # "-tps", # "-tr", c(10, 10), "-tap", "-r", "bilinear", # "-srcnodata", "-9999", ## missing values # "-dstnodata", "-9999", ## missing values # "-overwrite")) # warped <- read_stars(warped_file) # # plot(warped, reset = FALSE, axes = TRUE, main = "warped") ## ----echo=FALSE--------------------------------------------------------------- knitr::include_graphics("../man/figures/read-data-warped.png")