Skip to content

Commit b0b7a85

Browse files
Merge pull request #1144 from M3nin0/feature/dem-regularization
Support for DEM from MPC
2 parents fb85f44 + 4f9d04a commit b0b7a85

11 files changed

+267
-11
lines changed

NAMESPACE

+6
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ S3method(.raster_xres,terra)
126126
S3method(.raster_ymax,terra)
127127
S3method(.raster_ymin,terra)
128128
S3method(.raster_yres,terra)
129+
S3method(.reg_s2tile_convert,dem_cube)
129130
S3method(.reg_s2tile_convert,grd_cube)
130131
S3method(.reg_s2tile_convert,rtc_cube)
131132
S3method(.slice_dfr,numeric)
@@ -137,6 +138,7 @@ S3method(.source_collection_access_test,usgs_cube)
137138
S3method(.source_cube,stac_cube)
138139
S3method(.source_filter_tiles,"cdse_cube_sentinel-1-rtc")
139140
S3method(.source_filter_tiles,"deafrica_cube_sentinel-1-rtc")
141+
S3method(.source_filter_tiles,"mpc_cube_cop-dem-glo-30")
140142
S3method(.source_filter_tiles,"mpc_cube_sentinel-1-grd")
141143
S3method(.source_filter_tiles,stac_cube)
142144
S3method(.source_item_get_bands,stac_cube)
@@ -157,6 +159,7 @@ S3method(.source_items_fid,stac_cube)
157159
S3method(.source_items_new,"aws_cube_landsat-c2-l2")
158160
S3method(.source_items_new,"deafrica_cube_sentinel-1-rtc")
159161
S3method(.source_items_new,"deafrica_cube_sentinel-2-l2a")
162+
S3method(.source_items_new,"mpc_cube_cop-dem-glo-30")
160163
S3method(.source_items_new,"mpc_cube_landsat-c2-l2")
161164
S3method(.source_items_new,"mpc_cube_sentinel-1-grd")
162165
S3method(.source_items_new,"mpc_cube_sentinel-1-rtc")
@@ -172,6 +175,7 @@ S3method(.source_items_tile,"aws_cube_landsat-c2-l2")
172175
S3method(.source_items_tile,"cdse_cube_sentinel-1-rtc")
173176
S3method(.source_items_tile,"deafrica_cube_rainfall-chirps-daily")
174177
S3method(.source_items_tile,"deafrica_cube_rainfall-chirps-monthly")
178+
S3method(.source_items_tile,"mpc_cube_cop-dem-glo-30")
175179
S3method(.source_items_tile,"mpc_cube_landsat-c2-l2")
176180
S3method(.source_items_tile,"mpc_cube_sentinel-1-grd")
177181
S3method(.source_items_tile,"mpc_cube_sentinel-1-rtc")
@@ -187,6 +191,7 @@ S3method(.source_roi_tiles,"mpc_cube_landsat-c2-l2")
187191
S3method(.source_roi_tiles,sdc_cube)
188192
S3method(.source_roi_tiles,stac_cube)
189193
S3method(.source_tile_get_bbox,"cdse_cube_sentinel-1-rtc")
194+
S3method(.source_tile_get_bbox,"mpc_cube_cop-dem-glo-30")
190195
S3method(.source_tile_get_bbox,"mpc_cube_sentinel-1-grd")
191196
S3method(.source_tile_get_bbox,"mpc_cube_sentinel-1-rtc")
192197
S3method(.source_tile_get_bbox,stac_cube)
@@ -373,6 +378,7 @@ S3method(sits_reclassify,default)
373378
S3method(sits_reduce,raster_cube)
374379
S3method(sits_reduce,sits)
375380
S3method(sits_regularize,default)
381+
S3method(sits_regularize,dem_cube)
376382
S3method(sits_regularize,derived_cube)
377383
S3method(sits_regularize,raster_cube)
378384
S3method(sits_regularize,sar_cube)

R/api_cube.R

+14-1
Original file line numberDiff line numberDiff line change
@@ -350,12 +350,25 @@ NULL
350350
},
351351
.default = FALSE
352352
)
353+
354+
dem_cube <- .try({
355+
.conf("sources", source, "collections", collection, "dem_cube")
356+
},
357+
.default = FALSE
358+
)
359+
353360
if (sar_cube) {
354361
if (grepl("rtc", col_class, fixed = TRUE))
355362
unique(c(col_class, "rtc_cube", "sar_cube", s3_class, class(cube)))
356363
else
357364
unique(c(col_class, "grd_cube", "sar_cube", s3_class, class(cube)))
358-
} else {
365+
}
366+
367+
else if (dem_cube) {
368+
unique(c(col_class, "dem_cube", s3_class, class(cube)))
369+
}
370+
371+
else {
359372
unique(c(col_class, s3_class, class(cube)))
360373
}
361374
}

R/api_plot_raster.R

+2-2
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@
310310
# verifies if stars package is installed
311311
.check_require_packages("stars")
312312
# verifies if tmap package is installed
313-
.check_require_packages("plot")
313+
.check_require_packages("tmap")
314314

315315
# deal with color palette
316316
.check_palette(palette)
@@ -394,7 +394,7 @@
394394
# verifies if stars package is installed
395395
.check_require_packages("stars")
396396
# verifies if tmap package is installed
397-
.check_require_packages("plot")
397+
.check_require_packages("tmap")
398398
# precondition - check color palette
399399
.check_palette(palette)
400400
# revert the palette

R/api_regularize.R

+48
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,51 @@
236236
cube_class <- c(cube_class[[1]], "sar_cube", cube_class[-1])
237237
.cube_set_class(cube, cube_class)
238238
}
239+
#' @noRd
240+
#' @export
241+
#'
242+
.reg_s2tile_convert.dem_cube<- function(cube, roi = NULL, tiles = NULL) {
243+
# generate Sentinel-2 tiles and intersects it with doi
244+
tiles_mgrs <- .s2tile_open(roi, tiles)
245+
246+
# create a new cube according to Sentinel-2 MGRS
247+
cube_class <- .cube_s3class(cube)
248+
249+
cube <- tiles_mgrs |>
250+
dplyr::rowwise() |>
251+
dplyr::group_map(~{
252+
# prepare a sf object representing the bbox of each image in
253+
# file_info
254+
cube_crs <- dplyr::filter(cube, .data[["crs"]] == .x[["crs"]])
255+
if (nrow(cube_crs) == 0) {
256+
cube_crs <- cube
257+
}
258+
fi_bbox <- .bbox_as_sf(.bbox(
259+
x = .fi(cube_crs),
260+
default_crs = .crs(cube_crs),
261+
by_feature = TRUE
262+
))
263+
file_info <- .fi(cube_crs)[.intersects({{fi_bbox}}, .x), ]
264+
.cube_create(
265+
source = .tile_source(cube_crs),
266+
collection = .tile_collection(cube_crs),
267+
satellite = .tile_satellite(cube_crs),
268+
sensor = .tile_sensor(cube_crs),
269+
tile = .x[["tile_id"]],
270+
xmin = .xmin(.x),
271+
xmax = .xmax(.x),
272+
ymin = .ymin(.x),
273+
ymax = .ymax(.x),
274+
crs = paste0("EPSG:", .x[["epsg"]]),
275+
file_info = file_info
276+
)
277+
}) |>
278+
dplyr::bind_rows()
279+
280+
# Filter non-empty file info
281+
cube <- .cube_filter_nonempty(cube)
282+
283+
# Finalize customizing cube class
284+
cube_class <- c(cube_class[[1]], "dem_cube", cube_class[-1])
285+
.cube_set_class(cube, cube_class)
286+
}

R/api_source.R

+9
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,18 @@ NULL
6565
},
6666
.default = FALSE
6767
)
68+
# is this a collection of DEM data ?
69+
dem_cube <- .try({
70+
.conf("sources", source, "collections", collection, "dem_cube")
71+
},
72+
.default = FALSE
73+
)
6874
# if this is a SAR collection, add "sar_cube" to the class
6975
if (sar_cube)
7076
class(source) <- c("sar_cube", class(source))
77+
# if this is a DEM collection, add "dem_cube" to the class
78+
if (dem_cube)
79+
class(source) <- c("dem_cube", class(source))
7180
# add a class combining source and collection
7281
class_source_col <- paste(classes[[1]], tolower(collection), sep = "_")
7382
class(source) <- unique(c(class_source_col, class(source)))

R/api_source_mpc.R

+103
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,35 @@
233233
collection = collection
234234
)
235235
}
236+
#' @title Get bbox from file info for COP-DEM-GLO-30
237+
#' @keywords internal
238+
#' @noRd
239+
#' @param source Data source
240+
#' @param file_info File info
241+
#' @param ... Additional parameters.
242+
#' @param collection Image collection
243+
#' @return vector (xmin, ymin, xmax, ymax).
244+
#' @export
245+
`.source_tile_get_bbox.mpc_cube_cop-dem-glo-30` <- function(source,
246+
file_info, ...,
247+
collection = NULL) {
248+
.check_set_caller(".source_tile_get_bbox_mpc_dem_30")
249+
250+
# pre-condition
251+
.check_num(nrow(file_info), min = 1)
252+
253+
# get bbox based on file_info
254+
xmin <- min(file_info[["xmin"]])
255+
ymin <- min(file_info[["ymin"]])
256+
xmax <- max(file_info[["xmax"]])
257+
ymax <- max(file_info[["ymax"]])
258+
259+
# post-condition
260+
.check_that(xmin < xmax && ymin < ymax)
261+
# create a bbox
262+
bbox <- c(xmin = xmin, ymin = ymin, xmax = xmax, ymax = ymax)
263+
return(bbox)
264+
}
236265
#' @keywords internal
237266
#' @noRd
238267
#' @export
@@ -429,6 +458,53 @@
429458
#' @keywords internal
430459
#' @noRd
431460
#' @export
461+
`.source_items_new.mpc_cube_cop-dem-glo-30` <- function(source,
462+
collection,
463+
stac_query, ...,
464+
tiles = NULL) {
465+
.check_set_caller(".source_items_new_mpc_cube_cop-dem-glo-30")
466+
467+
# COP-DEM-GLO-30 does not support tiles - convert to ROI
468+
if (!is.null(tiles)) {
469+
roi <- .s2_mgrs_to_roi(tiles)
470+
stac_query[["params"]][["intersects"]] <- NULL
471+
stac_query[["params"]][["bbox"]] <- c(roi[["lon_min"]],
472+
roi[["lat_min"]],
473+
roi[["lon_max"]],
474+
roi[["lat_max"]]
475+
)
476+
}
477+
478+
# Fix temporal interval (All data available in the same date)
479+
stac_query[["params"]][["datetime"]] <- "2021-04-21/2021-04-23"
480+
481+
# Search content
482+
items_info <- rstac::post_request(q = stac_query, ...)
483+
.check_stac_items(items_info)
484+
# fetching all the metadata
485+
items_info <- suppressWarnings(
486+
rstac::items_fetch(items = items_info, progress = FALSE)
487+
)
488+
489+
# assign href
490+
access_key <- Sys.getenv("MPC_TOKEN")
491+
if (!nzchar(access_key)) {
492+
access_key <- NULL
493+
}
494+
# Clean old tokens cached in rstac
495+
.mpc_clean_token_cache()
496+
items_info <- suppressWarnings(
497+
rstac::items_sign(
498+
items_info, sign_fn = rstac::sign_planetary_computer(
499+
httr::add_headers("Ocp-Apim-Subscription-Key" = access_key)
500+
)
501+
)
502+
)
503+
return(items_info)
504+
}
505+
#' @keywords internal
506+
#' @noRd
507+
#' @export
432508
`.source_items_tile.mpc_cube_sentinel-1-grd` <- function(source,
433509
items, ...,
434510
collection = NULL) {
@@ -485,6 +561,20 @@
485561
})
486562
rstac::items_reap(items, field = c("properties", "tile"))
487563
}
564+
#' @title Organizes items for MPC COP-DEM-GLO-30 collections
565+
#' @param source Name of the STAC provider.
566+
#' @param items \code{STACItemcollection} object from rstac package.
567+
#' @param ... Other parameters to be passed for specific types.
568+
#' @param collection Collection to be searched in the data source.
569+
#' @return A list of items.
570+
#' @keywords internal
571+
#' @noRd
572+
#' @export
573+
`.source_items_tile.mpc_cube_cop-dem-glo-30` <- function(source,
574+
items, ...,
575+
collection = NULL) {
576+
rep("NoTilingSystem", rstac::items_length(items))
577+
}
488578
#' @title Filter S1 GRD tiles
489579
#' @noRd
490580
#' @param source Data source
@@ -509,6 +599,19 @@
509599
tiles = tiles)
510600

511601
}
602+
#' @title Filter COP-DEM-GLO-30 tiles
603+
#' @noRd
604+
#' @param source Data source
605+
#' @param cube Cube to be filtered
606+
#' @param tiles Tiles to be selected
607+
#' @return Filtered cube
608+
#' @export
609+
`.source_filter_tiles.mpc_cube_cop-dem-glo-30` <- function(source,
610+
collection,
611+
cube,
612+
tiles) {
613+
return(cube)
614+
}
512615
#' @title Check if roi or tiles are provided
513616
#' @param source Data source
514617
#' @param roi Region of interest

R/sits_merge.R

+5-8
Original file line numberDiff line numberDiff line change
@@ -207,16 +207,13 @@ sits_merge.raster_cube <- function(data1, data2, ...) {
207207
# Get data1 timeline.
208208
d1_tl <- unique(as.Date(.cube_timeline(data1)[[1]]))
209209
# Create new `file_info` using dates from `data1` timeline.
210-
fi_new <- purrr::map(seq_len(nrow(data2)), function(row) {
211-
data_row <- data2[row,]
212-
213-
fi <- .fi(data_row)
214-
fi[["date"]] <- as.Date(d1_tl[1:nrow(data_row)])
215-
216-
return(fi)
210+
fi_new <- purrr::map(sits_timeline(data1), function(date_row) {
211+
fi <- .fi(data2)
212+
fi[["date"]] <- as.Date(date_row)
213+
fi
217214
})
218215
# Assign the new `file_into` into `data2`
219-
data2[["file_info"]] <- fi_new
216+
data2[["file_info"]] <- list(dplyr::bind_rows(fi_new))
220217
# Merge cubes and return
221218
.cube_merge(data1, data2)
222219
}

R/sits_regularize.R

+46
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,52 @@ sits_regularize.sar_cube <- function(cube, ...,
205205
)
206206
return(cube)
207207
}
208+
209+
#' @rdname sits_regularize
210+
#' @export
211+
sits_regularize.dem_cube <- function(cube, ...,
212+
res,
213+
output_dir,
214+
roi = NULL,
215+
tiles = NULL,
216+
multicores = 2L,
217+
progress = TRUE) {
218+
# Preconditions
219+
.check_raster_cube_files(cube)
220+
.check_num_parameter(res, exclusive_min = 0)
221+
output_dir <- .file_normalize(output_dir)
222+
.check_output_dir(output_dir)
223+
.check_num_parameter(multicores, min = 1, max = 2048)
224+
.check_progress(progress)
225+
# Check for ROI and tiles
226+
.check_roi_tiles(roi, tiles)
227+
# Display warning message in case STAC cube
228+
# Prepare parallel processing
229+
.parallel_start(workers = multicores)
230+
on.exit(.parallel_stop(), add = TRUE)
231+
# Convert input sentinel1 cube to sentinel2 grid
232+
cube <- .reg_s2tile_convert(cube = cube, roi = roi, tiles = tiles)
233+
.check_that(nrow(cube) > 0,
234+
msg = .conf("messages", "sits_regularize_roi")
235+
)
236+
# Filter tiles
237+
if (is.character(tiles)) {
238+
cube <- .cube_filter_tiles(cube, tiles)
239+
}
240+
# DEMs don't have the temporal dimension, so the period is fixed in 1 day.
241+
period <- "P1D"
242+
# Call regularize in parallel
243+
cube <- .reg_cube(
244+
cube = cube,
245+
res = res,
246+
roi = roi,
247+
period = period,
248+
output_dir = output_dir,
249+
progress = progress
250+
)
251+
return(cube)
252+
}
253+
208254
#' @rdname sits_regularize
209255
#' @export
210256
sits_regularize.derived_cube <- function(cube, ...) {

inst/extdata/config_messages.yml

+1
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@
278278
.source_url: "invalid URL for requested source provider"
279279
.source_tile_get_bbox: "unable to retrieve images given a bounding box"
280280
.source_tile_get_bbox_cdse_s1_rtc: "unable to retrieve file information for S1 RTC cubes"
281+
.source_tile_get_bbox_mpc_dem_30: "unable to retrieve file information for COP DEM GLO 30m"
281282
.source_tile_get_bbox_mpc_s1_grd: "unable to retrieve file information for S1 GRD cubes"
282283
.stac_format_platform: "platform name should be unique (e.g. Landsat-8 or Sentinel-1A)"
283284
.stac_select_bands: "some bands for this product are not pre-configured in sits\n please include them in you user configuration file."

0 commit comments

Comments
 (0)