temporalComposite.R 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #' Calculate MODIS Composite Images
  2. #'
  3. #' @description
  4. #' Based on a user-defined function, e.g. \code{max} for maximum value
  5. #' composites (MVC), aggregate native 16-day MODIS datasets to custom temporal
  6. #' composites.
  7. #'
  8. #' @param x \code{Raster*} or \code{character}. MODIS composite dataset with an
  9. #' associated "composite_day_of_the_year" SDS, e.g. all vegetation indices
  10. #' products (MOD13).
  11. #' @param y \code{Raster*} or \code{character}. MODIS
  12. #' "composite_day_of_the_year" SDS associated with 'x'.
  13. #' @param timeInfo \code{Date} vector corresponding to all input layers. If not
  14. #' further specified, this is tried to be created through invoking
  15. #' \code{\link{extractDate}} upon 'x', assuming standard MODIS file names.
  16. #' @param interval \code{character}. Time period for aggregation, see
  17. #' \code{\link{aggInterval}}.
  18. #' @param fun,na.rm \code{function}. See \code{\link{overlay}}.
  19. #' @param cores \code{integer}. Number of cores for parallel processing.
  20. #' @param filename \code{character}. Optional output filename.
  21. #' @param ... Additional arguments passed to \code{\link{writeRaster}}.
  22. #'
  23. #' @return A \code{Raster*} object.
  24. #'
  25. #' @author
  26. #' Florian Detsch
  27. #'
  28. #' @seealso
  29. #' \code{\link{aggInterval}}, \code{\link{calc}}, \code{\link{writeRaster}}.
  30. #'
  31. #' @examples
  32. #' \dontrun{
  33. #' library(mapview)
  34. #' frc <- as(subset(franconia, district == "Mittelfranken"), "Spatial")
  35. #' tfs <- runGdal("MOD13A1", begin = "2015001", end = "2016366", extent = frc,
  36. #' job = "temporalComposite", SDSstring = "100000000010")
  37. #'
  38. #' ndvi <- sapply(tfs[[1]], "[[", 1)
  39. #' cdoy <- sapply(tfs[[1]], "[[", 2)
  40. #'
  41. #' mmvc <- temporalComposite(ndvi, cdoy)
  42. #' plot(mmvc[[1:4]])
  43. #' }
  44. #'
  45. #' @export temporalComposite
  46. #' @name temporalComposite
  47. temporalComposite <- function(x, y,
  48. timeInfo = extractDate(x, asDate = TRUE)$inputLayerDates,
  49. interval = c("month", "year", "fortnight"),
  50. fun = max, na.rm = TRUE,
  51. cores = 1L, filename = "", ...) {
  52. if (inherits(x, "character")) { names(x) <- NULL; x <- raster::stack(x) }
  53. if (inherits(y, "character")) { names(y) <- NULL; y <- raster::stack(y) }
  54. ## append year to "composite_day_of_the_year"
  55. y <- reformatDOY(y, cores = cores)
  56. ## create half-monthly time series
  57. dates_seq <- aggInterval(timeInfo, interval[1])
  58. ## initialize parallel cluster with required variables
  59. cl <- parallel::makePSOCKcluster(cores)
  60. on.exit(parallel::stopCluster(cl))
  61. parallel::clusterExport(cl, c("x", "y", "fun", "na.rm", "timeInfo", "dates_seq"),
  62. envir = environment())
  63. ## generate temporal composites
  64. lst_seq <- parallel::parLapply(cl, 1:length(dates_seq$begin), function(i) {
  65. dff <- timeInfo - dates_seq$begin[i]
  66. ids <- which(dff <= 16 & dff >= (-16))
  67. if (length(ids) == 0)
  68. return(NULL)
  69. lst <- lapply(ids, function(j) {
  70. doy <- raster::getValues(raster::subset(y, j))
  71. out <- which(doy < dates_seq$beginDOY[i] | doy > dates_seq$endDOY[i])
  72. val <- raster::getValues(raster::subset(x, j))
  73. val[out] <- NA
  74. raster::setValues(raster::subset(x, j), val)
  75. })
  76. rst <- if (length(lst) == 1) {
  77. lst[[1]]
  78. } else {
  79. rst <- raster::stack(lst)
  80. suppressWarnings(rst <- raster::calc(rst, fun = fun, na.rm = na.rm))
  81. }
  82. names(rst) <- paste0("A", dates_seq$beginDOY[i])
  83. return(rst)
  84. })
  85. ids <- !sapply(lst_seq, is.null)
  86. rst_seq <- raster::stack(lst_seq[ids])
  87. ## write to disk (optional)
  88. if (nchar(filename) > 0)
  89. rst_seq <- raster::writeRaster(rst_seq, filename, ...)
  90. return(rst_seq)
  91. }