amadeus relies on spatial tools such as
terra and exactextractr. These packages use
efficient C++ implementations for raster, vector, and extraction
operations, so each individual operation is already optimized for common
workflows.
Wall-clock time can still grow quickly as spatial extents, time
ranges, variables, or extraction locations increase. Many
amadeus workflows parallelize naturally because dates,
variables, and location chunks can often be processed independently and
recombined after each worker writes its result.
We provide a few examples using common R parallel backend packages
such as purr, future + furrr,
mirai, and targets.
purrr baselineif (requireNamespace("purrr", quietly = TRUE)) {
library(purrr)
dates <- seq.Date(
as.Date("2022-01-01"),
as.Date("2022-01-05"),
by = "day"
)
results <- purrr::map(dates, function(d) {
process_covariates(
covariate = "narr",
date = c(d, d),
variable = "weasd",
path = "/path/to/narr"
)
})
}future + furrrterra::SpatRaster objects should not be returned across
worker boundaries. Instead, write each worker result to a file path and
load those files back in the parent process.
if (
requireNamespace("future", quietly = TRUE) &&
requireNamespace("furrr", quietly = TRUE) &&
requireNamespace("terra", quietly = TRUE)
) {
dates <- seq.Date(
as.Date("2022-01-01"),
as.Date("2022-01-05"),
by = "day"
)
future::plan(future::multisession, workers = 4)
raster_paths <- furrr::future_map_chr(dates, function(d) {
worker_dir <- file.path(tempdir(), paste0("amadeus-", format(d)))
dir.create(worker_dir, recursive = TRUE, showWarnings = FALSE)
processed <- amadeus::process_covariates(
covariate = "narr",
date = c(d, d),
variable = "weasd",
path = "/path/to/narr"
)
out_path <- file.path(worker_dir, paste0("weasd-", format(d), ".tif"))
terra::writeRaster(processed, out_path, overwrite = TRUE)
out_path
})
rasters <- lapply(raster_paths, terra::rast)
future::plan(future::sequential)
}miraiThe same file-path handoff pattern applies when using
mirai workers.
if (
requireNamespace("mirai", quietly = TRUE) &&
requireNamespace("terra", quietly = TRUE)
) {
dates <- seq.Date(
as.Date("2022-01-01"),
as.Date("2022-01-05"),
by = "day"
)
mirai::daemons(4)
raster_paths <- mirai::mirai_map(dates, .f = function(d) {
worker_dir <- file.path(tempdir(), paste0("amadeus-", format(d)))
dir.create(worker_dir, recursive = TRUE, showWarnings = FALSE)
processed <- amadeus::process_covariates(
covariate = "narr",
date = c(d, d),
variable = "weasd",
path = "/path/to/narr"
)
out_path <- file.path(worker_dir, paste0("weasd-", format(d), ".tif"))
terra::writeRaster(processed, out_path, overwrite = TRUE)
out_path
})
rasters <- lapply(unlist(raster_paths), terra::rast)
mirai::daemons(0)
}targetsA _targets.R file can make date grids explicit and skip
work that is already up to date.
if (
requireNamespace("targets", quietly = TRUE) &&
requireNamespace("tarchetypes", quietly = TRUE) &&
requireNamespace("terra", quietly = TRUE)
) {
library(targets)
tar_option_set(packages = c("amadeus", "terra"))
dates <- seq.Date(
as.Date("2022-01-01"),
as.Date("2022-01-05"),
by = "day"
)
list(
tar_target(date_grid, dates),
tarchetypes::tar_map(
values = data.frame(date = dates),
tar_target(
processed_path,
{
processed <- process_covariates(
covariate = "narr",
date = c(date, date),
variable = "weasd",
path = "/path/to/narr"
)
out_path <- file.path(
tempdir(),
paste0("weasd-", format(date), ".tif")
)
terra::writeRaster(processed, out_path, overwrite = TRUE)
out_path
},
format = "file"
)
)
)
}terra::SpatRaster objects cannot safely cross worker
boundaries; pass file paths between workers and the parent process
instead.tempdir() path and clean up intermediate files when they
are no longer needed.terra::makeTiles() may outperform process-level
parallelism.