diff --git a/.Rbuildignore b/.Rbuildignore index f9266b7..accf23d 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -2,3 +2,4 @@ ^\.Rproj\.user$ ^README\.Rmd$ ^LICENSE\.md$ +man-roxygen diff --git a/CopernicusMarine.Rproj b/CopernicusMarine.Rproj index eaa6b81..584b854 100644 --- a/CopernicusMarine.Rproj +++ b/CopernicusMarine.Rproj @@ -15,4 +15,5 @@ LaTeX: pdfLaTeX BuildType: Package PackageUseDevtools: Yes PackageInstallArgs: --no-multiarch --with-keep.source +PackageCheckArgs: --as-cran PackageRoxygenize: rd,collate,namespace diff --git a/DESCRIPTION b/DESCRIPTION index 25fd2f9..612e8c1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: CopernicusMarine Type: Package Title: Search Download and Handle Data from Copernicus Marine Service Information -Version: 0.0.3 -Date: 2023-01-17 +Version: 0.0.6 +Date: 2023-01-23 Authors@R: c(person("Pepijn", "de Vries", role = c("aut", "cre", "dtc"), email = "pepijn.devries@outlook.com", comment = c(ORCID = "0000-0002-7961-6646"))) diff --git a/NEWS.md b/NEWS.md index 18fc3a8..3df73c7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,14 @@ -CopernicusMarine v0.02 (Release date: 2023-01-16) +CopernicusMarine v0.0.6 (Release date: 2023-01-23) +------------- + + * Fix in tests in order to comply with CRAN + policy + * Catch and handle errors and warnings when connecting + with internet resources and return gracefully + * Update documentation on GDAL utils dependency + in WMS functions + +CopernicusMarine v0.0.3 (Release date: 2023-01-16) ------------- * Initial implementation features data imports via: diff --git a/R/copernicus_cite_product.r b/R/copernicus_cite_product.r index 4044e2a..832cdfd 100644 --- a/R/copernicus_cite_product.r +++ b/R/copernicus_cite_product.r @@ -3,7 +3,7 @@ #' `r lifecycle::badge('stable')` Get details for properly citing a Copernicus product. #' #' @inheritParams copernicus_download_motu -#' @return Returns a list of character strings. The first element is always the product title, id and doi. +#' @return Returns a vector of character strings. The first element is always the product title, id and doi. #' Remaining elements are other associated references. Note that the remaining references are returned as #' listed at Copernicus. Note that the citing formatting does not appear to be standardised. #' @rdname copernicus_cite_product @@ -17,6 +17,7 @@ #' @export copernicus_cite_product <- function(product) { product_details <- copernicus_product_details(product) + if (is.null(product_details)) return(NULL) result <- product_details$refs result <- c(doi = with(product_details, sprintf("E.U. Copernicus Marine Service Information; %s - %s (%s). DOI:%s", title, id, creationDate, doi)), result) diff --git a/R/copernicus_download_motu.r b/R/copernicus_download_motu.r index 0349bf7..fe6551a 100644 --- a/R/copernicus_download_motu.r +++ b/R/copernicus_download_motu.r @@ -25,7 +25,8 @@ #' @param overwrite A `logical` value. When `FALSE` (default), files at the `destination` won't be #' overwritten when the exist. Instead an error will be thrown if this is the case. When set to #' `TRUE`, existing files will be overwritten. -#' @return Returns `NULL` invisibly but saves the requested file at the `destination` when successful. +#' @return Returns a `logical` value invisibly indicating whether the requested file was +#' successfully stored at the `destination`. #' @rdname copernicus_download_motu #' @name copernicus_download_motu #' @examples @@ -58,9 +59,11 @@ copernicus_download_motu <- function( # Go to motu login page end get form id (lt) login_form <- - "https://cmems-cas.cls.fr/cas/login" %>% - httr::GET() - + .try_online({ + httr::GET("https://cmems-cas.cls.fr/cas/login") + }, "log-in page") + if (is.null(login_form)) return(invisible(FALSE)) + ## Check if you are already logged in: success <- login_form %>% @@ -81,9 +84,12 @@ copernicus_download_motu <- function( message(crayon::white("Logging in onto MOTU server...")) login_result <- - sprintf("https://cmems-cas.cls.fr/cas/login?username=%s&password=%s<=%s&execution=e1s1&_eventId=submit", - username, password, lt) %>% - httr::GET() + .try_online({ + sprintf("https://cmems-cas.cls.fr/cas/login?username=%s&password=%s<=%s&execution=e1s1&_eventId=submit", + username, password, lt) %>% + httr::GET() + }, "log-in page") + if (is.null(login_result)) return(invisible(FALSE)) success <- login_result %>% httr::content() %>% rvest::html_element(xpath = "//div[@id='msg']") %>% rvest::html_attr("class") @@ -95,8 +101,7 @@ copernicus_download_motu <- function( product_services <- copernicus_product_services(product) %>% dplyr::filter(layer == {{layer}}) %>% dplyr::pull("motu") - if (is.na(product_services)) - stop("There is no subsetting MOTU server available for the requested data") + if (is.null(product_services) || is.na(product_services)) return(invisible(FALSE)) if (missing(timerange)) timerange <- NULL else timerange <- format(as.POSIXct(timerange), "%Y-%m-%d+%H%%3A%M%%3A%S") prepare_url <- @@ -112,14 +117,16 @@ copernicus_download_motu <- function( paste0(collapse = "&") result <- - prepare_url %>% - httr::GET( - ## Make sure to pass on cookies obtained earlier with account details: - do.call( - httr::set_cookies, - as.list(structure(login_result$cookies$value, names = login_result$cookies$name)) - ) - ) + .try_online({ + prepare_url %>% + httr::GET( + ## Make sure to pass on cookies obtained earlier with account details: + do.call( + httr::set_cookies, + as.list(structure(login_result$cookies$value, names = login_result$cookies$name)) + ) + )}, "Copernicus") + if (is.null(result)) return(invisible(FALSE)) if (result$headers$`content-type` %>% startsWith("text/html")) { errors <- @@ -127,7 +134,10 @@ copernicus_download_motu <- function( httr::content() %>% rvest::html_element(xpath = "//p[@class='error']") %>% rvest::html_text() - if (!is.na(errors)) stop(errors) + if (!is.na(errors)) { + message(errors) + return(invisible(FALSE)) + } message(crayon::white("Downloading file...")) @@ -138,17 +148,21 @@ copernicus_download_motu <- function( rvest::html_attr("action") if (dir.exists(destination)) destination <- file.path(destination, basename(download_url)) - download_url %>% - httr::GET( - httr::write_disk(destination, overwrite = overwrite), - ## Make sure to pass on cookies obtained earlier with account details: - do.call( - httr::set_cookies, - as.list(structure(login_result$cookies$value, names = login_result$cookies$name)) + download_result <- .try_online({ + download_url %>% + httr::GET( + httr::write_disk(destination, overwrite = overwrite), + ## Make sure to pass on cookies obtained earlier with account details: + do.call( + httr::set_cookies, + as.list(structure(login_result$cookies$value, names = login_result$cookies$name)) + ) ) - ) + }, "Copernicus") + + if (is.null(download_result)) return(invisible(FALSE)) message(crayon::green("Done")) - return(invisible(NULL)) + return(invisible(TRUE)) } else { stop("Retrieved unexpected content...") diff --git a/R/copernicus_product_details.r b/R/copernicus_product_details.r index a151acf..925990e 100644 --- a/R/copernicus_product_details.r +++ b/R/copernicus_product_details.r @@ -22,8 +22,15 @@ #' @export copernicus_product_details <- function(product, layer, variable) { if (missing(layer) && !missing(variable)) stop("Variable specified without layer.") - result <- sprintf("https://cmems-be.lobelia.earth/api/dataset/%s?variant=detailed-v2", product) %>% - httr::GET() %>% + if (missing(product)) product <- "" + result <- .try_online({ + sprintf("https://cmems-be.lobelia.earth/api/dataset/%s?variant=detailed-v2", product) %>% + httr::GET() + }, "Copernicus") + if (is.null(result)) return(NULL) + + result <- + result %>% httr::content("text") %>% jsonlite::fromJSON() if (!missing(layer)) { diff --git a/R/copernicus_product_metadata.r b/R/copernicus_product_metadata.r index 9e9fe3f..e98fb9e 100644 --- a/R/copernicus_product_metadata.r +++ b/R/copernicus_product_metadata.r @@ -4,7 +4,8 @@ #' for specific Copernicus marine products #' #' @inheritParams copernicus_download_motu -#' @return Returns a named `list` with info about the requested `product`. +#' @return Returns a named `list` with info about the requested `product`. Returns `NULL` +#' when contacting Copernicus fails. #' @rdname copernicus_product_metadata #' @name copernicus_product_metadata #' @family product-functions @@ -16,8 +17,13 @@ #' @export copernicus_product_metadata <- function(product) { meta_data <- - sprintf("https://cmems-be.lobelia.earth/api/metadata/%s", product) %>% - httr::GET() %>% + .try_online({ + sprintf("https://cmems-be.lobelia.earth/api/metadata/%s", product) %>% + httr::GET() + }, "Copernicus") + if (is.null(meta_data)) return(NULL) + meta_data <- + meta_data %>% httr::content() %>% xml2::as_list() return(meta_data) diff --git a/R/copernicus_products_list.r b/R/copernicus_products_list.r index 2fb9f93..df654ff 100644 --- a/R/copernicus_products_list.r +++ b/R/copernicus_products_list.r @@ -8,7 +8,8 @@ #' @param info_type One of `"list"` (default) or `"meta"`. `"list"` returns the actual list #' whereas `"meta"` returns meta information for the executed query (e.g. number of hits). #' @return Returns a `tibble` of products available from or -#' a named `list` when `info_type = "meta"`. +#' a named `list` when `info_type = "meta"`. Returns `NULL` in case on-line services are +#' unavailable. #' @rdname copernicus_products_list #' @name copernicus_products_list #' @family product-functions @@ -26,12 +27,15 @@ copernicus_products_list <- function(..., info_type = c("list", "meta")) { payload <- .payload_data_list payload_mod <- list(...) payload[names(payload_mod)] <- payload_mod - result <- + result <- .try_online({ httr::POST( "https://cmems-be.lobelia.earth/api/datasets", body = payload, - encode = "json" - ) %>% + encode = "json") + }, "Copernicus") + if (is.null(result)) return(NULL) + result <- + result %>% httr::content("text") %>% jsonlite::fromJSON() switch( diff --git a/R/ftp.r b/R/ftp.r index 2cc3c4a..5e3da91 100644 --- a/R/ftp.r +++ b/R/ftp.r @@ -14,8 +14,8 @@ #' @inheritParams copernicus_download_motu #' @return In case of `copernicus_ftp_list` a `tibble` is returned containing available URLs #' (for the specified product and layer) and some meta information is returned. -#' In case of `copernicus_ftp_get` an invisible `NULL` is returned, but the -#' requested file is stored at the `destination` path. +#' In case of `copernicus_ftp_get` an invisible `logical` value is returned, indicating whether +#' the requested file is successfully stored at the `destination` path. #' @rdname copernicus_ftp #' @name copernicus_ftp_list #' @examples @@ -36,10 +36,16 @@ copernicus_ftp_list <- function( name <- NULL # workaround for 'no visible binding global for global variable' dirlist <- function(url){ dir_result <- - httr::GET( - url, - httr::authenticate(user = getOption("CopernicusMarine_uid", ""), password = getOption("CopernicusMarine_pwd", "")), - dirlistonly = TRUE) %>% + .try_online({ + httr::GET( + url, + httr::authenticate(user = getOption("CopernicusMarine_uid", ""), password = getOption("CopernicusMarine_pwd", "")), + dirlistonly = TRUE) + }, "Copernicus") + if (is.null(dir_result)) return(NULL) + + dir_result <- + dir_result %>% `[[`("content") %>% rawToChar() %>% readr::read_fwf( @@ -64,6 +70,7 @@ copernicus_ftp_list <- function( } base_url <- copernicus_product_services(product) + if (length(base_url) == 0) return(NULL) if (missing(layer)) { base_url <- dirname(base_url$ftp)[[1]] @@ -85,12 +92,14 @@ copernicus_ftp_get <- function( if (!dir.exists(destination)) stop("'destination' either doesn't exist or is not a directory!") destination <- file.path(destination, basename(url)) - result <- httr::GET( - url, httr::write_disk(destination, overwrite = overwrite), - if (show_progress) httr::progress() else NULL, - httr::authenticate(user = getOption("CopernicusMarine_uid", ""), - password = getOption("CopernicusMarine_pwd", "")) - ) + result <- + .try_online({ + httr::GET( + url, httr::write_disk(destination, overwrite = overwrite), + if (show_progress) httr::progress() else NULL, + httr::authenticate(user = getOption("CopernicusMarine_uid", ""), + password = getOption("CopernicusMarine_pwd", "")) + )}, "Copernicus") - return(invisible(NULL)) + return(invisible(!is.null(result))) } \ No newline at end of file diff --git a/R/generics.r b/R/generics.r new file mode 100644 index 0000000..452fa58 --- /dev/null +++ b/R/generics.r @@ -0,0 +1,36 @@ +.http_status_ok <- function(x) { + if (dplyr::between(x$status_code, 100, 199)) { + message(sprintf("Unexpected informational response from Copernicus (status %i).", x$status_code)) + return(FALSE) + } + if (dplyr::between(x$status_code, 300, 399)) { + message(sprintf("Unexpected redirection from Copernicus (status %i).", x$status_code)) + return(FALSE) + } + if (dplyr::between(x$status_code, 400, 499)) { + message(sprintf(paste("Copernicus reported a client error (status %i).", + "You may have requested information that is not available,", + "please check your input.", + sep = "\n"), x$status_code)) + return(FALSE) + } + if (dplyr::between(x$status_code, 500, 599)) { + message(sprintf("Copernicus reported a server error (status %i).\nPlease try again later.", x$status_code)) + return(FALSE) + } + if (x$status_code < 100 || x$status_code >= 600) { + message(sprintf("Copernicus responded with unknown status (status %i).", x$status_code)) + return(FALSE) + } + return(TRUE) +} + +.try_online <- function(expr, resource) { + result <- tryCatch(expr, error = function(e) { + message(sprintf("Failed to collect information from %s.\n%s", resource, e$message)) + return(NULL) + }) + if (is.null(result)) return(NULL) + if (!.http_status_ok(result)) return(NULL) + return(result) +} \ No newline at end of file diff --git a/R/wms.r b/R/wms.r index d54b7ac..950d774 100644 --- a/R/wms.r +++ b/R/wms.r @@ -2,6 +2,7 @@ #' #' `r lifecycle::badge('experimental')` Web Map Services are not available for all #' products and layers. Use this function to obtain URLs of WMS services if any. +#' @template wms_template #' @inheritParams copernicus_download_motu #' @return Returns a `tibble` with WMS URLs and descriptors for the specified product. #' @rdname copernicus_wms_details @@ -19,14 +20,16 @@ #' @export copernicus_wms_details <- function(product, layer, variable) { product_details <- copernicus_product_details(product, layer, variable) + if (is.null(product_details)) return(NULL) copwmsinfo <- sf::gdal_utils("info", paste0("WMS:", product_details$wmsUrl), quiet = TRUE) desc <- copwmsinfo %>% stringr::str_match_all("SUBDATASET_(\\d)_DESC=(.*?)\n") + if (length(desc) == 0) return(dplyr::tibble(desc = character(0), url = character(0))) desc <- desc[[1]][,3] url <- copwmsinfo %>% stringr::str_match_all("SUBDATASET_(\\d)_NAME=(.*?)\n") url <- url[[1]][,3] - dplyr::bind_cols(desc = desc, url = url) + return(dplyr::bind_cols(desc = desc, url = url)) } #' Add Copernicus Marine WMS Tiles to a leaflet map @@ -34,6 +37,7 @@ copernicus_wms_details <- function(product, layer, variable) { #' `r lifecycle::badge('experimental')` Create an interactive map with #' `leaflet::leaflet()` and add layers of Copernicus marine WMS data #' to it. +#' @template wms_template #' @param map A map widget object created from [`leaflet::leaflet()`] #' @inheritParams copernicus_download_motu #' @param options Passed on to [`leaflet::addWMSTiles()`]. @@ -44,23 +48,26 @@ copernicus_wms_details <- function(product, layer, variable) { #' @family wms-functions #' @examples #' \donttest{ -#' leaflet::leaflet() %>% -#' leaflet::setView(lng = 3, lat = 54, zoom = 4) %>% -#' leaflet::addProviderTiles("Esri.WorldImagery") %>% -#' addCopernicusWMSTiles( -#' product = "GLOBAL_ANALYSISFORECAST_PHY_001_024", -#' layer = "cmems_mod_glo_phy-thetao_anfc_0.083deg_P1D-m", -#' variable = "thetao" -#' ) +#' if (interactive()) { +#' leaflet::leaflet() %>% +#' leaflet::setView(lng = 3, lat = 54, zoom = 4) %>% +#' leaflet::addProviderTiles("Esri.WorldImagery") %>% +#' addCopernicusWMSTiles( +#' product = "GLOBAL_ANALYSISFORECAST_PHY_001_024", +#' layer = "cmems_mod_glo_phy-thetao_anfc_0.083deg_P1D-m", +#' variable = "thetao") +#' } #' } #' @author Pepijn de Vries #' @export addCopernicusWMSTiles <- function(map, product, layer, variable, options = leaflet::WMSTileOptions(format = "image/png", transparent = TRUE), ...) { + detail <- copernicus_product_details(product, layer, variable) + if (is.null(detail)) return(NULL) leaflet::addWMSTiles( map = map, - baseUrl = copernicus_product_details(product, layer, variable)[["wmsUrl"]], + baseUrl = detail[["wmsUrl"]], layers = variable, options = options, ... @@ -76,6 +83,7 @@ addCopernicusWMSTiles <- function(map, product, layer, variable, #' For that purpose you need to extract and download a specific region in a format #' that can be handled by plots. You can use this function to store a subset of a #' WMS map as a geo-referenced TIFF file. +#' @template wms_template #' @inheritParams copernicus_download_motu #' @param destination File name for the geo-referenced TIFF. #' @param width Width in pixels of the TIFF image. @@ -102,6 +110,7 @@ addCopernicusWMSTiles <- function(map, product, layer, variable, copernicus_wms2geotiff <- function(product, layer, variable, region, destination, width, height) { wms_details <- copernicus_wms_details(product, layer, variable) product_details <- copernicus_product_details(product, layer, variable) + if (is.null(wms_details) || is.null(product_details)) return(NULL) desc <- NULL # <- silences R checks with respect to global bindings... url <- wms_details %>% diff --git a/README.Rmd b/README.Rmd index 3f4825a..24171d8 100644 --- a/README.Rmd +++ b/README.Rmd @@ -84,7 +84,7 @@ copernicus_download_motu( mydata <- stars::read_stars(destination) -plot(mydata["vo"], col = hcl.colors(100), axes = T) +plot(mydata["vo"], col = hcl.colors(100), axes = TRUE) ```

Downloading a complete Copernicus marine product

@@ -92,7 +92,7 @@ plot(mydata["vo"], col = hcl.colors(100), axes = T) If you don't want to subset the data and want the complete set, you can use the File Transfer Protocol (FTP) if that service is available for your product. First you can list files available for a specific product: -```{r, eval = T} +```{r, eval=TRUE} cop_ftp_files <- copernicus_ftp_list("GLOBAL_ANALYSISFORECAST_PHY_001_024", "cmems_mod_glo_phy-cur_anfc_0.083deg_P1D-m") cop_ftp_files ``` @@ -124,6 +124,8 @@ When you want to use WMS tiles in static plots, you could download and store spe as a [geo-referenced tiff](https://en.wikipedia.org/wiki/GeoTIFF) file for future use. Use `copernicus_wms2geotiff` for that purpose. +Note that the WMS functions may not work on systems that don't support GDAL utils. + ### Citing the data you use A Copernicus account comes with several terms of use. One of these is that you @@ -137,7 +139,7 @@ copernicus_cite_product("GLOBAL_ANALYSISFORECAST_PHY_001_024") ## Resources -```{r, eval=TRUE, echo = F} +```{r, eval=TRUE, echo=FALSE} cop_det <- copernicus_product_details("GLOBAL_ANALYSISFORECAST_PHY_001_024") ``` diff --git a/README.md b/README.md index 5e69d07..f9ad80c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ programme and facilitates retrieval of information from ## Why use `{CopernicusMarine}` -Previously, there was only a MOTUS client available for Python. +Previously, there was only a MOTU client available for Python. Therefore, automating Copernicus downloads in R used to require installation of python and its [motuclient](https://pypi.org/project/motuclient/) package. The @@ -96,7 +96,7 @@ copernicus_download_motu( mydata <- stars::read_stars(destination) #> vo, uo, -plot(mydata["vo"], col = hcl.colors(100), axes = T) +plot(mydata["vo"], col = hcl.colors(100), axes = TRUE) ``` ![](man/figures/README-motu-subset-1.png) @@ -112,7 +112,7 @@ your product. First you can list files available for a specific product: ``` r cop_ftp_files <- copernicus_ftp_list("GLOBAL_ANALYSISFORECAST_PHY_001_024", "cmems_mod_glo_phy-cur_anfc_0.083deg_P1D-m") cop_ftp_files -#> # A tibble: 814 x 8 +#> # A tibble: 818 x 8 #> flags len protocol size month day time url #> #> 1 -rw-rw-r-- 1 ftp 1937968861 Oct 14 06:10 ftp://nrt.cmems-du.eu~ @@ -125,7 +125,7 @@ cop_ftp_files #> 8 -rw-rw-r-- 1 ftp 1937954892 Oct 14 06:10 ftp://nrt.cmems-du.eu~ #> 9 -rw-rw-r-- 1 ftp 1937964478 Oct 14 06:09 ftp://nrt.cmems-du.eu~ #> 10 -rw-rw-r-- 1 ftp 1937962443 Oct 14 06:06 ftp://nrt.cmems-du.eu~ -#> # ... with 804 more rows +#> # ... with 808 more rows ``` Downloading the first file can be done with @@ -163,6 +163,9 @@ store specific regions of the tiles as a [geo-referenced tiff](https://en.wikipedia.org/wiki/GeoTIFF) file for future use. Use `copernicus_wms2geotiff` for that purpose. +Note that the WMS functions may not work on systems that don’t support +GDAL utils. + ### Citing the data you use A Copernicus account comes with several terms of use. One of these is @@ -175,7 +178,7 @@ code: ``` r copernicus_cite_product("GLOBAL_ANALYSISFORECAST_PHY_001_024") #> $doi -#> [1] "Global Ocean 1/12° Physics Analysis and Forecast updated Daily - GLOBAL_ANALYSISFORECAST_PHY_001_024 (2016-10-14). DOI:10.48670/moi-00016" +#> [1] "E.U. Copernicus Marine Service Information; Global Ocean 1/12° Physics Analysis and Forecast updated Daily - GLOBAL_ANALYSISFORECAST_PHY_001_024 (2016-10-14). DOI:10.48670/moi-00016" ``` ## Resources diff --git a/man-roxygen/wms_template.r b/man-roxygen/wms_template.r new file mode 100644 index 0000000..d517d10 --- /dev/null +++ b/man-roxygen/wms_template.r @@ -0,0 +1,2 @@ +#' @note WMS functions don't work on systems that don't support GDAL utils +NULL diff --git a/man/addCopernicusWMSTiles.Rd b/man/addCopernicusWMSTiles.Rd index c42a6e7..3cb9180 100644 --- a/man/addCopernicusWMSTiles.Rd +++ b/man/addCopernicusWMSTiles.Rd @@ -36,16 +36,20 @@ Returns an updated \code{map} \code{leaflet::leaflet()} and add layers of Copernicus marine WMS data to it. } +\note{ +WMS functions don't work on systems that don't support GDAL utils +} \examples{ \donttest{ -leaflet::leaflet() \%>\% - leaflet::setView(lng = 3, lat = 54, zoom = 4) \%>\% - leaflet::addProviderTiles("Esri.WorldImagery") \%>\% - addCopernicusWMSTiles( - product = "GLOBAL_ANALYSISFORECAST_PHY_001_024", - layer = "cmems_mod_glo_phy-thetao_anfc_0.083deg_P1D-m", - variable = "thetao" - ) +if (interactive()) { + leaflet::leaflet() \%>\% + leaflet::setView(lng = 3, lat = 54, zoom = 4) \%>\% + leaflet::addProviderTiles("Esri.WorldImagery") \%>\% + addCopernicusWMSTiles( + product = "GLOBAL_ANALYSISFORECAST_PHY_001_024", + layer = "cmems_mod_glo_phy-thetao_anfc_0.083deg_P1D-m", + variable = "thetao") +} } } \seealso{ diff --git a/man/copernicus_cite_product.Rd b/man/copernicus_cite_product.Rd index 62e1f52..25ee1ea 100644 --- a/man/copernicus_cite_product.Rd +++ b/man/copernicus_cite_product.Rd @@ -11,7 +11,7 @@ copernicus_cite_product(product) Can be obtained with \code{\link{copernicus_products_list}}.} } \value{ -Returns a list of character strings. The first element is always the product title, id and doi. +Returns a vector of character strings. The first element is always the product title, id and doi. Remaining elements are other associated references. Note that the remaining references are returned as listed at Copernicus. Note that the citing formatting does not appear to be standardised. } diff --git a/man/copernicus_download_motu.Rd b/man/copernicus_download_motu.Rd index 3d8daf1..b01779f 100644 --- a/man/copernicus_download_motu.Rd +++ b/man/copernicus_download_motu.Rd @@ -54,7 +54,8 @@ overwritten when the exist. Instead an error will be thrown if this is the case. \code{TRUE}, existing files will be overwritten.} } \value{ -Returns \code{NULL} invisibly but saves the requested file at the \code{destination} when successful. +Returns a \code{logical} value invisibly indicating whether the requested file was +successfully stored at the \code{destination}. } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}} Subset and download a specific marine product from Copernicus. diff --git a/man/copernicus_ftp.Rd b/man/copernicus_ftp.Rd index 402b7cd..10caa6e 100644 --- a/man/copernicus_ftp.Rd +++ b/man/copernicus_ftp.Rd @@ -48,8 +48,8 @@ overwritten when the exist. Instead an error will be thrown if this is the case. \value{ In case of \code{copernicus_ftp_list} a \code{tibble} is returned containing available URLs (for the specified product and layer) and some meta information is returned. -In case of \code{copernicus_ftp_get} an invisible \code{NULL} is returned, but the -requested file is stored at the \code{destination} path. +In case of \code{copernicus_ftp_get} an invisible \code{logical} value is returned, indicating whether +the requested file is successfully stored at the \code{destination} path. } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}} Full marine data sets can be downloaded using the diff --git a/man/copernicus_product_metadata.Rd b/man/copernicus_product_metadata.Rd index fe2fae7..9d80fe8 100644 --- a/man/copernicus_product_metadata.Rd +++ b/man/copernicus_product_metadata.Rd @@ -11,7 +11,8 @@ copernicus_product_metadata(product) Can be obtained with \code{\link{copernicus_products_list}}.} } \value{ -Returns a named \code{list} with info about the requested \code{product}. +Returns a named \code{list} with info about the requested \code{product}. Returns \code{NULL} +when contacting Copernicus fails. } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}} Collect meta information, such as vocabularies used, diff --git a/man/copernicus_products_list.Rd b/man/copernicus_products_list.Rd index c93deb5..91ae1c1 100644 --- a/man/copernicus_products_list.Rd +++ b/man/copernicus_products_list.Rd @@ -15,7 +15,8 @@ whereas \code{"meta"} returns meta information for the executed query (e.g. numb } \value{ Returns a \code{tibble} of products available from \url{https://data.marine.copernicus.eu} or -a named \code{list} when \code{info_type = "meta"}. +a named \code{list} when \code{info_type = "meta"}. Returns \code{NULL} in case on-line services are +unavailable. } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}} Collect a list of products and some brief diff --git a/man/copernicus_wms2geotiff.Rd b/man/copernicus_wms2geotiff.Rd index 17a9a67..7f3e9b1 100644 --- a/man/copernicus_wms2geotiff.Rd +++ b/man/copernicus_wms2geotiff.Rd @@ -45,6 +45,9 @@ For that purpose you need to extract and download a specific region in a format that can be handled by plots. You can use this function to store a subset of a WMS map as a geo-referenced TIFF file. } +\note{ +WMS functions don't work on systems that don't support GDAL utils +} \examples{ \donttest{ destination <- tempfile("wms", fileext = ".tiff") diff --git a/man/copernicus_wms_details.Rd b/man/copernicus_wms_details.Rd index 7e74f85..d6eeb08 100644 --- a/man/copernicus_wms_details.Rd +++ b/man/copernicus_wms_details.Rd @@ -22,6 +22,9 @@ Returns a \code{tibble} with WMS URLs and descriptors for the specified product. \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} Web Map Services are not available for all products and layers. Use this function to obtain URLs of WMS services if any. } +\note{ +WMS functions don't work on systems that don't support GDAL utils +} \examples{ \donttest{ copernicus_wms_details( diff --git a/man/figures/README-leaflet-1.png b/man/figures/README-leaflet-1.png index ada9578..9e89081 100644 Binary files a/man/figures/README-leaflet-1.png and b/man/figures/README-leaflet-1.png differ diff --git a/tests/testthat/helper.r b/tests/testthat/helper.r index 772472c..060ef14 100644 --- a/tests/testthat/helper.r +++ b/tests/testthat/helper.r @@ -1,15 +1,20 @@ -has_internet <- function() { - if( - tryCatch( - "https://data.marine.copernicus.eu" %>% - httr::GET(httr::timeout(1)) %>% - httr::http_error(), - error = function(e) TRUE) - ) skip("No internet connection") -} - has_account_details <- function() { if (is.null(getOption("CopernicusMarine_uid")) || is.null(getOption("CopernicusMarine_pwd"))) { skip("No Copernicus account details found") } } + +has_gdal_utils <- function() { + result <- tryCatch({ + cp <- + copernicus_wms_details( + product = "GLOBAL_ANALYSISFORECAST_PHY_001_024", + layer = "cmems_mod_glo_phy-thetao_anfc_0.083deg_P1D-m", + variable = "thetao" + ) + is.data.frame(cp) && nrow(cp) > 0 + }, error = function(e) FALSE) + if (!result) { + skip("No functional GDAL utils available") + } +} \ No newline at end of file diff --git a/tests/testthat/test_ftp.r b/tests/testthat/test_ftp.r index 70af92c..14a6c4b 100644 --- a/tests/testthat/test_ftp.r +++ b/tests/testthat/test_ftp.r @@ -1,5 +1,6 @@ test_that("Copernicus files can be downloaded via FTP", { - has_internet() + skip_on_cran() + skip_if_offline("data.marine.copernicus.eu") has_account_details() expect_error({ cop_ftp_files <- copernicus_ftp_list("GLOBAL_OMI_WMHE_heattrp") diff --git a/tests/testthat/test_motu.r b/tests/testthat/test_motu.r index eca82e5..7021e2e 100644 --- a/tests/testthat/test_motu.r +++ b/tests/testthat/test_motu.r @@ -1,6 +1,7 @@ test_that("Products can be listed", { + skip_on_cran() has_account_details() - has_internet() + skip_if_offline("data.marine.copernicus.eu") expect_true({ pds <- copernicus_products_list() is.data.frame(pds) && nrow(pds) > 0 @@ -8,8 +9,9 @@ test_that("Products can be listed", { }) test_that("Product details make sence", { + skip_on_cran() has_account_details() - has_internet() + skip_if_offline("data.marine.copernicus.eu") id <- "GLOBAL_ANALYSISFORECAST_PHY_001_024" expect_true({ pd <- copernicus_product_details(id) @@ -18,16 +20,18 @@ test_that("Product details make sence", { }) test_that("Product details can't have variable without layer", { + skip_on_cran() has_account_details() - has_internet() + skip_if_offline("data.marine.copernicus.eu") expect_error({ copernicus_product_details("GLOBAL_ANALYSISFORECAST_PHY_001_024", variable = "thetao") }) }) test_that("Product meta info make sence", { + skip_on_cran() has_account_details() - has_internet() + skip_if_offline("data.marine.copernicus.eu") id <- "GLOBAL_ANALYSISFORECAST_PHY_001_024" expect_true({ pd <- copernicus_product_metadata(id) @@ -36,22 +40,25 @@ test_that("Product meta info make sence", { }) test_that("Motu download produces valid ncdf file", { + skip_on_cran() has_account_details() - has_internet() + skip_if_offline("data.marine.copernicus.eu") expect_true({ destination <- tempfile("copernicus", fileext = ".nc") - copernicus_download_motu( - destination = destination, - product = "GLOBAL_ANALYSISFORECAST_PHY_001_024", - layer = "cmems_mod_glo_phy-cur_anfc_0.083deg_P1D-m", - variable = "sea_water_velocity", - output = "netcdf", - region = c(-1, 50, 10, 55), - timerange = c("2021-01-01", "2021-01-02"), - verticalrange = c(0, 2), - sub_variables = c("uo", "vo") - ) - test_file <- stars::read_stars(destination) - "stars" %in% class(test_file) + suppressMessages({ + copernicus_download_motu( + destination = destination, + product = "GLOBAL_ANALYSISFORECAST_PHY_001_024", + layer = "cmems_mod_glo_phy-cur_anfc_0.083deg_P1D-m", + variable = "sea_water_velocity", + output = "netcdf", + region = c(-1, 50, 10, 55), + timerange = c("2021-01-01", "2021-01-02"), + verticalrange = c(0, 2), + sub_variables = c("uo", "vo") + ) + capture.output(test_file <- stars::read_stars(destination)) + "stars" %in% class(test_file) + }) }) }) diff --git a/tests/testthat/test_wms.r b/tests/testthat/test_wms.r index 47640b7..b4e8504 100644 --- a/tests/testthat/test_wms.r +++ b/tests/testthat/test_wms.r @@ -1,5 +1,7 @@ test_that("Copernicus WMS tile can be added to a map", { - has_internet() + skip_on_cran() + skip_if_offline("data.marine.copernicus.eu") + has_gdal_utils() testthat::expect_error({ leaflet::leaflet() %>% addCopernicusWMSTiles( @@ -10,21 +12,10 @@ test_that("Copernicus WMS tile can be added to a map", { }, NA) }) -test_that("WMS services can be listed", { - has_internet() - expect_true({ - cp <- - copernicus_wms_details( - product = "GLOBAL_ANALYSISFORECAST_PHY_001_024", - layer = "cmems_mod_glo_phy-thetao_anfc_0.083deg_P1D-m", - variable = "thetao" - ) - is.data.frame(cp) && nrow(cp) > 0 - }) -}) - test_that("Copernicus WMS tile can be stored as valid geoTIFF", { - has_internet() + skip_on_cran() + skip_if_offline("data.marine.copernicus.eu") + has_gdal_utils() expect_error({ destination <- tempfile("wms", fileext = ".tiff") copernicus_wms2geotiff(