From dbb48d29d9570cba8c4dcf0220f5c4bd7fd73b4f Mon Sep 17 00:00:00 2001 From: dieghernan Date: Mon, 13 Feb 2023 09:05:49 +0000 Subject: [PATCH] Prepare for CRAN --- .github/workflows/cran-status.yaml | 3 +- CITATION.cff | 4 +- DESCRIPTION | 2 +- NEWS.md | 20 +- R/gisco_bulk_download.R | 312 ++++----- R/gisco_get_airports.R | 294 ++++---- R/gisco_get_coastallines.R | 190 +++--- R/gisco_get_countries.R | 426 ++++++------ R/gisco_get_grid.R | 426 ++++++------ R/gisco_get_healthcare.R | 180 ++--- R/gisco_get_lau.R | 624 ++++++++--------- R/gisco_get_nuts.R | 342 +++++----- R/gisco_get_units.R | 740 ++++++++++----------- R/gisco_get_urban_audit.R | 206 +++--- R/utils_downloads.R | 6 +- R/utils_names.R | 213 +++--- README.Rmd | 3 - README.md | 2 +- codemeta.json | 4 +- data/gisco_countrycode.rda | Bin 6376 -> 5060 bytes data/gisco_db.rda | Bin 1001 -> 976 bytes data/tgs00026.rda | Bin 5015 -> 4816 bytes giscoR.Rproj | 1 + img/README-thematic-1.png | Bin 784293 -> 784356 bytes tests/testthat/test-gisco_get_healthcare.R | 18 +- vignettes/giscoR-1.png | Bin 229659 -> 229661 bytes 26 files changed, 2011 insertions(+), 2005 deletions(-) diff --git a/.github/workflows/cran-status.yaml b/.github/workflows/cran-status.yaml index be22372c..2c8d77e5 100644 --- a/.github/workflows/cran-status.yaml +++ b/.github/workflows/cran-status.yaml @@ -20,5 +20,4 @@ jobs: issue-assignees: "dieghernan" # Create an issue if one or more of the following # statuses are reported on the check report. - status-types: "WARNING,ERROR" - \ No newline at end of file + statuses: "WARNING,ERROR" diff --git a/CITATION.cff b/CITATION.cff index 4f0d83b7..5a646aca 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -8,7 +8,7 @@ message: 'To cite package "giscoR" in publications use:' type: software license: GPL-3.0-only title: 'giscoR: Download Map Data from GISCO API - Eurostat' -version: 0.3.2.9000 +version: 0.3.3 doi: 10.5281/zenodo.4317946 abstract: Tools to download data from the GISCO (Geographic Information System of the Commission) Eurostat database . Global @@ -31,7 +31,7 @@ preferred-citation: affiliation: rOpenGov doi: 10.5281/zenodo.4317946 year: '2023' - version: 0.3.2.9000 + version: 0.3.3 url: https://ropengov.github.io/giscoR/ abstract: Tools to download data from the GISCO (Geographic Information System of the Commission) Eurostat database . Global diff --git a/DESCRIPTION b/DESCRIPTION index 4a64450c..ed291076 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: giscoR Title: Download Map Data from GISCO API - Eurostat -Version: 0.3.2.9000 +Version: 0.3.3 Authors@R: c( person("Diego", "Hernangómez", , "diego.hernangomezherrero@gmail.com", role = c("aut", "cre", "cph"), comment = c(ORCID = "0000-0001-8457-4658", affiliation = "rOpenGov")), diff --git a/NEWS.md b/NEWS.md index 59cf3200..99f4d838 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,6 @@ -# giscoR (development version) - -- Fix broken urls on - `gisco_get_healthcare()` (#51). +# giscoR 0.3.3 +- Fix broken urls on `gisco_get_healthcare()` (#51). # giscoR 0.3.2 @@ -26,9 +24,14 @@ # giscoR 0.3.0 -- Now **giscoR** is part of [rOpenGov](https://ropengov.org/). Repo has been transferred. -- Caching improvements: new function `gisco_set_cache_dir()` based on `rappdirs::user_cache_dir()`. Now the `cache_dir` path is stored and it is not necessary to set it up again on a new session. Also added `gisco_clear_cache()`. -- Fix an error when `cache = FALSE`. Now files are loaded instead throwing an error. +- Now **giscoR** is part of [rOpenGov](https://ropengov.org/). Repo has been + transferred. +- Caching improvements: new function `gisco_set_cache_dir()` based on + `rappdirs::user_cache_dir()`. Now the `cache_dir` path is stored and it is + not necessary to set it up again on a new session. Also added + `gisco_clear_cache()`. +- Fix an error when `cache = FALSE`. Now files are loaded instead throwing an + error. - New tests with `testthat`. - Update on docs. New examples - Refactor documents and codes for the previous `gisco_get` doc. @@ -84,7 +87,8 @@ - `gisco_get_ports()` - `gisco_get_units()` -- Now `gisco_get_countries()` and `gisco_get_nuts()` uses `gisco_get_units()` for individual files, making the call much faster. +- Now `gisco_get_countries()` and `gisco_get_nuts()` uses `gisco_get_units()` + for individual files, making the call much faster. # giscoR 0.1.1 diff --git a/R/gisco_bulk_download.R b/R/gisco_bulk_download.R index 3b6b449f..9e210c70 100644 --- a/R/gisco_bulk_download.R +++ b/R/gisco_bulk_download.R @@ -1,156 +1,156 @@ -#' Bulk download from GISCO API -#' -#' @concept political -#' -#' @family political -#' -#' @description -#' Downloads zipped data from GISCO and extract them on the `cache_dir` folder. -#' -#' @return Silent function. -#' -#' @param year Release year of the file. See Details -#' -#' @param id_giscoR Type of dataset to be downloaded. Values supported are: -#' * "coastallines" -#' * "communes" -#' * "countries" -#' * "lau" -#' * "nuts" -#' * "urban_audit" -#' -#' @inheritParams gisco_get_countries -#' -#' @inheritSection gisco_get_countries About caching -#' -#' @param ext Extension of the file(s) to be downloaded. Formats available are -#' "geojson", "shp", "svg", "json", "gdb". See **Details**. -#' -#' @param recursive Tries to unzip recursively the zip files (if any) included -#' in the initial bulk download (case of `ext = "shp"`). -#' -#' @details -#' -#' See the years available in the corresponding functions: -#' * [gisco_get_coastallines()] -#' * [gisco_get_communes()] -#' * [gisco_get_countries()] -#' * [gisco_get_lau()] -#' * [gisco_get_nuts()] -#' * [gisco_get_urban_audit()] -#' -#' -#' The usual extension used across **giscoR** is "geojson", -#' however other formats are already available on GISCO. -#' -#' -#' @source -#' -#' -#' @examples -#' \dontrun{ -#' -#' # Countries 2016 - It would take some time -#' gisco_bulk_download(id_giscoR = "countries", resolution = "60") -#' } -#' @export -gisco_bulk_download <- function(id_giscoR = "countries", - year = "2016", - cache_dir = NULL, - update_cache = FALSE, - verbose = FALSE, - resolution = "10", - ext = "geojson", - recursive = TRUE) { - valid <- c( - "coastallines", - "communes", - "countries", - "lau", - "nuts", - "urban_audit" - ) - alias <- - c("coastline", "communes", "countries", "lau", "nuts", "urau") - - if (!(id_giscoR %in% valid)) { - stop( - "id_giscoR values should be one of ", - paste0("'", sort(valid), "'", collapse = ",") - ) - } - - availext <- c("geojson", "shp", "svg", "json", "gdb") - if (!(ext %in% availext)) { - stop("ext should be one of ", paste0(availext, collapse = ", ")) - } - - # Standard parameters for the call - year <- as.character(year) - epsg <- "4326" - spatialtype <- "RG" - level <- "all" - if (id_giscoR == "urban_audit" & year < "2014") { - level <- "CITY" - } - - routes <- gsc_api_url( - id_giscoR, - year, - epsg, - resolution, - spatialtype, - "geojson", - nuts_level = "all", - level = level, - verbose = verbose - ) - - api_entry <- unlist(strsplit(routes, "/geojson/"))[1] - remain <- unlist(strsplit(routes, "/geojson/"))[2] - - api_entry <- file.path(api_entry, "download") - getalias <- alias[valid == id_giscoR] - - # Clean names - remain2 <- gsub(spatialtype, "", remain) - remain2 <- gsub(epsg, "", remain2) - remain2 <- gsub(year, "", remain2) - remain2 <- gsub(".geojson", "", remain2) - remain2 <- gsub(level, "", remain2) - remain2 <- (unlist(strsplit(remain2, "_")))[-1] - remain2 <- tolower(paste0(remain2, collapse = "")) - - # Create url - zipname <- paste0( - "ref-", - getalias, - "-", - year, - "-", - remain2, - ".", - ext, - ".zip" - ) - url <- file.path(api_entry, zipname) - - - destfile <- gsc_api_cache( - url, - zipname, cache_dir, update_cache, - verbose - ) - - # Clean cache dir name for extracting - unzip_dir <- gsub(paste0("/", zipname), "", destfile) - - # Unzip - gsc_unzip( - destfile, - unzip_dir, ext, - recursive, - verbose, - update_cache - ) -} +#' Bulk download from GISCO API +#' +#' @concept political +#' +#' @family political +#' +#' @description +#' Downloads zipped data from GISCO and extract them on the `cache_dir` folder. +#' +#' @return Silent function. +#' +#' @param year Release year of the file. See Details +#' +#' @param id_giscoR Type of dataset to be downloaded. Values supported are: +#' * "coastallines" +#' * "communes" +#' * "countries" +#' * "lau" +#' * "nuts" +#' * "urban_audit" +#' +#' @inheritParams gisco_get_countries +#' +#' @inheritSection gisco_get_countries About caching +#' +#' @param ext Extension of the file(s) to be downloaded. Formats available are +#' "geojson", "shp", "svg", "json", "gdb". See **Details**. +#' +#' @param recursive Tries to unzip recursively the zip files (if any) included +#' in the initial bulk download (case of `ext = "shp"`). +#' +#' @details +#' +#' See the years available in the corresponding functions: +#' * [gisco_get_coastallines()] +#' * [gisco_get_communes()] +#' * [gisco_get_countries()] +#' * [gisco_get_lau()] +#' * [gisco_get_nuts()] +#' * [gisco_get_urban_audit()] +#' +#' +#' The usual extension used across **giscoR** is "geojson", +#' however other formats are already available on GISCO. +#' +#' +#' @source +#' +#' +#' @examples +#' \dontrun{ +#' +#' # Countries 2016 - It would take some time +#' gisco_bulk_download(id_giscoR = "countries", resolution = "60") +#' } +#' @export +gisco_bulk_download <- function(id_giscoR = "countries", + year = "2016", + cache_dir = NULL, + update_cache = FALSE, + verbose = FALSE, + resolution = "10", + ext = "geojson", + recursive = TRUE) { + valid <- c( + "coastallines", + "communes", + "countries", + "lau", + "nuts", + "urban_audit" + ) + alias <- + c("coastline", "communes", "countries", "lau", "nuts", "urau") + + if (!(id_giscoR %in% valid)) { + stop( + "id_giscoR values should be one of ", + paste0("'", sort(valid), "'", collapse = ",") + ) + } + + availext <- c("geojson", "shp", "svg", "json", "gdb") + if (!(ext %in% availext)) { + stop("ext should be one of ", paste0(availext, collapse = ", ")) + } + + # Standard parameters for the call + year <- as.character(year) + epsg <- "4326" + spatialtype <- "RG" + level <- "all" + if (id_giscoR == "urban_audit" && year < "2014") { + level <- "CITY" + } + + routes <- gsc_api_url( + id_giscoR, + year, + epsg, + resolution, + spatialtype, + "geojson", + nuts_level = "all", + level = level, + verbose = verbose + ) + + api_entry <- unlist(strsplit(routes, "/geojson/"))[1] + remain <- unlist(strsplit(routes, "/geojson/"))[2] + + api_entry <- file.path(api_entry, "download") + getalias <- alias[valid == id_giscoR] + + # Clean names + remain2 <- gsub(spatialtype, "", remain) + remain2 <- gsub(epsg, "", remain2) + remain2 <- gsub(year, "", remain2) + remain2 <- gsub(".geojson", "", remain2) + remain2 <- gsub(level, "", remain2) + remain2 <- (unlist(strsplit(remain2, "_")))[-1] + remain2 <- tolower(paste0(remain2, collapse = "")) + + # Create url + zipname <- paste0( + "ref-", + getalias, + "-", + year, + "-", + remain2, + ".", + ext, + ".zip" + ) + url <- file.path(api_entry, zipname) + + + destfile <- gsc_api_cache( + url, + zipname, cache_dir, update_cache, + verbose + ) + + # Clean cache dir name for extracting + unzip_dir <- gsub(paste0("/", zipname), "", destfile) + + # Unzip + gsc_unzip( + destfile, + unzip_dir, ext, + recursive, + verbose, + update_cache + ) +} diff --git a/R/gisco_get_airports.R b/R/gisco_get_airports.R index 86469656..5e81992e 100644 --- a/R/gisco_get_airports.R +++ b/R/gisco_get_airports.R @@ -1,147 +1,147 @@ -#' Get location of airports and ports from GISCO API -#' -#' Loads a `sf` object from GISCO API or your local library. -#' -#' @concept infrastructure -#' @family infrastructure -#' -#' @return A `POINT` object on EPSG:4326. -#' -#' @param year Year of reference. Only year available right now is "2013". -#' -#' @inheritParams gisco_get_countries -#' -#' @inheritSection gisco_get_countries About caching -#' @source -#' -#' -#' -#' @details -#' [gisco_get_airports()] refer to Europe. All shapefiles provided in -#' [EPSG:4326](https://epsg.io/4326). -#' -#' @examplesIf gisco_check_access() -#' \donttest{ -#' library(sf) -#' -#' Greece <- gisco_get_countries(country = "EL", resolution = "1") -#' AirP_GC <- gisco_get_airports(country = "EL") -#' AirP_GC <- st_transform(AirP_GC, st_crs(Greece)) -#' -#' library(ggplot2) -#' -#' -#' ggplot(Greece) + -#' geom_sf(fill = "grey80") + -#' geom_sf(data = AirP_GC, color = "blue") + -#' labs( -#' title = "Airports on Greece", -#' shape = NULL, -#' color = NULL, -#' caption = gisco_attributions() -#' ) -#' -#' -#' ############################## -#' # Plot ports # -#' ############################## -#' -#' ports <- gisco_get_ports() -#' coast <- gisco_get_coastallines(year = 2013) -#' -#' # To Equal Earth projection :) -#' -#' library(sf) -#' coast <- st_transform(coast, 8857) -#' ports <- st_transform(ports, st_crs(coast)) -#' -#' -#' ggplot(coast) + -#' geom_sf(fill = "#F6E1B9", color = "#0978AB") + -#' geom_sf(data = ports, fill = "red", shape = 21) + -#' theme_void() + -#' theme( -#' panel.background = element_rect(fill = "#C6ECFF"), -#' panel.grid = element_blank(), -#' plot.title = element_text(face = "bold", hjust = 0.5), -#' plot.subtitle = element_text(face = "italic", hjust = 0.5) -#' ) + -#' labs( -#' title = "Ports Worldwide", subtitle = "Year 2013", -#' caption = "(c) European Union, 1995 - today" -#' ) -#' } -#' @export -gisco_get_airports <- function(year = "2013", - country = NULL, - cache_dir = NULL, - update_cache = FALSE, - verbose = FALSE) { - year <- as.character(year) - if (!(year %in% c("2013"))) { - stop("Year should be 2013") - } - - if (year == "2013") { - url <- paste0( - "https://ec.europa.eu/eurostat/cache/GISCO/", - "geodatafiles/Airports-2013-SHP.zip" - ) - } - - data_sf <- gsc_load_shp(url, cache_dir, verbose, update_cache) - data_sf <- sf::st_make_valid(data_sf) - - # Normalize to lonlat - data_sf <- sf::st_transform(data_sf, 4326) - - - if (!is.null(country) & "CNTR_CODE" %in% names(data_sf)) { - country <- gsc_helper_countrynames(country, "eurostat") - data_sf <- data_sf[data_sf$CNTR_CODE %in% country, ] - } - return(data_sf) -} - -#' @rdname gisco_get_airports -#' -#' @details -#' -#' [gisco_get_ports()] adds a new field `CNTR_ISO2` to the original data -#' identifying the country of the port. Worldwide information available. -#' The port codes are aligned with -#' [UN/LOCODE](https://unece.org/trade/uncefact/unlocode) standard. -#' -#' @export -gisco_get_ports <- function(year = "2013", - country = NULL, - cache_dir = NULL, - update_cache = FALSE, - verbose = FALSE) { - year <- as.character(year) - if (!(year %in% c("2013"))) { - stop("Year should be 2013") - } - - if (year == "2013") { - url <- paste0( - "https://ec.europa.eu/eurostat/cache/GISCO/", - "geodatafiles/PORT_2013_SH.zip" - ) - } - - data_sf <- gsc_load_shp(url, cache_dir, verbose, update_cache) - data_sf <- sf::st_make_valid(data_sf) - - # Normalize to lonlat - data_sf <- sf::st_transform(data_sf, 4326) - - # Add ISO2 country - data_sf$CNTR_ISO2 <- substr(data_sf$PORT_ID, 1, 2) - - if (!is.null(country) & "PORT_ID" %in% names(data_sf)) { - country <- gsc_helper_countrynames(country, "iso2c") - data_sf <- data_sf[data_sf$CNTR_ISO2 %in% country, ] - } - return(data_sf) -} +#' Get location of airports and ports from GISCO API +#' +#' Loads a `sf` object from GISCO API or your local library. +#' +#' @concept infrastructure +#' @family infrastructure +#' +#' @return A `POINT` object on EPSG:4326. +#' +#' @param year Year of reference. Only year available right now is "2013". +#' +#' @inheritParams gisco_get_countries +#' +#' @inheritSection gisco_get_countries About caching +#' @source +#' +#' +#' +#' @details +#' [gisco_get_airports()] refer to Europe. All shapefiles provided in +#' [EPSG:4326](https://epsg.io/4326). +#' +#' @examplesIf gisco_check_access() +#' \donttest{ +#' library(sf) +#' +#' Greece <- gisco_get_countries(country = "EL", resolution = "1") +#' AirP_GC <- gisco_get_airports(country = "EL") +#' AirP_GC <- st_transform(AirP_GC, st_crs(Greece)) +#' +#' library(ggplot2) +#' +#' +#' ggplot(Greece) + +#' geom_sf(fill = "grey80") + +#' geom_sf(data = AirP_GC, color = "blue") + +#' labs( +#' title = "Airports on Greece", +#' shape = NULL, +#' color = NULL, +#' caption = gisco_attributions() +#' ) +#' +#' +#' ############################## +#' # Plot ports # +#' ############################## +#' +#' ports <- gisco_get_ports() +#' coast <- gisco_get_coastallines(year = 2013) +#' +#' # To Equal Earth projection :) +#' +#' library(sf) +#' coast <- st_transform(coast, 8857) +#' ports <- st_transform(ports, st_crs(coast)) +#' +#' +#' ggplot(coast) + +#' geom_sf(fill = "#F6E1B9", color = "#0978AB") + +#' geom_sf(data = ports, fill = "red", shape = 21) + +#' theme_void() + +#' theme( +#' panel.background = element_rect(fill = "#C6ECFF"), +#' panel.grid = element_blank(), +#' plot.title = element_text(face = "bold", hjust = 0.5), +#' plot.subtitle = element_text(face = "italic", hjust = 0.5) +#' ) + +#' labs( +#' title = "Ports Worldwide", subtitle = "Year 2013", +#' caption = "(c) European Union, 1995 - today" +#' ) +#' } +#' @export +gisco_get_airports <- function(year = "2013", + country = NULL, + cache_dir = NULL, + update_cache = FALSE, + verbose = FALSE) { + year <- as.character(year) + if (!(year %in% c("2013"))) { + stop("Year should be 2013") + } + + if (year == "2013") { + url <- paste0( + "https://ec.europa.eu/eurostat/cache/GISCO/", + "geodatafiles/Airports-2013-SHP.zip" + ) + } + + data_sf <- gsc_load_shp(url, cache_dir, verbose, update_cache) + data_sf <- sf::st_make_valid(data_sf) + + # Normalize to lonlat + data_sf <- sf::st_transform(data_sf, 4326) + + + if (!is.null(country) && "CNTR_CODE" %in% names(data_sf)) { + country <- gsc_helper_countrynames(country, "eurostat") + data_sf <- data_sf[data_sf$CNTR_CODE %in% country, ] + } + return(data_sf) +} + +#' @rdname gisco_get_airports +#' +#' @details +#' +#' [gisco_get_ports()] adds a new field `CNTR_ISO2` to the original data +#' identifying the country of the port. Worldwide information available. +#' The port codes are aligned with +#' [UN/LOCODE](https://unece.org/trade/uncefact/unlocode) standard. +#' +#' @export +gisco_get_ports <- function(year = "2013", + country = NULL, + cache_dir = NULL, + update_cache = FALSE, + verbose = FALSE) { + year <- as.character(year) + if (!(year %in% c("2013"))) { + stop("Year should be 2013") + } + + if (year == "2013") { + url <- paste0( + "https://ec.europa.eu/eurostat/cache/GISCO/", + "geodatafiles/PORT_2013_SH.zip" + ) + } + + data_sf <- gsc_load_shp(url, cache_dir, verbose, update_cache) + data_sf <- sf::st_make_valid(data_sf) + + # Normalize to lonlat + data_sf <- sf::st_transform(data_sf, 4326) + + # Add ISO2 country + data_sf$CNTR_ISO2 <- substr(data_sf$PORT_ID, 1, 2) + + if (!is.null(country) && "PORT_ID" %in% names(data_sf)) { + country <- gsc_helper_countrynames(country, "iso2c") + data_sf <- data_sf[data_sf$CNTR_ISO2 %in% country, ] + } + return(data_sf) +} diff --git a/R/gisco_get_coastallines.R b/R/gisco_get_coastallines.R index b4069191..68486b55 100644 --- a/R/gisco_get_coastallines.R +++ b/R/gisco_get_coastallines.R @@ -1,95 +1,95 @@ -#' Get GISCO coastlines `sf` polygons -#' -#' Downloads worldwide coastlines -#' -#' @concept political -#' @family political -#' -#' @param year Release year. One of "2006", "2010", "2013" or "2016" -#' -#' @inheritParams gisco_get_countries -#' -#' @inheritSection gisco_get_countries About caching -#' -#' @source -#' -#' @return A `sf` `POLYGON` object. -#' -#' @note -#' Please check the download and usage provisions on [gisco_attributions()]. -#' -#' @seealso [gisco_coastallines] -#' -#' @examples -#' coast <- gisco_get_coastallines() -#' -#' library(ggplot2) -#' -#' ggplot(coast) + -#' geom_sf(color = "#1278AB", fill = "#FDFBEA") + -#' # Zoom on Caribe -#' coord_sf( -#' xlim = c(-99, -49), -#' ylim = c(4, 30) -#' ) + -#' theme_minimal() + -#' theme(panel.background = element_rect(fill = "#C7E7FB", color = "black")) -#' @export -gisco_get_coastallines <- function(year = "2016", - epsg = "4326", - cache = TRUE, - update_cache = FALSE, - cache_dir = NULL, - verbose = FALSE, - resolution = "20") { - ext <- "geojson" - - api_entry <- gsc_api_url( - id_giscoR = "coastallines", - year = year, - epsg = epsg, - resolution = resolution, - spatialtype = NULL, - ext = ext, - nuts_level = NULL, - level = NULL, - verbose = verbose - ) - - filename <- basename(api_entry) - - # Check if data is already available - checkdata <- grep("COAS_RG_20M_2016_4326", api_entry) - if (isFALSE(update_cache) & length(checkdata)) { - dwnload <- FALSE - data_sf <- giscoR::gisco_coastallines - - gsc_message( - verbose, - "Loaded from gisco_coastallines dataset. Use update_cache = TRUE", - "to load the shapefile from the .geojson file" - ) - } else { - dwnload <- TRUE - } - if (dwnload) { - if (cache) { - # Guess source to load - namefileload <- - gsc_api_cache( - api_entry, - filename, - cache_dir, - update_cache, - verbose - ) - } else { - namefileload <- api_entry - } - - # Load - geojson only so far - data_sf <- - gsc_api_load(namefileload, epsg, ext, cache, verbose) - } - return(data_sf) -} +#' Get GISCO coastlines `sf` polygons +#' +#' Downloads worldwide coastlines +#' +#' @concept political +#' @family political +#' +#' @param year Release year. One of "2006", "2010", "2013" or "2016" +#' +#' @inheritParams gisco_get_countries +#' +#' @inheritSection gisco_get_countries About caching +#' +#' @source +#' +#' @return A `sf` `POLYGON` object. +#' +#' @note +#' Please check the download and usage provisions on [gisco_attributions()]. +#' +#' @seealso [gisco_coastallines] +#' +#' @examples +#' coast <- gisco_get_coastallines() +#' +#' library(ggplot2) +#' +#' ggplot(coast) + +#' geom_sf(color = "#1278AB", fill = "#FDFBEA") + +#' # Zoom on Caribe +#' coord_sf( +#' xlim = c(-99, -49), +#' ylim = c(4, 30) +#' ) + +#' theme_minimal() + +#' theme(panel.background = element_rect(fill = "#C7E7FB", color = "black")) +#' @export +gisco_get_coastallines <- function(year = "2016", + epsg = "4326", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + verbose = FALSE, + resolution = "20") { + ext <- "geojson" + + api_entry <- gsc_api_url( + id_giscoR = "coastallines", + year = year, + epsg = epsg, + resolution = resolution, + spatialtype = NULL, + ext = ext, + nuts_level = NULL, + level = NULL, + verbose = verbose + ) + + filename <- basename(api_entry) + + # Check if data is already available + checkdata <- grep("COAS_RG_20M_2016_4326", api_entry) + if (isFALSE(update_cache) && length(checkdata)) { + dwnload <- FALSE + data_sf <- giscoR::gisco_coastallines + + gsc_message( + verbose, + "Loaded from gisco_coastallines dataset. Use update_cache = TRUE", + "to load the shapefile from the .geojson file" + ) + } else { + dwnload <- TRUE + } + if (dwnload) { + if (cache) { + # Guess source to load + namefileload <- + gsc_api_cache( + api_entry, + filename, + cache_dir, + update_cache, + verbose + ) + } else { + namefileload <- api_entry + } + + # Load - geojson only so far + data_sf <- + gsc_api_load(namefileload, epsg, ext, cache, verbose) + } + return(data_sf) +} diff --git a/R/gisco_get_countries.R b/R/gisco_get_countries.R index 32fd3059..f7bc6ded 100644 --- a/R/gisco_get_countries.R +++ b/R/gisco_get_countries.R @@ -1,213 +1,213 @@ -#' Get GISCO world country `sf` polygons, points and lines -#' -#' @description -#' Returns world country polygons, lines and points at a specified scale, as -#' provided by GISCO. Also, specific areas as Gibraltar or Antarctica are -#' presented separately. The definition of country used on GISCO -#' correspond roughly with territories with an official -#' [ISO-3166](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) -#' code. -#' -#' @rdname gisco_get -#' -#' @note -#' Please check the download and usage provisions on [gisco_attributions()]. -#' -#' @concept political -#' @family political -#' -#' @details -#' # About caching -#' -#' You can set your `cache_dir` with [gisco_set_cache_dir()]. -#' -#' Sometimes cached files may be corrupt. On that case, try re-downloading -#' the data setting `update_cache = TRUE`. -#' -#' If you experience any problem on download, try to download the -#' corresponding .geojson file by any other method and save it on your -#' `cache_dir`. Use the option `verbose = TRUE` for debugging the API query. -#' -#' For a complete list of files available check [gisco_db]. -#' -#' -#' # World Regions -#' -#' Regions are defined as per the geographic regions defined by the -#' UN (see . -#' Under this scheme Cyprus is assigned to Asia. You may use -#' `region = "EU"` to get the EU members (reference date: 2021). -#' -#' -#' @return A `sf` object specified by `spatialtype`. -#' -#' @param year Release year of the file. One of "2001", "2006", -#' "2010", "2013", "2016" or "2020". -#' -#' @param epsg projection of the map: 4-digit [EPSG code](https://epsg.io/). -#' One of: -#' * "4258": ETRS89 -#' * "4326": WGS84 -#' * "3035": ETRS89 / ETRS-LAEA -#' * "3857": Pseudo-Mercator -#' -#' @param cache A logical whether to do caching. Default is `TRUE`. See -#' **About caching**. -#' -#' @param update_cache A logical whether to update cache. Default is `FALSE`. -#' When set to `TRUE` it would force a fresh download of the source -#' .geojson file. -#' -#' @param cache_dir A path to a cache directory. See **About caching**. -#' -#' @param spatialtype Type of geometry to be returned: -#' * **"BN"**: Boundaries - `LINESTRING` object. -#' * **"COASTL"**: coastlines - `LINESTRING` object. -#' * **"INLAND"**: inland boundaries - `LINESTRING` object. -#' * **"LB"**: Labels - `POINT` object. -#' * **"RG"**: Regions - `MULTIPOLYGON/POLYGON` object. -#' -#' @param country Optional. A character vector of country codes. It could be -#' either a vector of country names, a vector of ISO3 country codes or a -#' vector of Eurostat country codes. Mixed types (as `c("Turkey","US","FRA")`) -#' would not work. See also [countrycode::countrycode()]. -#' -#' @param verbose Logical, displays information. Useful for debugging, -#' default is `FALSE`. -#' -#' @param resolution Resolution of the geospatial data. One of -#' * "60": 1:60million -#' * "20": 1:20million -#' * "10": 1:10million -#' * "03": 1:3million -#' * "01": 1:1million -#' -#' @param region Optional. A character vector of UN M49 region codes or -#' European Union membership. Possible values are "Africa", "Americas", -#' "Asia", "Europe", "Oceania" or "EU" for countries belonging to the European -#' Union (as per 2021). See **About world regions** and [gisco_countrycode] -#' -#' @seealso [gisco_countrycode()], [gisco_countries], -#' [countrycode::countrycode()] -#' -#' @source -#' @export -#' -#' @examples -#' cntries <- gisco_get_countries() -#' -#' library(ggplot2) -#' ggplot(cntries) + -#' geom_sf() -#' -#' # Get a region -#' -#' africa <- gisco_get_countries(region = "Africa") -#' ggplot(africa) + -#' geom_sf(fill = "#078930", col = "white") + -#' theme_minimal() -#' \donttest{ -#' if (gisco_check_access()) { -#' # Extract points -#' asia_pol <- gisco_get_countries(region = "Asia", resolution = "3") -#' asia_lb <- gisco_get_countries(spatialtype = "LB", region = "Asia") -#' ggplot(asia_pol) + -#' geom_sf(fill = "gold3") + -#' geom_sf(data = asia_lb, color = "#007FFF") -#' } -#' } -gisco_get_countries <- function(year = "2016", - epsg = "4326", - cache = TRUE, - update_cache = FALSE, - cache_dir = NULL, - verbose = FALSE, - resolution = "20", - spatialtype = "RG", - country = NULL, - region = NULL) { - ext <- "geojson" - - api_entry <- gsc_api_url( - id_giscoR = "countries", - year = year, - epsg = epsg, - resolution = resolution, - spatialtype = spatialtype, - ext = ext, - nuts_level = NULL, - level = NULL, - verbose = verbose - ) - - filename <- basename(api_entry) - - # Check if data is already available - checkdata <- grep("CNTR_RG_20M_2016_4326", filename) - if (isFALSE(update_cache) & length(checkdata)) { - dwnload <- FALSE - data_sf <- giscoR::gisco_countries - - gsc_message( - verbose, - "Loaded from gisco_countries dataset. Use update_cache = TRUE - to load the shapefile from the .geojson file" - ) - } else { - dwnload <- TRUE - } - if (dwnload) { - # Speed up if requesting units - if (!is.null(country) & spatialtype %in% c("RG", "LB")) { - data_sf <- gisco_get_units( - id_giscoR = "countries", - unit = country, - mode = "sf", - year = year, - epsg = epsg, - cache = cache, - cache_dir = cache_dir, - update_cache = update_cache, - verbose = verbose, - resolution = resolution, - spatialtype = spatialtype - ) - } else { - if (cache) { - # Guess source to load - namefileload <- - gsc_api_cache( - api_entry, - filename, - cache_dir, - update_cache, - verbose - ) - } else { - namefileload <- api_entry - } - - # Load - geojson only so far - data_sf <- - gsc_api_load(namefileload, epsg, ext, cache, verbose) - } - } - - if (!is.null(country) & "CNTR_ID" %in% names(data_sf)) { - country <- gsc_helper_countrynames(country, "eurostat") - data_sf <- data_sf[data_sf$CNTR_ID %in% country, ] - } - if (!is.null(region) & "CNTR_ID" %in% names(data_sf)) { - region_df <- giscoR::gisco_countrycode - cntryregion <- region_df[region_df$un.region.name %in% region, ] - - if ("EU" %in% region) { - eu <- region_df[region_df$eu, ] - cntryregion <- unique(rbind(cntryregion, eu)) - } - - data_sf <- data_sf[data_sf$CNTR_ID %in% cntryregion$CNTR_CODE, ] - } - - return(data_sf) -} +#' Get GISCO world country `sf` polygons, points and lines +#' +#' @description +#' Returns world country polygons, lines and points at a specified scale, as +#' provided by GISCO. Also, specific areas as Gibraltar or Antarctica are +#' presented separately. The definition of country used on GISCO +#' correspond roughly with territories with an official +#' [ISO-3166](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) +#' code. +#' +#' @rdname gisco_get +#' +#' @note +#' Please check the download and usage provisions on [gisco_attributions()]. +#' +#' @concept political +#' @family political +#' +#' @details +#' # About caching +#' +#' You can set your `cache_dir` with [gisco_set_cache_dir()]. +#' +#' Sometimes cached files may be corrupt. On that case, try re-downloading +#' the data setting `update_cache = TRUE`. +#' +#' If you experience any problem on download, try to download the +#' corresponding .geojson file by any other method and save it on your +#' `cache_dir`. Use the option `verbose = TRUE` for debugging the API query. +#' +#' For a complete list of files available check [gisco_db]. +#' +#' +#' # World Regions +#' +#' Regions are defined as per the geographic regions defined by the +#' UN (see . +#' Under this scheme Cyprus is assigned to Asia. You may use +#' `region = "EU"` to get the EU members (reference date: 2021). +#' +#' +#' @return A `sf` object specified by `spatialtype`. +#' +#' @param year Release year of the file. One of "2001", "2006", +#' "2010", "2013", "2016" or "2020". +#' +#' @param epsg projection of the map: 4-digit [EPSG code](https://epsg.io/). +#' One of: +#' * "4258": ETRS89 +#' * "4326": WGS84 +#' * "3035": ETRS89 / ETRS-LAEA +#' * "3857": Pseudo-Mercator +#' +#' @param cache A logical whether to do caching. Default is `TRUE`. See +#' **About caching**. +#' +#' @param update_cache A logical whether to update cache. Default is `FALSE`. +#' When set to `TRUE` it would force a fresh download of the source +#' .geojson file. +#' +#' @param cache_dir A path to a cache directory. See **About caching**. +#' +#' @param spatialtype Type of geometry to be returned: +#' * **"BN"**: Boundaries - `LINESTRING` object. +#' * **"COASTL"**: coastlines - `LINESTRING` object. +#' * **"INLAND"**: inland boundaries - `LINESTRING` object. +#' * **"LB"**: Labels - `POINT` object. +#' * **"RG"**: Regions - `MULTIPOLYGON/POLYGON` object. +#' +#' @param country Optional. A character vector of country codes. It could be +#' either a vector of country names, a vector of ISO3 country codes or a +#' vector of Eurostat country codes. Mixed types (as `c("Turkey","US","FRA")`) +#' would not work. See also [countrycode::countrycode()]. +#' +#' @param verbose Logical, displays information. Useful for debugging, +#' default is `FALSE`. +#' +#' @param resolution Resolution of the geospatial data. One of +#' * "60": 1:60million +#' * "20": 1:20million +#' * "10": 1:10million +#' * "03": 1:3million +#' * "01": 1:1million +#' +#' @param region Optional. A character vector of UN M49 region codes or +#' European Union membership. Possible values are "Africa", "Americas", +#' "Asia", "Europe", "Oceania" or "EU" for countries belonging to the European +#' Union (as per 2021). See **About world regions** and [gisco_countrycode] +#' +#' @seealso [gisco_countrycode()], [gisco_countries], +#' [countrycode::countrycode()] +#' +#' @source +#' @export +#' +#' @examples +#' cntries <- gisco_get_countries() +#' +#' library(ggplot2) +#' ggplot(cntries) + +#' geom_sf() +#' +#' # Get a region +#' +#' africa <- gisco_get_countries(region = "Africa") +#' ggplot(africa) + +#' geom_sf(fill = "#078930", col = "white") + +#' theme_minimal() +#' \donttest{ +#' if (gisco_check_access()) { +#' # Extract points +#' asia_pol <- gisco_get_countries(region = "Asia", resolution = "3") +#' asia_lb <- gisco_get_countries(spatialtype = "LB", region = "Asia") +#' ggplot(asia_pol) + +#' geom_sf(fill = "gold3") + +#' geom_sf(data = asia_lb, color = "#007FFF") +#' } +#' } +gisco_get_countries <- function(year = "2016", + epsg = "4326", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + verbose = FALSE, + resolution = "20", + spatialtype = "RG", + country = NULL, + region = NULL) { + ext <- "geojson" + + api_entry <- gsc_api_url( + id_giscoR = "countries", + year = year, + epsg = epsg, + resolution = resolution, + spatialtype = spatialtype, + ext = ext, + nuts_level = NULL, + level = NULL, + verbose = verbose + ) + + filename <- basename(api_entry) + + # Check if data is already available + checkdata <- grep("CNTR_RG_20M_2016_4326", filename) + if (isFALSE(update_cache) && length(checkdata)) { + dwnload <- FALSE + data_sf <- giscoR::gisco_countries + + gsc_message( + verbose, + "Loaded from gisco_countries dataset. Use update_cache = TRUE + to load the shapefile from the .geojson file" + ) + } else { + dwnload <- TRUE + } + if (dwnload) { + # Speed up if requesting units + if (!is.null(country) && spatialtype %in% c("RG", "LB")) { + data_sf <- gisco_get_units( + id_giscoR = "countries", + unit = country, + mode = "sf", + year = year, + epsg = epsg, + cache = cache, + cache_dir = cache_dir, + update_cache = update_cache, + verbose = verbose, + resolution = resolution, + spatialtype = spatialtype + ) + } else { + if (cache) { + # Guess source to load + namefileload <- + gsc_api_cache( + api_entry, + filename, + cache_dir, + update_cache, + verbose + ) + } else { + namefileload <- api_entry + } + + # Load - geojson only so far + data_sf <- + gsc_api_load(namefileload, epsg, ext, cache, verbose) + } + } + + if (!is.null(country) && "CNTR_ID" %in% names(data_sf)) { + country <- gsc_helper_countrynames(country, "eurostat") + data_sf <- data_sf[data_sf$CNTR_ID %in% country, ] + } + if (!is.null(region) && "CNTR_ID" %in% names(data_sf)) { + region_df <- giscoR::gisco_countrycode + cntryregion <- region_df[region_df$un.region.name %in% region, ] + + if ("EU" %in% region) { + eu <- region_df[region_df$eu, ] + cntryregion <- unique(rbind(cntryregion, eu)) + } + + data_sf <- data_sf[data_sf$CNTR_ID %in% cntryregion$CNTR_CODE, ] + } + + return(data_sf) +} diff --git a/R/gisco_get_grid.R b/R/gisco_get_grid.R index 475aa31f..e3a0da38 100644 --- a/R/gisco_get_grid.R +++ b/R/gisco_get_grid.R @@ -1,213 +1,213 @@ -#' Get grid cells covering covering Europe for various resolutions -#' -#' @description -#' These datasets contain grid cells covering the European land -#' territory, for various resolutions from 1km to 100km. Base statistics such -#' as population figures are provided for these cells. -#' -#' @concept misc -#' -#' @return A `POLYGON/POINT` object. -#' -#' @author dieghernan, -#' -#' @source -#' -#' -#' @param resolution Resolution of the grid cells on kms. Available values are -#' "1", "2", "5", "10", "20", "50", "100". See Details -#' -#' @param spatialtype Select one of "REGION" or "POINT". -#' -#' @inheritParams gisco_get_countries -#' -#' @inheritSection gisco_get_countries About caching -#' -#' @details -#' -#' Files are distributed on EPSG:3035. -#' -#' The file sizes range is from 428Kb (`resolution = "100"`) -#' to 1.7Gb `resolution = "1"`. For resolutions 1km and 2km you would -#' need to confirm the download. -#' -#' @note -#' There are specific downloading provisions, please see -#' -#' -#' @examplesIf gisco_check_access() -#' \donttest{ -#' grid <- gisco_get_grid(resolution = 20) -#' grid$popdens <- grid$TOT_P_2011 / 20 -#' -#' -#' breaks <- -#' c( -#' 0, -#' 0.1, # For capturing 0 -#' 100, -#' 500, -#' 1000, -#' 2500, -#' 5000, -#' 10000, -#' 25000, -#' max(grid$popdens) + 1 -#' ) -#' -#' # Cut groups -#' -#' grid$popdens_cut <- cut(grid$popdens, -#' breaks = breaks, -#' include.lowest = TRUE -#' ) -#' cut_labs <- prettyNum(breaks, big.mark = " ")[-1] -#' cut_labs[1] <- "0" -#' cut_labs[9] <- "> 25 000" -#' -#' pal <- c("black", hcl.colors(length(breaks) - 2, -#' palette = "Spectral", -#' alpha = 0.9 -#' )) -#' -#' library(ggplot2) -#' -#' ggplot(grid) + -#' geom_sf(aes(fill = popdens_cut), color = NA, linewidth = 0) + -#' coord_sf( -#' xlim = c(2500000, 7000000), -#' ylim = c(1500000, 5200000) -#' ) + -#' scale_fill_manual( -#' values = pal, na.value = "black", -#' name = "people per sq. kilometer", -#' labels = cut_labs, -#' guide = guide_legend( -#' direction = "horizontal", -#' keyheight = 0.5, -#' keywidth = 2, -#' title.position = "top", -#' title.hjust = 0.5, -#' label.hjust = .5, -#' nrow = 1, -#' byrow = TRUE, -#' reverse = FALSE, -#' label.position = "bottom" -#' ) -#' ) + -#' theme_void() + -#' labs( -#' title = "Population density in Europe", -#' subtitle = "Grid: 20 km.", -#' caption = gisco_attributions() -#' ) + -#' theme( -#' plot.background = element_rect(fill = "grey2"), -#' plot.title = element_text( -#' size = 18, color = "white", -#' hjust = 0.5, -#' ), -#' plot.subtitle = element_text( -#' size = 14, -#' color = "white", -#' hjust = 0.5, -#' face = "bold" -#' ), -#' plot.caption = element_text( -#' size = 9, color = "grey60", -#' hjust = 0.5, vjust = 0, -#' margin = margin(t = 5, b = 10) -#' ), -#' legend.text = element_text( -#' size = 8, -#' color = "white" -#' ), -#' legend.title = element_text( -#' color = "white" -#' ), -#' legend.position = "bottom" -#' ) -#' } -#' @export -gisco_get_grid <- function(resolution = "20", - spatialtype = "REGION", - cache_dir = NULL, - update_cache = FALSE, - verbose = FALSE) { - resolution <- as.character(resolution) - validres <- as.character(c(1, 2, 5, 10, 20, 50, 100)) - - if (!resolution %in% validres) { - stop( - "resolution should be one of ", - paste0(validres, collapse = ", ") - ) - } - - valid <- c("REGION", "POINT") - if (!spatialtype %in% valid) { - stop("spatialtype should be 'REGION' or 'POINT'") - } - - translate <- c("surf", "point") - ftrans <- translate[valid == spatialtype] - filename <- paste0("grid_", resolution, "km_", ftrans, ".gpkg") - api_entry <- "https://gisco-services.ec.europa.eu/grid" - url <- file.path(api_entry, filename) - - local <- file.path(gsc_helper_cachedir(cache_dir), filename) - exist_local <- file.exists(local) - - - gsc_message( - verbose & exist_local, - "File exits on local cache dir" - ) - - # nocov start - if (resolution %in% c("1", "2") & isFALSE(exist_local)) { - sel <- - menu(c("Yes", "No"), - title = "You are about to download a large file (>500M). Proceed?" - ) - if (sel != 1) { - stop("Execution halted") - } - } - # nocov end - - - localfile <- - gsc_api_cache(url, filename, cache_dir, update_cache, verbose) - - - size <- file.size(localfile) - class(size) <- "object_size" - gsc_message(verbose, format(size, units = "auto")) - - data_sf <- try( - sf::st_read( - localfile, - quiet = !verbose, - stringsAsFactors = FALSE - ), - silent = TRUE - ) - - - # nocov start - if (inherits(data_sf, "try-error")) { - stop( - "\n Malformed ", - localfile, - "\n Try downloading from: \n", - url, - "\n to your cache_dir folder" - ) - } - # nocov end - - data_sf <- sf::st_make_valid(data_sf) - - return(data_sf) -} +#' Get grid cells covering covering Europe for various resolutions +#' +#' @description +#' These datasets contain grid cells covering the European land +#' territory, for various resolutions from 1km to 100km. Base statistics such +#' as population figures are provided for these cells. +#' +#' @concept misc +#' +#' @return A `POLYGON/POINT` object. +#' +#' @author dieghernan, +#' +#' @source +#' +#' +#' @param resolution Resolution of the grid cells on kms. Available values are +#' "1", "2", "5", "10", "20", "50", "100". See Details +#' +#' @param spatialtype Select one of "REGION" or "POINT". +#' +#' @inheritParams gisco_get_countries +#' +#' @inheritSection gisco_get_countries About caching +#' +#' @details +#' +#' Files are distributed on EPSG:3035. +#' +#' The file sizes range is from 428Kb (`resolution = "100"`) +#' to 1.7Gb `resolution = "1"`. For resolutions 1km and 2km you would +#' need to confirm the download. +#' +#' @note +#' There are specific downloading provisions, please see +#' +#' +#' @examplesIf gisco_check_access() +#' \donttest{ +#' grid <- gisco_get_grid(resolution = 20) +#' grid$popdens <- grid$TOT_P_2011 / 20 +#' +#' +#' breaks <- +#' c( +#' 0, +#' 0.1, # For capturing 0 +#' 100, +#' 500, +#' 1000, +#' 2500, +#' 5000, +#' 10000, +#' 25000, +#' max(grid$popdens) + 1 +#' ) +#' +#' # Cut groups +#' +#' grid$popdens_cut <- cut(grid$popdens, +#' breaks = breaks, +#' include.lowest = TRUE +#' ) +#' cut_labs <- prettyNum(breaks, big.mark = " ")[-1] +#' cut_labs[1] <- "0" +#' cut_labs[9] <- "> 25 000" +#' +#' pal <- c("black", hcl.colors(length(breaks) - 2, +#' palette = "Spectral", +#' alpha = 0.9 +#' )) +#' +#' library(ggplot2) +#' +#' ggplot(grid) + +#' geom_sf(aes(fill = popdens_cut), color = NA, linewidth = 0) + +#' coord_sf( +#' xlim = c(2500000, 7000000), +#' ylim = c(1500000, 5200000) +#' ) + +#' scale_fill_manual( +#' values = pal, na.value = "black", +#' name = "people per sq. kilometer", +#' labels = cut_labs, +#' guide = guide_legend( +#' direction = "horizontal", +#' keyheight = 0.5, +#' keywidth = 2, +#' title.position = "top", +#' title.hjust = 0.5, +#' label.hjust = .5, +#' nrow = 1, +#' byrow = TRUE, +#' reverse = FALSE, +#' label.position = "bottom" +#' ) +#' ) + +#' theme_void() + +#' labs( +#' title = "Population density in Europe", +#' subtitle = "Grid: 20 km.", +#' caption = gisco_attributions() +#' ) + +#' theme( +#' plot.background = element_rect(fill = "grey2"), +#' plot.title = element_text( +#' size = 18, color = "white", +#' hjust = 0.5, +#' ), +#' plot.subtitle = element_text( +#' size = 14, +#' color = "white", +#' hjust = 0.5, +#' face = "bold" +#' ), +#' plot.caption = element_text( +#' size = 9, color = "grey60", +#' hjust = 0.5, vjust = 0, +#' margin = margin(t = 5, b = 10) +#' ), +#' legend.text = element_text( +#' size = 8, +#' color = "white" +#' ), +#' legend.title = element_text( +#' color = "white" +#' ), +#' legend.position = "bottom" +#' ) +#' } +#' @export +gisco_get_grid <- function(resolution = "20", + spatialtype = "REGION", + cache_dir = NULL, + update_cache = FALSE, + verbose = FALSE) { + resolution <- as.character(resolution) + validres <- as.character(c(1, 2, 5, 10, 20, 50, 100)) + + if (!resolution %in% validres) { + stop( + "resolution should be one of ", + paste0(validres, collapse = ", ") + ) + } + + valid <- c("REGION", "POINT") + if (!spatialtype %in% valid) { + stop("spatialtype should be 'REGION' or 'POINT'") + } + + translate <- c("surf", "point") + ftrans <- translate[valid == spatialtype] + filename <- paste0("grid_", resolution, "km_", ftrans, ".gpkg") + api_entry <- "https://gisco-services.ec.europa.eu/grid" + url <- file.path(api_entry, filename) + + local <- file.path(gsc_helper_cachedir(cache_dir), filename) + exist_local <- file.exists(local) + + + gsc_message( + verbose & exist_local, + "File exits on local cache dir" + ) + + # nocov start + if (resolution %in% c("1", "2") && isFALSE(exist_local)) { + sel <- + menu(c("Yes", "No"), + title = "You are about to download a large file (>500M). Proceed?" + ) + if (sel != 1) { + stop("Execution halted") + } + } + # nocov end + + + localfile <- + gsc_api_cache(url, filename, cache_dir, update_cache, verbose) + + + size <- file.size(localfile) + class(size) <- "object_size" + gsc_message(verbose, format(size, units = "auto")) + + data_sf <- try( + sf::st_read( + localfile, + quiet = !verbose, + stringsAsFactors = FALSE + ), + silent = TRUE + ) + + + # nocov start + if (inherits(data_sf, "try-error")) { + stop( + "\n Malformed ", + localfile, + "\n Try downloading from: \n", + url, + "\n to your cache_dir folder" + ) + } + # nocov end + + data_sf <- sf::st_make_valid(data_sf) + + return(data_sf) +} diff --git a/R/gisco_get_healthcare.R b/R/gisco_get_healthcare.R index 8477f90d..f6056b29 100644 --- a/R/gisco_get_healthcare.R +++ b/R/gisco_get_healthcare.R @@ -1,90 +1,90 @@ -#' Get locations of healthcare services in Europe. -#' -#' @concept infrastructure -#' @family infrastructure -#' -#' @description -#' The dataset contains information on main healthcare services considered to -#' be 'hospitals' by Member States. -#' -#' @return A `POINT` object. -#' -#' @author dieghernan, -#' -#' @source -#' -#' -#' @inheritParams gisco_get_countries -#' -#' @inheritSection gisco_get_countries About caching -#' -#' @details -#' Files are distributed on EPSG:4326. Metadata available on -#' . -#' -#' @seealso [gisco_get_countries()] -#' @examplesIf gisco_check_access() -#' \donttest{ -#' -#' health_BEL <- gisco_get_healthcare(country = "Belgium") -#' health_BEL[health_BEL$public_private == "", ]$public_private <- "unknown" -#' BEL <- gisco_get_nuts( -#' country = "Belgium", nuts_level = 2, -#' resolution = "01" -#' ) -#' -#' library(ggplot2) -#' -#' ggplot(BEL) + -#' geom_sf(fill = "white", color = "grey80") + -#' geom_sf( -#' data = health_BEL, aes(color = public_private), -#' alpha = 0.5, size = 3 -#' ) + -#' theme_bw() + -#' labs( -#' title = "Healthcare in Belgium", -#' subtitle = "NUTS 2", -#' fill = "type", -#' caption = paste0(gisco_attributions()) -#' ) + -#' scale_color_manual(name = "type", values = hcl.colors(3, "Berlin")) + -#' theme_minimal() -#' } -#' @export -gisco_get_healthcare <- function(cache = TRUE, - update_cache = FALSE, - cache_dir = NULL, - verbose = FALSE, - country = NULL) { - # Given vars - epsg <- "4326" - ext <- "gpkg" - - api_entry <- "https://gisco-services.ec.europa.eu/pub/healthcare/gpkg/EU/EU.gpkg" - filename <- basename(api_entry) - - - if (cache) { - # Guess source to load - namefileload <- - gsc_api_cache( - api_entry, - filename, - cache_dir, - update_cache, - verbose - ) - } else { - namefileload <- api_entry - } - - data_sf <- - gsc_api_load(namefileload, epsg, ext, cache, verbose) - - if (!is.null(country) & "cc" %in% names(data_sf)) { - country <- gsc_helper_countrynames(country, "eurostat") - data_sf <- data_sf[data_sf$cc %in% country, ] - } - return(data_sf) -} +#' Get locations of healthcare services in Europe. +#' +#' @concept infrastructure +#' @family infrastructure +#' +#' @description +#' The dataset contains information on main healthcare services considered to +#' be 'hospitals' by Member States. +#' +#' @return A `POINT` object. +#' +#' @author dieghernan, +#' +#' @source +#' +#' +#' @inheritParams gisco_get_countries +#' +#' @inheritSection gisco_get_countries About caching +#' +#' @details +#' Files are distributed on EPSG:4326. Metadata available on +#' . +#' +#' @seealso [gisco_get_countries()] +#' @examplesIf gisco_check_access() +#' \donttest{ +#' +#' health_BEL <- gisco_get_healthcare(country = "Belgium") +#' health_BEL[health_BEL$public_private == "", ]$public_private <- "unknown" +#' BEL <- gisco_get_nuts( +#' country = "Belgium", nuts_level = 2, +#' resolution = "01" +#' ) +#' +#' library(ggplot2) +#' +#' ggplot(BEL) + +#' geom_sf(fill = "white", color = "grey80") + +#' geom_sf( +#' data = health_BEL, aes(color = public_private), +#' alpha = 0.5, size = 3 +#' ) + +#' theme_bw() + +#' labs( +#' title = "Healthcare in Belgium", +#' subtitle = "NUTS 2", +#' fill = "type", +#' caption = paste0(gisco_attributions()) +#' ) + +#' scale_color_manual(name = "type", values = hcl.colors(3, "Berlin")) + +#' theme_minimal() +#' } +#' @export +gisco_get_healthcare <- function(cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + verbose = FALSE, + country = NULL) { + # Given vars + epsg <- "4326" + ext <- "gpkg" + + api_entry <- "https://gisco-services.ec.europa.eu/pub/healthcare/gpkg/EU/EU.gpkg" + filename <- basename(api_entry) + + + if (cache) { + # Guess source to load + namefileload <- + gsc_api_cache( + api_entry, + filename, + cache_dir, + update_cache, + verbose + ) + } else { + namefileload <- api_entry + } + + data_sf <- + gsc_api_load(namefileload, epsg, ext, cache, verbose) + + if (!is.null(country) && "cc" %in% names(data_sf)) { + country <- gsc_helper_countrynames(country, "eurostat") + data_sf <- data_sf[data_sf$cc %in% country, ] + } + return(data_sf) +} diff --git a/R/gisco_get_lau.R b/R/gisco_get_lau.R index 6332284e..b7257912 100644 --- a/R/gisco_get_lau.R +++ b/R/gisco_get_lau.R @@ -1,312 +1,312 @@ -#' Get GISCO urban areas `sf` polygons, points and lines -#' -#' @description -#' [gisco_get_communes()] and [gisco_get_lau()] download shapes of Local -#' Urban Areas, that correspond roughly with towns and cities. -#' -#' @order 2 -#' -#' @note -#' Please check the download and usage provisions on [gisco_attributions()]. -#' @concept political -#' @family political -#' -#' @return A `sf` object specified by `spatialtype`. In the case of -#' [gisco_get_lau()], a `POLYGON` object. -#' -#' @param year Release year of the file. See Details. -#' -#' @param gisco_id Optional. A character vector of GISCO_ID LAU values. -#' -#' @inheritParams gisco_get_countries -#' -#' @inheritSection gisco_get_countries About caching -#' -#' @details -#' Valid years for eacg function are: -#' * **`gisco_get_communes`**: one of '2001', '2004', '2006', '2008', '2010', -#' '2013' or '2016'. -#' * **`gisco_get_lau`**: one of -#' -#' ```{r, echo=FALSE, results= "asis"} -#' cat(paste0( -#' paste0("'", (2011:2020), "'", collapse = ", "), -#' ".") -#' ) -#' -#' ``` -#' -#' @export -gisco_get_lau <- function(year = "2016", - epsg = "4326", - cache = TRUE, - update_cache = FALSE, - cache_dir = NULL, - verbose = FALSE, - country = NULL, - gisco_id = NULL) { - ext <- "geojson" - - api_entry <- gsc_api_url( - id_giscoR = "lau", - year = year, - epsg = epsg, - resolution = 0, - spatialtype = "RG", - ext = ext, - nuts_level = NULL, - level = NULL, - verbose = verbose - ) - - filename <- basename(api_entry) - # Improve speed using querys if country(es) are selected - # We construct the query and passed it to the st_read fun - - - if ((!is.null(country) || !is.null(gisco_id)) && cache) { - gsc_message(verbose, "Speed up using sf query") - if (!is.null(country)) { - country <- gsc_helper_countrynames( - country, "eurostat" - ) - } - - namefileload <- - gsc_api_cache( - api_entry, - filename, - cache_dir, - update_cache, - verbose - ) - - # Get layer name - layer <- tools::file_path_sans_ext(basename(namefileload)) - - # Construct query - q <- paste0( - "SELECT * from \"", - layer, - "\" WHERE" - ) - - where <- NULL - if (!is.null(country)) { - where <- c(where, paste0( - "CNTR_CODE IN (", - paste0("'", country, "'", collapse = ", "), - ")" - )) - } - - if (!is.null(gisco_id)) { - where <- c(where, paste0( - "GISCO_ID IN (", - paste0("'", gisco_id, "'", collapse = ", "), - ")" - )) - } - - where <- paste(where, collapse = " OR ") - q <- paste(q, where) - - gsc_message(verbose, "Using query:\n ", q) - - - data_sf <- try( - suppressWarnings( - sf::st_read(namefileload, - quiet = !verbose, - query = q - ) - ), - silent = TRUE - ) - - # If everything was fine then output - if (!inherits(data_sf, "try-error")) { - data_sf <- sf::st_make_valid(data_sf) - return(data_sf) - } - - # If not don't update cache (was already updated) and continue - update_cache <- FALSE - rm(data_sf) - gsc_message( - TRUE, - "\n\nIt was a problem with the query.", - "Retrying without country filters\n\n" - ) - } - - if (cache) { - # Guess source to load - namefileload <- - gsc_api_cache( - api_entry, - filename, - cache_dir, - update_cache, - verbose - ) - } else { - namefileload <- api_entry - } - - # Load - geojson only so far - data_sf <- - gsc_api_load(namefileload, epsg, ext, cache, verbose) - - if (!is.null(country) & "CNTR_CODE" %in% names(data_sf)) { - # Convert ISO3 to EUROSTAT thanks to Vincent Arel-Bundock (countrycode) - country <- gsc_helper_countrynames(country, "eurostat") - data_sf <- data_sf[data_sf$CNTR_CODE %in% country, ] - } - - if (!is.null(country) & "CNTR_ID" %in% names(data_sf)) { - country <- gsc_helper_countrynames(country, "eurostat") - data_sf <- data_sf[data_sf$CNTR_ID %in% country, ] - } - - if (!is.null(gisco_id) & "GISCO_ID" %in% names(data_sf)) { - data_sf <- data_sf[data_sf$GISCO_ID %in% gisco_id, ] - } - return(data_sf) -} - - -#' @rdname gisco_get_lau -#' @name gisco_get_lau -#' -#' @order 1 -#' -#' @examplesIf gisco_check_access() -#' \donttest{ -#' -#' ire_lau <- gisco_get_communes(spatialtype = "LB", country = "Ireland") -#' -#' library(ggplot2) -#' -#' ggplot(ire_lau) + -#' geom_sf(shape = 21, col = "#009A44", size = 0.5) + -#' labs( -#' title = "Communes in Ireland", -#' subtitle = "Year 2016", -#' caption = gisco_attributions() -#' ) + -#' theme_void() + -#' theme(text = element_text( -#' colour = "#009A44", -#' family = "serif", face = "bold" -#' )) -#' } -#' @export -gisco_get_communes <- function(year = "2016", - epsg = "4326", - cache = TRUE, - update_cache = FALSE, - cache_dir = NULL, - verbose = FALSE, - spatialtype = "RG", - country = NULL) { - ext <- "geojson" - - api_entry <- gsc_api_url( - id_giscoR = "communes", - year = year, - epsg = epsg, - resolution = 0, - # Not neccesary - spatialtype = spatialtype, - ext = ext, - nuts_level = NULL, - level = NULL, - verbose = verbose - ) - - - filename <- basename(api_entry) - - # Improve speed using querys if country(es) are selected - # We construct the query and passed it to the st_read fun - - if (cache && !is.null(country)) { - gsc_message(verbose, "Speed up using sf query") - country <- gsc_helper_countrynames(country, "eurostat") - namefileload <- - gsc_api_cache( - api_entry, - filename, - cache_dir, - update_cache, - verbose - ) - - # Get layer name - layer <- tools::file_path_sans_ext(basename(namefileload)) - - # Construct query - q <- paste0( - "SELECT * from \"", - layer, - "\" WHERE CNTR_CODE IN (", - paste0("'", country, "'", collapse = ", "), - ")" - ) - - gsc_message(verbose, "Using query:\n ", q) - - - data_sf <- try( - suppressWarnings( - sf::st_read(namefileload, - quiet = !verbose, - query = q - ) - ), - silent = TRUE - ) - - # If everything was fine then output - if (!inherits(data_sf, "try-error")) { - data_sf <- sf::st_make_valid(data_sf) - return(data_sf) - } - - # If not don't update cache (was already updated) and continue - update_cache <- FALSE - rm(data_sf) - gsc_message( - TRUE, - "\n\nIt was a problem with the query.", - "Retrying without country filters\n\n" - ) - } - - - - - if (cache) { - # Guess source to load - namefileload <- - gsc_api_cache( - api_entry, - filename, - cache_dir, - update_cache, - verbose - ) - } else { - namefileload <- api_entry - } - - # Load - geojson only so far - data_sf <- gsc_api_load( - namefileload, epsg, ext, cache, - verbose - ) - - - return(data_sf) -} +#' Get GISCO urban areas `sf` polygons, points and lines +#' +#' @description +#' [gisco_get_communes()] and [gisco_get_lau()] download shapes of Local +#' Urban Areas, that correspond roughly with towns and cities. +#' +#' @order 2 +#' +#' @note +#' Please check the download and usage provisions on [gisco_attributions()]. +#' @concept political +#' @family political +#' +#' @return A `sf` object specified by `spatialtype`. In the case of +#' [gisco_get_lau()], a `POLYGON` object. +#' +#' @param year Release year of the file. See Details. +#' +#' @param gisco_id Optional. A character vector of GISCO_ID LAU values. +#' +#' @inheritParams gisco_get_countries +#' +#' @inheritSection gisco_get_countries About caching +#' +#' @details +#' Valid years for eacg function are: +#' * **`gisco_get_communes`**: one of '2001', '2004', '2006', '2008', '2010', +#' '2013' or '2016'. +#' * **`gisco_get_lau`**: one of +#' +#' ```{r, echo=FALSE, results= "asis"} +#' cat(paste0( +#' paste0("'", (2011:2020), "'", collapse = ", "), +#' ".") +#' ) +#' +#' ``` +#' +#' @export +gisco_get_lau <- function(year = "2016", + epsg = "4326", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + verbose = FALSE, + country = NULL, + gisco_id = NULL) { + ext <- "geojson" + + api_entry <- gsc_api_url( + id_giscoR = "lau", + year = year, + epsg = epsg, + resolution = 0, + spatialtype = "RG", + ext = ext, + nuts_level = NULL, + level = NULL, + verbose = verbose + ) + + filename <- basename(api_entry) + # Improve speed using querys if country(es) are selected + # We construct the query and passed it to the st_read fun + + + if ((!is.null(country) || !is.null(gisco_id)) && cache) { + gsc_message(verbose, "Speed up using sf query") + if (!is.null(country)) { + country <- gsc_helper_countrynames( + country, "eurostat" + ) + } + + namefileload <- + gsc_api_cache( + api_entry, + filename, + cache_dir, + update_cache, + verbose + ) + + # Get layer name + layer <- tools::file_path_sans_ext(basename(namefileload)) + + # Construct query + q <- paste0( + "SELECT * from \"", + layer, + "\" WHERE" + ) + + where <- NULL + if (!is.null(country)) { + where <- c(where, paste0( + "CNTR_CODE IN (", + paste0("'", country, "'", collapse = ", "), + ")" + )) + } + + if (!is.null(gisco_id)) { + where <- c(where, paste0( + "GISCO_ID IN (", + paste0("'", gisco_id, "'", collapse = ", "), + ")" + )) + } + + where <- paste(where, collapse = " OR ") + q <- paste(q, where) + + gsc_message(verbose, "Using query:\n ", q) + + + data_sf <- try( + suppressWarnings( + sf::st_read(namefileload, + quiet = !verbose, + query = q + ) + ), + silent = TRUE + ) + + # If everything was fine then output + if (!inherits(data_sf, "try-error")) { + data_sf <- sf::st_make_valid(data_sf) + return(data_sf) + } + + # If not don't update cache (was already updated) and continue + update_cache <- FALSE + rm(data_sf) + gsc_message( + TRUE, + "\n\nIt was a problem with the query.", + "Retrying without country filters\n\n" + ) + } + + if (cache) { + # Guess source to load + namefileload <- + gsc_api_cache( + api_entry, + filename, + cache_dir, + update_cache, + verbose + ) + } else { + namefileload <- api_entry + } + + # Load - geojson only so far + data_sf <- + gsc_api_load(namefileload, epsg, ext, cache, verbose) + + if (!is.null(country) && "CNTR_CODE" %in% names(data_sf)) { + # Convert ISO3 to EUROSTAT thanks to Vincent Arel-Bundock (countrycode) + country <- gsc_helper_countrynames(country, "eurostat") + data_sf <- data_sf[data_sf$CNTR_CODE %in% country, ] + } + + if (!is.null(country) && "CNTR_ID" %in% names(data_sf)) { + country <- gsc_helper_countrynames(country, "eurostat") + data_sf <- data_sf[data_sf$CNTR_ID %in% country, ] + } + + if (!is.null(gisco_id) && "GISCO_ID" %in% names(data_sf)) { + data_sf <- data_sf[data_sf$GISCO_ID %in% gisco_id, ] + } + return(data_sf) +} + + +#' @rdname gisco_get_lau +#' @name gisco_get_lau +#' +#' @order 1 +#' +#' @examplesIf gisco_check_access() +#' \donttest{ +#' +#' ire_lau <- gisco_get_communes(spatialtype = "LB", country = "Ireland") +#' +#' library(ggplot2) +#' +#' ggplot(ire_lau) + +#' geom_sf(shape = 21, col = "#009A44", size = 0.5) + +#' labs( +#' title = "Communes in Ireland", +#' subtitle = "Year 2016", +#' caption = gisco_attributions() +#' ) + +#' theme_void() + +#' theme(text = element_text( +#' colour = "#009A44", +#' family = "serif", face = "bold" +#' )) +#' } +#' @export +gisco_get_communes <- function(year = "2016", + epsg = "4326", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + verbose = FALSE, + spatialtype = "RG", + country = NULL) { + ext <- "geojson" + + api_entry <- gsc_api_url( + id_giscoR = "communes", + year = year, + epsg = epsg, + resolution = 0, + # Not neccesary + spatialtype = spatialtype, + ext = ext, + nuts_level = NULL, + level = NULL, + verbose = verbose + ) + + + filename <- basename(api_entry) + + # Improve speed using querys if country(es) are selected + # We construct the query and passed it to the st_read fun + + if (cache && !is.null(country)) { + gsc_message(verbose, "Speed up using sf query") + country <- gsc_helper_countrynames(country, "eurostat") + namefileload <- + gsc_api_cache( + api_entry, + filename, + cache_dir, + update_cache, + verbose + ) + + # Get layer name + layer <- tools::file_path_sans_ext(basename(namefileload)) + + # Construct query + q <- paste0( + "SELECT * from \"", + layer, + "\" WHERE CNTR_CODE IN (", + paste0("'", country, "'", collapse = ", "), + ")" + ) + + gsc_message(verbose, "Using query:\n ", q) + + + data_sf <- try( + suppressWarnings( + sf::st_read(namefileload, + quiet = !verbose, + query = q + ) + ), + silent = TRUE + ) + + # If everything was fine then output + if (!inherits(data_sf, "try-error")) { + data_sf <- sf::st_make_valid(data_sf) + return(data_sf) + } + + # If not don't update cache (was already updated) and continue + update_cache <- FALSE + rm(data_sf) + gsc_message( + TRUE, + "\n\nIt was a problem with the query.", + "Retrying without country filters\n\n" + ) + } + + + + + if (cache) { + # Guess source to load + namefileload <- + gsc_api_cache( + api_entry, + filename, + cache_dir, + update_cache, + verbose + ) + } else { + namefileload <- api_entry + } + + # Load - geojson only so far + data_sf <- gsc_api_load( + namefileload, epsg, ext, cache, + verbose + ) + + + return(data_sf) +} diff --git a/R/gisco_get_nuts.R b/R/gisco_get_nuts.R index 313ea8e9..669a361e 100644 --- a/R/gisco_get_nuts.R +++ b/R/gisco_get_nuts.R @@ -1,171 +1,171 @@ -#' Get GISCO NUTS `sf` polygons, points and lines -#' -#' @description -#' Returns -#' [NUTS regions](https://en.wikipedia.org/wiki/Nomenclature_of_Territorial_Units_for_Statistics) -#' polygons, lines and points at a specified scale, as provided by GISCO. -#' -#' NUTS are provided at three different levels: -#' * **"0"**: Country level -#' * **"1"**: Groups of states/regions -#' * **"2"**: States/regions -#' * **"3"**: Counties/provinces/districts -#' -#' Note that NUTS-level definition may vary across countries. See also -#' . -#' -#' @concept political -#' @family political -#' -#' @return A `sf` object specified by `spatialtype`. -#' -#' @param year Release year of the file. One of "2003", "2006, -#' "2010", "2013", "2016" or "2021". -#' -#' @param spatialtype Type of geometry to be returned: -#' * **"BN"**: Boundaries - `LINESTRING` object. -#' * **"LB"**: Labels - `POINT` object. -#' * **"RG"**: Regions - `MULTIPOLYGON/POLYGON` object. -#' -#' @param nuts_level NUTS level. One of "0", "1", "2" or "3". -#' See Description. -#' -#' @param nuts_id Optional. A character vector of NUTS IDs. -#' -#' @inheritParams gisco_get_countries -#' -#' @inheritSection gisco_get_countries About caching -#' -#' @seealso [gisco_nuts], [gisco_get_countries()] -#' -#' @source -#' -#' @export -#' -#' @examples -#' nuts2 <- gisco_get_nuts(nuts_level = 2) -#' -#' library(ggplot2) -#' -#' ggplot(nuts2) + -#' geom_sf() + -#' # ETRS89 / ETRS-LAEA -#' coord_sf( -#' crs = 3035, xlim = c(2377294, 7453440), -#' ylim = c(1313597, 5628510) -#' ) + -#' labs(title = "NUTS-2 levels") -#' \donttest{ -#' # NUTS-3 for Germany -#' germany_nuts3 <- gisco_get_nuts(nuts_level = 3, country = "Germany") -#' -#' ggplot(germany_nuts3) + -#' geom_sf() + -#' labs( -#' title = "NUTS-3 levels", -#' subtitle = "Germany", -#' caption = gisco_attributions() -#' ) -#' -#' -#' # Select specific regions -#' select_nuts <- gisco_get_nuts(nuts_id = c("ES2", "FRJ", "FRL", "ITC")) -#' -#' ggplot(select_nuts) + -#' geom_sf(aes(fill = CNTR_CODE)) + -#' scale_fill_viridis_d() -#' } -gisco_get_nuts <- function(year = "2016", - epsg = "4326", - cache = TRUE, - update_cache = FALSE, - cache_dir = NULL, - verbose = FALSE, - resolution = "20", - spatialtype = "RG", - country = NULL, - nuts_id = NULL, - nuts_level = "all") { - ext <- "geojson" - - nuts_level <- as.character(nuts_level) - - api_entry <- gsc_api_url( - id_giscoR = "nuts", - year = year, - epsg = epsg, - resolution = resolution, - spatialtype = spatialtype, - ext = ext, - nuts_level = nuts_level, - level = NULL, - verbose = verbose - ) - - filename <- basename(api_entry) - - # Check if data is already available - checkdata <- grep("NUTS_RG_20M_2016_4326", filename) - if (isFALSE(update_cache) & length(checkdata)) { - dwnload <- FALSE - data_sf <- giscoR::gisco_nuts - - gsc_message( - verbose, - "Loaded from gisco_nuts dataset. Use update_cache = TRUE to load", - " the shapefile from the .geojson file" - ) - - if (nuts_level %in% c("0", "1", "2", "3")) { - data_sf <- data_sf[data_sf$LEVL_CODE == nuts_level, ] - } - } else { - dwnload <- TRUE - } - if (dwnload) { - # Speed up if requesting units - if (!is.null(nuts_id) & spatialtype %in% c("RG", "LB")) { - data_sf <- gisco_get_units( - id_giscoR = "nuts", - unit = nuts_id, - mode = "sf", - year = year, - epsg = epsg, - cache = cache, - cache_dir = cache_dir, - update_cache = update_cache, - verbose = verbose, - resolution = resolution, - spatialtype = spatialtype - ) - } else { - if (cache) { - # Guess source to load - namefileload <- - gsc_api_cache( - api_entry, - filename, - cache_dir, - update_cache, - verbose - ) - } else { - namefileload <- api_entry - } - - # Load - geojson only so far - data_sf <- - gsc_api_load(namefileload, epsg, ext, cache, verbose) - } - } - if (!is.null(country) & "CNTR_CODE" %in% names(data_sf)) { - # Convert ISO3 to EUROSTAT thanks to Vincent Arel-Bundock (countrycode) - country <- gsc_helper_countrynames(country, "eurostat") - data_sf <- data_sf[data_sf$CNTR_CODE %in% country, ] - } - - if (!is.null(nuts_id) & "NUTS_ID" %in% names(data_sf)) { - data_sf <- data_sf[data_sf$NUTS_ID %in% nuts_id, ] - } - return(data_sf) -} +#' Get GISCO NUTS `sf` polygons, points and lines +#' +#' @description +#' Returns +#' [NUTS regions](https://en.wikipedia.org/wiki/Nomenclature_of_Territorial_Units_for_Statistics) +#' polygons, lines and points at a specified scale, as provided by GISCO. +#' +#' NUTS are provided at three different levels: +#' * **"0"**: Country level +#' * **"1"**: Groups of states/regions +#' * **"2"**: States/regions +#' * **"3"**: Counties/provinces/districts +#' +#' Note that NUTS-level definition may vary across countries. See also +#' . +#' +#' @concept political +#' @family political +#' +#' @return A `sf` object specified by `spatialtype`. +#' +#' @param year Release year of the file. One of "2003", "2006, +#' "2010", "2013", "2016" or "2021". +#' +#' @param spatialtype Type of geometry to be returned: +#' * **"BN"**: Boundaries - `LINESTRING` object. +#' * **"LB"**: Labels - `POINT` object. +#' * **"RG"**: Regions - `MULTIPOLYGON/POLYGON` object. +#' +#' @param nuts_level NUTS level. One of "0", "1", "2" or "3". +#' See Description. +#' +#' @param nuts_id Optional. A character vector of NUTS IDs. +#' +#' @inheritParams gisco_get_countries +#' +#' @inheritSection gisco_get_countries About caching +#' +#' @seealso [gisco_nuts], [gisco_get_countries()] +#' +#' @source +#' +#' @export +#' +#' @examples +#' nuts2 <- gisco_get_nuts(nuts_level = 2) +#' +#' library(ggplot2) +#' +#' ggplot(nuts2) + +#' geom_sf() + +#' # ETRS89 / ETRS-LAEA +#' coord_sf( +#' crs = 3035, xlim = c(2377294, 7453440), +#' ylim = c(1313597, 5628510) +#' ) + +#' labs(title = "NUTS-2 levels") +#' \donttest{ +#' # NUTS-3 for Germany +#' germany_nuts3 <- gisco_get_nuts(nuts_level = 3, country = "Germany") +#' +#' ggplot(germany_nuts3) + +#' geom_sf() + +#' labs( +#' title = "NUTS-3 levels", +#' subtitle = "Germany", +#' caption = gisco_attributions() +#' ) +#' +#' +#' # Select specific regions +#' select_nuts <- gisco_get_nuts(nuts_id = c("ES2", "FRJ", "FRL", "ITC")) +#' +#' ggplot(select_nuts) + +#' geom_sf(aes(fill = CNTR_CODE)) + +#' scale_fill_viridis_d() +#' } +gisco_get_nuts <- function(year = "2016", + epsg = "4326", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + verbose = FALSE, + resolution = "20", + spatialtype = "RG", + country = NULL, + nuts_id = NULL, + nuts_level = "all") { + ext <- "geojson" + + nuts_level <- as.character(nuts_level) + + api_entry <- gsc_api_url( + id_giscoR = "nuts", + year = year, + epsg = epsg, + resolution = resolution, + spatialtype = spatialtype, + ext = ext, + nuts_level = nuts_level, + level = NULL, + verbose = verbose + ) + + filename <- basename(api_entry) + + # Check if data is already available + checkdata <- grep("NUTS_RG_20M_2016_4326", filename) + if (isFALSE(update_cache) && length(checkdata)) { + dwnload <- FALSE + data_sf <- giscoR::gisco_nuts + + gsc_message( + verbose, + "Loaded from gisco_nuts dataset. Use update_cache = TRUE to load", + " the shapefile from the .geojson file" + ) + + if (nuts_level %in% c("0", "1", "2", "3")) { + data_sf <- data_sf[data_sf$LEVL_CODE == nuts_level, ] + } + } else { + dwnload <- TRUE + } + if (dwnload) { + # Speed up if requesting units + if (!is.null(nuts_id) && spatialtype %in% c("RG", "LB")) { + data_sf <- gisco_get_units( + id_giscoR = "nuts", + unit = nuts_id, + mode = "sf", + year = year, + epsg = epsg, + cache = cache, + cache_dir = cache_dir, + update_cache = update_cache, + verbose = verbose, + resolution = resolution, + spatialtype = spatialtype + ) + } else { + if (cache) { + # Guess source to load + namefileload <- + gsc_api_cache( + api_entry, + filename, + cache_dir, + update_cache, + verbose + ) + } else { + namefileload <- api_entry + } + + # Load - geojson only so far + data_sf <- + gsc_api_load(namefileload, epsg, ext, cache, verbose) + } + } + if (!is.null(country) && "CNTR_CODE" %in% names(data_sf)) { + # Convert ISO3 to EUROSTAT thanks to Vincent Arel-Bundock (countrycode) + country <- gsc_helper_countrynames(country, "eurostat") + data_sf <- data_sf[data_sf$CNTR_CODE %in% country, ] + } + + if (!is.null(nuts_id) && "NUTS_ID" %in% names(data_sf)) { + data_sf <- data_sf[data_sf$NUTS_ID %in% nuts_id, ] + } + return(data_sf) +} diff --git a/R/gisco_get_units.R b/R/gisco_get_units.R index a572e8f1..bd44cace 100644 --- a/R/gisco_get_units.R +++ b/R/gisco_get_units.R @@ -1,370 +1,370 @@ -#' Get geospatial units data from GISCO API -#' -#' @description -#' Download individual shapefiles of units. Unlike [gisco_get_countries()], -#' [gisco_get_nuts()] or [gisco_get_urban_audit()], that downloads a full -#' dataset and applies filters, [gisco_get_units()] downloads a single -#' shapefile for each unit. -#' -#' @concept political -#' @family political -#' -#' @return -#' A `sf` object on `mode = "sf"` or a dataframe on `mode = "df"`. -#' -#' @param id_giscoR Select the `unit` type to be downloaded. -#' Accepted values are "nuts", "countries" or "urban_audit". -#' -#' @param unit Unit ID to be downloaded. See Details. -#' -#' @param mode Controls the output of the function. Possible values are "sf" -#' or "df". See Value and Details. -#' -#' @param spatialtype Type of geometry to be returned: "RG", for `POLYGON` and -#' "LB" for `POINT`. -#' -#' @inheritParams gisco_get_countries -#' -#' @inheritSection gisco_get_countries About caching -#' -#' @details -#' The function can return a dataframe on `mode = "df"` or a `sf` object -#' on `mode = "sf"`. -#' -#' In order to see the available `unit` ids with the required -#' combination of `spatialtype, year`, first run the function on "df" -#' mode. Once that you get the data frame you can select the required ids -#' on the `unit` parameter. -#' -#' On `mode = "df"` the only relevant parameters are `spatialtype, year`. -#' -#' @note -#' Country-level files would be renamed on your `cache_dir` -#' to avoid naming conflicts with NUTS-0 datasets. -#' -#' Please check the download and usage provisions on [gisco_attributions()]. -#' -#' @author dieghernan, -#' @source -#' -#' @seealso [gisco_get_countries()] -#' -#' @examplesIf gisco_check_access() -#' \donttest{ -#' cities <- gisco_get_units( -#' id_giscoR = "urban_audit", -#' mode = "df", -#' year = "2020" -#' ) -#' VAL <- cities[grep("Valencia", cities$URAU_NAME), ] -#' # Order from big to small -#' VAL <- VAL[order(as.double(VAL$AREA_SQM), decreasing = TRUE), ] -#' -#' VAL.sf <- gisco_get_units( -#' id_giscoR = "urban_audit", -#' year = "2020", -#' unit = VAL$URAU_CODE -#' ) -#' # Provincia -#' Provincia <- -#' gisco_get_units( -#' id_giscoR = "nuts", -#' unit = c("ES523"), -#' resolution = "01" -#' ) -#' -#' # Reorder -#' VAL.sf$URAU_CATG <- factor(VAL.sf$URAU_CATG, levels = c("F", "K", "C")) -#' -#' # Plot -#' library(ggplot2) -#' -#' ggplot(Provincia) + -#' geom_sf(fill = "gray1") + -#' geom_sf(data = VAL.sf, aes(fill = URAU_CATG)) + -#' scale_fill_viridis_d() + -#' labs( -#' title = "Valencia", -#' subtitle = "Urban Audit", -#' fill = "Urban Audit\ncategory" -#' ) -#' } -#' @export -gisco_get_units <- function(id_giscoR = "nuts", - unit = "ES4", - mode = "sf", - year = "2016", - epsg = "4326", - cache = TRUE, - update_cache = FALSE, - cache_dir = NULL, - verbose = FALSE, - resolution = "20", - spatialtype = "RG") { - year <- as.character(year) - - cache_dir <- gsc_helper_cachedir(cache_dir) - unit <- unique(unit) - - - # Validations - if (!(id_giscoR %in% c("countries", "nuts", "urban_audit"))) { - stop('id_giscoR should be one of "countries","nuts","urban_audit"') - } - - if (!(mode %in% c("df", "sf"))) { - stop('mode should be one of "df","sf"') - } - - if (mode == "sf" & !(spatialtype %in% c("RG", "LB"))) { - stop('spatialtype should be one of "RG","LB"') - } - - if (is.null(unit) & mode == "sf") { - stop("Select unit(s) to download with unit = c('unit_id1','unit_id2')") - } - - # Convert to iso3c for countries 2001 - if (mode == "sf" & id_giscoR == "countries") { - if (year == "2001") { - unit <- gsc_helper_countrynames(unit, "iso3c") - } else { - unit <- gsc_helper_countrynames(unit, "eurostat") - } - } - - # Start getting urls and routes - level <- "all" - - if (id_giscoR == "urban_audit" & year < "2014") { - level <- "CITY" - } - - - api_entry <- - gsc_api_url( - id_giscoR, - year, - epsg, - resolution, - ext = "geojson", - spatialtype, - verbose = verbose, - level = level - ) - basename <- basename(api_entry) - - api_url <- unlist(strsplit(api_entry, "/geojson/"))[1] - remain <- unlist(strsplit(api_entry, "/geojson/"))[2] - - # Compose depending of the mode - if (mode == "df") { - df <- gsc_units_df(id_giscoR, year, api_url, verbose) - - return(df) - } else if (mode == "sf") { - sf <- gsc_units_sf( - id_giscoR, - unit, - year, - epsg, - cache, - update_cache, - cache_dir, - verbose, - spatialtype, - api_url, - remain, - level - ) - return(sf) - } -} - -#' Download sf for units -#' @noRd -gsc_units_sf <- function(id_giscoR, - unit, - year, - epsg, - cache, - update_cache, - cache_dir, - verbose, - spatialtype, - api_url, - remain, - level) { - cache_dir <- gsc_helper_cachedir(cache_dir) - - filename <- unit - - api_url <- file.path(api_url, "distribution") - - # Slice path - remain <- gsub(paste0("_", level), "", remain) - - filepattern <- tolower(gsub(".geojson", "", remain)) - - slice <- (unlist(strsplit(filepattern, "_")))[c(-1, -2)] - - # Remove year epsg and spatial type - slice <- slice[-grep(year, slice)] - slice <- slice[-grep(epsg, slice)] - - if (spatialtype == "LB") { - filepattern <- - paste0(paste("-label", epsg, year, sep = "-"), ".geojson") - filename <- paste0(filename, filepattern) - } else { - filepattern <- - paste0(paste("-region", slice, epsg, year, sep = "-"), ".geojson") - filepattern <- gsub("-rg", "", filepattern) - filename <- paste0(filename, filepattern) - } - - for (i in seq_len(length(filename))) { - fn <- filename[i] - if (id_giscoR == "countries") { - # Modify name for countries - fn <- gsub(unit[i], paste0(unit[i], "-cntry"), fn) - } - - if (cache) { - path <- try( - gsc_api_cache( - file.path(api_url, filename[i]), - fn, - cache_dir, - update_cache, - verbose - ), - silent = TRUE - ) - } else { - path <- file.path(api_url, filename[i]) - } - - - - if (inherits(path, "try-error")) { - gsc_message( - TRUE, - "\nSkipping unit = ", unit[i], "\nNot found" - ) - next() - } - - - iter_sf <- try( - gsc_api_load(path, epsg, "geojson", cache, verbose), - silent = TRUE - ) - - if (inherits(iter_sf, "try-error")) { - gsc_message( - TRUE, - "\nSkipping unit = ", unit[i], - "\n Corrupted file" - ) - next() - } - - - if (exists("df_sf")) { - df_sf <- rbind(df_sf, iter_sf) - } else { - df_sf <- iter_sf - } - } - - if (!exists("df_sf")) { - stop("No results for c(", paste0("'", unit, "'", collapse = ", "), ")", - call. = FALSE - ) - } - - # Last check - df_sf <- sf::st_make_valid(df_sf) - return(df_sf) -} - -#' Download data frame for units -#' @noRd -gsc_units_df <- function(id_giscoR, year, api_url, verbose) { - if (id_giscoR == "countries") { - if (year < "2013") { - csv <- "csv/CNTR_AT.csv" - } else { - csv <- paste0("csv/CNTR_AT_", year, ".csv") - } - } else if (id_giscoR == "urban_audit") { - if (year <= "2004") { - csv <- paste0("csv/URAU_CITY_AT_", year, ".csv") - } else if (year < "2018") { - csv <- "csv/URAU_AT_2011_2014.csv" - } else { - csv <- paste0("csv/URAU_AT_", year, ".csv") - } - } else if (id_giscoR == "nuts") { - csv <- paste0("csv/NUTS_AT_", year, ".csv") - } - - url <- file.path(api_url, csv) - - file.local <- tempfile(fileext = ".csv") - - err_dwnload <- try( - download.file( - url, - file.local, - quiet = isFALSE(verbose), - mode = "wb" - ), - silent = TRUE - ) - - # If error then try again - - # nocov start - - if (inherits(err_dwnload, "try-error")) { - gsc_message(verbose, "Retry query") - Sys.sleep(1) - err_dwnload <- try( - download.file( - url, - file.local, - quiet = isFALSE(verbose), - mode = "wb" - ), - silent = TRUE - ) - } - - # If not then stop - if (inherits(err_dwnload, "try-error")) { - gsc_message( - TRUE, - "\nurl \n ", - url, - "not reachable.\n\nPlease download manually.", - "If you think this is a bug please consider opening an issue on ", - "https://github.com/ropengov/giscoR/issues" - ) - stop("Download failed") - } - - # nocov end - - df_csv <- read.csv2( - file.local, - sep = ",", - stringsAsFactors = FALSE, - encoding = "UTF-8" - ) - - - gsc_message(verbose, "Database loaded succesfully") - return(df_csv) -} +#' Get geospatial units data from GISCO API +#' +#' @description +#' Download individual shapefiles of units. Unlike [gisco_get_countries()], +#' [gisco_get_nuts()] or [gisco_get_urban_audit()], that downloads a full +#' dataset and applies filters, [gisco_get_units()] downloads a single +#' shapefile for each unit. +#' +#' @concept political +#' @family political +#' +#' @return +#' A `sf` object on `mode = "sf"` or a dataframe on `mode = "df"`. +#' +#' @param id_giscoR Select the `unit` type to be downloaded. +#' Accepted values are "nuts", "countries" or "urban_audit". +#' +#' @param unit Unit ID to be downloaded. See Details. +#' +#' @param mode Controls the output of the function. Possible values are "sf" +#' or "df". See Value and Details. +#' +#' @param spatialtype Type of geometry to be returned: "RG", for `POLYGON` and +#' "LB" for `POINT`. +#' +#' @inheritParams gisco_get_countries +#' +#' @inheritSection gisco_get_countries About caching +#' +#' @details +#' The function can return a dataframe on `mode = "df"` or a `sf` object +#' on `mode = "sf"`. +#' +#' In order to see the available `unit` ids with the required +#' combination of `spatialtype, year`, first run the function on "df" +#' mode. Once that you get the data frame you can select the required ids +#' on the `unit` parameter. +#' +#' On `mode = "df"` the only relevant parameters are `spatialtype, year`. +#' +#' @note +#' Country-level files would be renamed on your `cache_dir` +#' to avoid naming conflicts with NUTS-0 datasets. +#' +#' Please check the download and usage provisions on [gisco_attributions()]. +#' +#' @author dieghernan, +#' @source +#' +#' @seealso [gisco_get_countries()] +#' +#' @examplesIf gisco_check_access() +#' \donttest{ +#' cities <- gisco_get_units( +#' id_giscoR = "urban_audit", +#' mode = "df", +#' year = "2020" +#' ) +#' VAL <- cities[grep("Valencia", cities$URAU_NAME), ] +#' # Order from big to small +#' VAL <- VAL[order(as.double(VAL$AREA_SQM), decreasing = TRUE), ] +#' +#' VAL.sf <- gisco_get_units( +#' id_giscoR = "urban_audit", +#' year = "2020", +#' unit = VAL$URAU_CODE +#' ) +#' # Provincia +#' Provincia <- +#' gisco_get_units( +#' id_giscoR = "nuts", +#' unit = c("ES523"), +#' resolution = "01" +#' ) +#' +#' # Reorder +#' VAL.sf$URAU_CATG <- factor(VAL.sf$URAU_CATG, levels = c("F", "K", "C")) +#' +#' # Plot +#' library(ggplot2) +#' +#' ggplot(Provincia) + +#' geom_sf(fill = "gray1") + +#' geom_sf(data = VAL.sf, aes(fill = URAU_CATG)) + +#' scale_fill_viridis_d() + +#' labs( +#' title = "Valencia", +#' subtitle = "Urban Audit", +#' fill = "Urban Audit\ncategory" +#' ) +#' } +#' @export +gisco_get_units <- function(id_giscoR = "nuts", + unit = "ES4", + mode = "sf", + year = "2016", + epsg = "4326", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + verbose = FALSE, + resolution = "20", + spatialtype = "RG") { + year <- as.character(year) + + cache_dir <- gsc_helper_cachedir(cache_dir) + unit <- unique(unit) + + + # Validations + if (!(id_giscoR %in% c("countries", "nuts", "urban_audit"))) { + stop('id_giscoR should be one of "countries","nuts","urban_audit"') + } + + if (!(mode %in% c("df", "sf"))) { + stop('mode should be one of "df","sf"') + } + + if (mode == "sf" && !(spatialtype %in% c("RG", "LB"))) { + stop('spatialtype should be one of "RG","LB"') + } + + if (is.null(unit) && mode == "sf") { + stop("Select unit(s) to download with unit = c('unit_id1','unit_id2')") + } + + # Convert to iso3c for countries 2001 + if (mode == "sf" && id_giscoR == "countries") { + if (year == "2001") { + unit <- gsc_helper_countrynames(unit, "iso3c") + } else { + unit <- gsc_helper_countrynames(unit, "eurostat") + } + } + + # Start getting urls and routes + level <- "all" + + if (id_giscoR == "urban_audit" && year < "2014") { + level <- "CITY" + } + + + api_entry <- + gsc_api_url( + id_giscoR, + year, + epsg, + resolution, + ext = "geojson", + spatialtype, + verbose = verbose, + level = level + ) + basename <- basename(api_entry) + + api_url <- unlist(strsplit(api_entry, "/geojson/"))[1] + remain <- unlist(strsplit(api_entry, "/geojson/"))[2] + + # Compose depending of the mode + if (mode == "df") { + df <- gsc_units_df(id_giscoR, year, api_url, verbose) + + return(df) + } else if (mode == "sf") { + sf <- gsc_units_sf( + id_giscoR, + unit, + year, + epsg, + cache, + update_cache, + cache_dir, + verbose, + spatialtype, + api_url, + remain, + level + ) + return(sf) + } +} + +#' Download sf for units +#' @noRd +gsc_units_sf <- function(id_giscoR, + unit, + year, + epsg, + cache, + update_cache, + cache_dir, + verbose, + spatialtype, + api_url, + remain, + level) { + cache_dir <- gsc_helper_cachedir(cache_dir) + + filename <- unit + + api_url <- file.path(api_url, "distribution") + + # Slice path + remain <- gsub(paste0("_", level), "", remain) + + filepattern <- tolower(gsub(".geojson", "", remain)) + + slice <- (unlist(strsplit(filepattern, "_")))[c(-1, -2)] + + # Remove year epsg and spatial type + slice <- slice[-grep(year, slice)] + slice <- slice[-grep(epsg, slice)] + + if (spatialtype == "LB") { + filepattern <- + paste0(paste("-label", epsg, year, sep = "-"), ".geojson") + filename <- paste0(filename, filepattern) + } else { + filepattern <- + paste0(paste("-region", slice, epsg, year, sep = "-"), ".geojson") + filepattern <- gsub("-rg", "", filepattern) + filename <- paste0(filename, filepattern) + } + + for (i in seq_len(length(filename))) { + fn <- filename[i] + if (id_giscoR == "countries") { + # Modify name for countries + fn <- gsub(unit[i], paste0(unit[i], "-cntry"), fn) + } + + if (cache) { + path <- try( + gsc_api_cache( + file.path(api_url, filename[i]), + fn, + cache_dir, + update_cache, + verbose + ), + silent = TRUE + ) + } else { + path <- file.path(api_url, filename[i]) + } + + + + if (inherits(path, "try-error")) { + gsc_message( + TRUE, + "\nSkipping unit = ", unit[i], "\nNot found" + ) + next() + } + + + iter_sf <- try( + gsc_api_load(path, epsg, "geojson", cache, verbose), + silent = TRUE + ) + + if (inherits(iter_sf, "try-error")) { + gsc_message( + TRUE, + "\nSkipping unit = ", unit[i], + "\n Corrupted file" + ) + next() + } + + + if (exists("df_sf")) { + df_sf <- rbind(df_sf, iter_sf) + } else { + df_sf <- iter_sf + } + } + + if (!exists("df_sf")) { + stop("No results for c(", paste0("'", unit, "'", collapse = ", "), ")", + call. = FALSE + ) + } + + # Last check + df_sf <- sf::st_make_valid(df_sf) + return(df_sf) +} + +#' Download data frame for units +#' @noRd +gsc_units_df <- function(id_giscoR, year, api_url, verbose) { + if (id_giscoR == "countries") { + if (year < "2013") { + csv <- "csv/CNTR_AT.csv" + } else { + csv <- paste0("csv/CNTR_AT_", year, ".csv") + } + } else if (id_giscoR == "urban_audit") { + if (year <= "2004") { + csv <- paste0("csv/URAU_CITY_AT_", year, ".csv") + } else if (year < "2018") { + csv <- "csv/URAU_AT_2011_2014.csv" + } else { + csv <- paste0("csv/URAU_AT_", year, ".csv") + } + } else if (id_giscoR == "nuts") { + csv <- paste0("csv/NUTS_AT_", year, ".csv") + } + + url <- file.path(api_url, csv) + + file.local <- tempfile(fileext = ".csv") + + err_dwnload <- try( + download.file( + url, + file.local, + quiet = isFALSE(verbose), + mode = "wb" + ), + silent = TRUE + ) + + # If error then try again + + # nocov start + + if (inherits(err_dwnload, "try-error")) { + gsc_message(verbose, "Retry query") + Sys.sleep(1) + err_dwnload <- try( + download.file( + url, + file.local, + quiet = isFALSE(verbose), + mode = "wb" + ), + silent = TRUE + ) + } + + # If not then stop + if (inherits(err_dwnload, "try-error")) { + gsc_message( + TRUE, + "\nurl \n ", + url, + "not reachable.\n\nPlease download manually.", + "If you think this is a bug please consider opening an issue on ", + "https://github.com/ropengov/giscoR/issues" + ) + stop("Download failed") + } + + # nocov end + + df_csv <- read.csv2( + file.local, + sep = ",", + stringsAsFactors = FALSE, + encoding = "UTF-8" + ) + + + gsc_message(verbose, "Database loaded succesfully") + return(df_csv) +} diff --git a/R/gisco_get_urban_audit.R b/R/gisco_get_urban_audit.R index f4e2f637..45d4c976 100644 --- a/R/gisco_get_urban_audit.R +++ b/R/gisco_get_urban_audit.R @@ -1,103 +1,103 @@ -#' Get GISCO greater cities and metropolitan areas `sf` polygons and points -#' -#' @description -#' Returns polygons and points corresponding to cities, greater cities and -#' metropolitan areas included on the -#' [Urban Audit report](https://ec.europa.eu/eurostat/web/regions-and-cities) -#' of Eurostat. -#' -#' @concept political -#' @family political -#' -#' @return A `sf` object specified by `spatialtype`. -#' -#' @param year Release year of the file. One of "2001", "2004", -#' "2014", "2018" or "2020". -#' -#' @param spatialtype Type of geometry to be returned: -#' * **"LB"**: Labels - `POINT` object. -#' * **"RG"**: Regions - `MULTIPOLYGON/POLYGON` object. -#' -#' @param level Level of Urban Audit. Possible values are "CITIES", "FUA", -#' "GREATER_CITIES" or `NULL`, that would download the full dataset. -#' -#' @inheritParams gisco_get_countries -#' -#' @inheritSection gisco_get_countries About caching -#' -#' @source -#' -#' @seealso [gisco_get_communes()], [gisco_get_lau()] -#' -#' @export -#' -#' @note -#' Please check the download and usage provisions on [gisco_attributions()]. -#' -#' @examplesIf gisco_check_access() -#' \donttest{ -#' cities <- gisco_get_urban_audit(year = "2020", level = "CITIES") -#' -#' bcn <- cities[cities$URAU_NAME == "Barcelona", ] -#' -#' library(ggplot2) -#' ggplot(bcn) + -#' geom_sf() -#' } -gisco_get_urban_audit <- function(year = "2020", - epsg = "4326", - cache = TRUE, - update_cache = FALSE, - cache_dir = NULL, - verbose = FALSE, - spatialtype = "RG", - country = NULL, - level = NULL) { - ext <- "geojson" - - api_entry <- gsc_api_url( - id_giscoR = "urban_audit", - year = year, - epsg = epsg, - resolution = 0, - # Not necessary - spatialtype = spatialtype, - ext = ext, - nuts_level = NULL, - level = level, - verbose = verbose - ) - - filename <- basename(api_entry) - - if (cache) { - # Guess source to load - namefileload <- - gsc_api_cache( - api_entry, - filename, - cache_dir, - update_cache, - verbose - ) - } else { - namefileload <- api_entry - } - - # Load - geojson only so far - data_sf <- gsc_api_load( - namefileload, - epsg, - ext, - cache, - verbose - ) - - - if (!is.null(country) & "CNTR_CODE" %in% names(data_sf)) { - # Convert ISO3 to EUROSTAT thanks to Vincent Arel-Bundock (countrycode) - country <- gsc_helper_countrynames(country, "eurostat") - data_sf <- data_sf[data_sf$CNTR_CODE %in% country, ] - } - return(data_sf) -} +#' Get GISCO greater cities and metropolitan areas `sf` polygons and points +#' +#' @description +#' Returns polygons and points corresponding to cities, greater cities and +#' metropolitan areas included on the +#' [Urban Audit report](https://ec.europa.eu/eurostat/web/regions-and-cities) +#' of Eurostat. +#' +#' @concept political +#' @family political +#' +#' @return A `sf` object specified by `spatialtype`. +#' +#' @param year Release year of the file. One of "2001", "2004", +#' "2014", "2018" or "2020". +#' +#' @param spatialtype Type of geometry to be returned: +#' * **"LB"**: Labels - `POINT` object. +#' * **"RG"**: Regions - `MULTIPOLYGON/POLYGON` object. +#' +#' @param level Level of Urban Audit. Possible values are "CITIES", "FUA", +#' "GREATER_CITIES" or `NULL`, that would download the full dataset. +#' +#' @inheritParams gisco_get_countries +#' +#' @inheritSection gisco_get_countries About caching +#' +#' @source +#' +#' @seealso [gisco_get_communes()], [gisco_get_lau()] +#' +#' @export +#' +#' @note +#' Please check the download and usage provisions on [gisco_attributions()]. +#' +#' @examplesIf gisco_check_access() +#' \donttest{ +#' cities <- gisco_get_urban_audit(year = "2020", level = "CITIES") +#' +#' bcn <- cities[cities$URAU_NAME == "Barcelona", ] +#' +#' library(ggplot2) +#' ggplot(bcn) + +#' geom_sf() +#' } +gisco_get_urban_audit <- function(year = "2020", + epsg = "4326", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + verbose = FALSE, + spatialtype = "RG", + country = NULL, + level = NULL) { + ext <- "geojson" + + api_entry <- gsc_api_url( + id_giscoR = "urban_audit", + year = year, + epsg = epsg, + resolution = 0, + # Not necessary + spatialtype = spatialtype, + ext = ext, + nuts_level = NULL, + level = level, + verbose = verbose + ) + + filename <- basename(api_entry) + + if (cache) { + # Guess source to load + namefileload <- + gsc_api_cache( + api_entry, + filename, + cache_dir, + update_cache, + verbose + ) + } else { + namefileload <- api_entry + } + + # Load - geojson only so far + data_sf <- gsc_api_load( + namefileload, + epsg, + ext, + cache, + verbose + ) + + + if (!is.null(country) && "CNTR_CODE" %in% names(data_sf)) { + # Convert ISO3 to EUROSTAT thanks to Vincent Arel-Bundock (countrycode) + country <- gsc_helper_countrynames(country, "eurostat") + data_sf <- data_sf[data_sf$CNTR_CODE %in% country, ] + } + return(data_sf) +} diff --git a/R/utils_downloads.R b/R/utils_downloads.R index 1d040e2d..0861c19e 100644 --- a/R/utils_downloads.R +++ b/R/utils_downloads.R @@ -249,7 +249,7 @@ gsc_api_cache <- fileoncache <- file.exists(file.local) # If already cached return - if (isFALSE(update_cache) & fileoncache) { + if (isFALSE(update_cache) && fileoncache) { gsc_message( verbose, "\nFile already cached\n", @@ -441,7 +441,9 @@ gsc_unzip <- # Extract files outfiles <- infiles[grep(ext, infiles$Name), ]$Name - gsc_message(verbose, "Extracting files:\n", paste0(outfiles, collapse = "\n"), "\n") + gsc_message(verbose, "Extracting files:\n", paste0(outfiles, + collapse = "\n" + ), "\n") allfiles <- list.files(cache_dir) diff --git a/R/utils_names.R b/R/utils_names.R index 8ac63b4b..696dd4fe 100644 --- a/R/utils_names.R +++ b/R/utils_names.R @@ -1,105 +1,108 @@ -#' Helper function to convert country names to codes -#' -#' Convert country codes -#' -#' @param names vector of names or codes -#' -#' @param out out code -#' -#' @return a vector of names -#' -#' @noRd -gsc_helper_countrynames <- function(names, out = "eurostat") { - maxname <- max(nchar(names)) - if (maxname > 3) { - outnames <- countrycode::countryname(names, out) - } else if (maxname == 3) { - outnames <- countrycode::countrycode(names, "iso3c", out) - } else if (maxname == 2) { - outnames <- countrycode::countrycode(names, "eurostat", out) - } else { - stop("Invalid country names. Try a vector of names, ISO3 codes or Eurostat codes") - } - linit <- length(outnames) - outnames2 <- outnames[!is.na(outnames)] - lend <- length(outnames2) - if (linit != lend) { - f <- paste(names[is.na(outnames)], sep = ",", collapse = ",") - warning( - paste( - "Countries ommited: ", - f, - ". Review the names of switch to ISO3 or Eurostat codes.", - sep = " " - ) - ) - } - return(outnames2) -} - -#' Convert sf object to UTF-8 -#' -#' Convert to UTF-8 -#' -#' @param data_sf data_sf -#' -#' @return data_sf with UTF-8 encoding. -#' -#' @source Extracted from **sf** package. -#' -#' @noRd -gsc_helper_utf8 <- function(data_sf) { - # From sf/read.R - https://github.com/r-spatial/sf/blob/master/R/read.R - set_utf8 <- function(x) { - n <- names(x) - Encoding(n) <- "UTF-8" - to_utf8 <- function(x) { - if (is.character(x)) { - Encoding(x) <- "UTF-8" - } - x - } - structure(lapply(x, to_utf8), names = n) - } - # end - - # To UTF-8 - names <- names(data_sf) - g <- sf::st_geometry(data_sf) - - which.geom <- - which(vapply(data_sf, function(f) { - inherits(f, "sfc") - }, TRUE)) - - nm <- names(which.geom) - - data_utf8 <- - as.data.frame(set_utf8(sf::st_drop_geometry(data_sf)), - stringsAsFactors = FALSE - ) - - # Regenerate with right encoding - data_sf <- sf::st_as_sf(data_utf8, g) - - # Rename geometry to original value - newnames <- names(data_sf) - newnames[newnames == "g"] <- nm - colnames(data_sf) <- newnames - data_sf <- sf::st_set_geometry(data_sf, nm) - - return(data_sf) -} - - -#' Helper for display messages on verbose -#' -#' @noRd -gsc_message <- function(verbose, ...) { - dots <- list(...) - msg <- paste(dots, collapse = " ") - - if (verbose) message(msg) - - return(invisible()) -} +#' Helper function to convert country names to codes +#' +#' Convert country codes +#' +#' @param names vector of names or codes +#' +#' @param out out code +#' +#' @return a vector of names +#' +#' @noRd +gsc_helper_countrynames <- function(names, out = "eurostat") { + maxname <- max(nchar(names)) + if (maxname > 3) { + outnames <- countrycode::countryname(names, out) + } else if (maxname == 3) { + outnames <- countrycode::countrycode(names, "iso3c", out) + } else if (maxname == 2) { + outnames <- countrycode::countrycode(names, "eurostat", out) + } else { + stop(paste0( + "Invalid country names. Try a vector of names,", + " ISO3 codes or Eurostat codes" + )) + } + linit <- length(outnames) + outnames2 <- outnames[!is.na(outnames)] + lend <- length(outnames2) + if (linit != lend) { + f <- paste(names[is.na(outnames)], sep = ",", collapse = ",") + warning( + paste( + "Countries ommited: ", + f, + ". Review the names of switch to ISO3 or Eurostat codes.", + sep = " " + ) + ) + } + return(outnames2) +} + +#' Convert sf object to UTF-8 +#' +#' Convert to UTF-8 +#' +#' @param data_sf data_sf +#' +#' @return data_sf with UTF-8 encoding. +#' +#' @source Extracted from **sf** package. +#' +#' @noRd +gsc_helper_utf8 <- function(data_sf) { + # From sf/read.R - https://github.com/r-spatial/sf/blob/master/R/read.R + set_utf8 <- function(x) { + n <- names(x) + Encoding(n) <- "UTF-8" + to_utf8 <- function(x) { + if (is.character(x)) { + Encoding(x) <- "UTF-8" + } + x + } + structure(lapply(x, to_utf8), names = n) + } + # end + + # To UTF-8 + names <- names(data_sf) + g <- sf::st_geometry(data_sf) + + which.geom <- + which(vapply(data_sf, function(f) { + inherits(f, "sfc") + }, TRUE)) + + nm <- names(which.geom) + + data_utf8 <- + as.data.frame(set_utf8(sf::st_drop_geometry(data_sf)), + stringsAsFactors = FALSE + ) + + # Regenerate with right encoding + data_sf <- sf::st_as_sf(data_utf8, g) + + # Rename geometry to original value + newnames <- names(data_sf) + newnames[newnames == "g"] <- nm + colnames(data_sf) <- newnames + data_sf <- sf::st_set_geometry(data_sf, nm) + + return(data_sf) +} + + +#' Helper for display messages on verbose +#' +#' @noRd +gsc_message <- function(verbose, ...) { + dots <- list(...) + msg <- paste(dots, collapse = " ") + + if (verbose) message(msg) + + return(invisible()) +} diff --git a/README.Rmd b/README.Rmd index 168d2bb7..12e370a9 100644 --- a/README.Rmd +++ b/README.Rmd @@ -1,8 +1,5 @@ --- output: github_document -editor_options: - markdown: - wrap: 80 --- diff --git a/README.md b/README.md index ba747c22..3a3d96c1 100644 --- a/README.md +++ b/README.md @@ -336,7 +336,7 @@ A BibTeX entry for LaTeX users is doi = {10.5281/zenodo.4317946}, author = {Diego Hernangómez}, year = {2023}, - version = {0.3.2.9000}, + version = {0.3.3}, url = {https://ropengov.github.io/giscoR/}, abstract = {Tools to download data from the GISCO (Geographic Information System of the Commission) Eurostat database . Global and European map data available. This package is in no way officially related to or endorsed by Eurostat.}, } diff --git a/codemeta.json b/codemeta.json index f2aa77f3..5d0fc651 100644 --- a/codemeta.json +++ b/codemeta.json @@ -8,7 +8,7 @@ "codeRepository": "https://github.com/rOpenGov/giscoR", "issueTracker": "https://github.com/rOpenGov/giscoR/issues", "license": "https://spdx.org/licenses/GPL-3.0", - "version": "0.3.2.9000", + "version": "0.3.3", "programmingLanguage": { "@type": "ComputerLanguage", "name": "R", @@ -204,7 +204,7 @@ "applicationCategory": "cartography", "isPartOf": "http://ropengov.org/", "keywords": ["ropengov", "r", "spatial", "api-wrapper", "rstats", "r-package", "eurostat", "gisco", "thematic-maps", "eurostat-data", "cran", "ggplot2", "gis"], - "fileSize": "1396.68KB", + "fileSize": "1393.212KB", "citation": [ { "@type": "SoftwareSourceCode", diff --git a/data/gisco_countrycode.rda b/data/gisco_countrycode.rda index 7dd9721df92e877a9feb4a8bcf9d1f5bbae866b3..a096d5cca3fd5873943991f40959b0d76fde7f3c 100644 GIT binary patch literal 5060 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 diff --git a/data/gisco_db.rda b/data/gisco_db.rda index f6e778c72543b9b23d877bd286cdc687de466810..28cef8203d9bdcb0516c802f663d75a6c39b8670 100644 GIT binary patch literal 976 zcmV;>126pjH+ooF0004LBHlIv03iV!0000G&sfahF(U(%T>vQ&2UJ%gRpOV=m zVLY=O$8P(6bs^RCy)47U6cX!>)kebaIU;nf$a}a%sn;9*clnu?+!2AaQ=6+ZXH+`6 z(tuWxBRZWlG{rc|K|J9U3+L^oUFWrHuU)Qq0HtYE9=Ly2aglx+H%%mAkRljHe(kFU zz2c0U8lX6xm~Q%%mEJyY9g%agDb<~LSYoDSauvVfSSC3+C-0Y*#B$!WA$=eoL)21X zau*5gjVA4?ny4A+?&12Sb>C6t*Z18H0iVev&wou)EvqDnXjel;iX{y$MA5Lsy5F6L zeBx|qr@R>F$d;n){OqH@0I;Z_YxxdS-VW3-CsjppIUxrM1A#u(Rii01{7{{1a`0PQ zqvmgBI-@GDX-FF+=Yo60+EcxJ+#x|%XHS`8QhLi&j4A9Qp`&I zKO~CVr9rP(e=YqqyzcixruiaBLkd$A|HWCx^~z-|B)CoK)AK}2r+mW8_H zWR+#r;ilo`sW1O=<7kb~2a_|vqHnsVt5NcAje;wVZi^;7@r`;1ZEoySMU3vDh#}+h z+(VMoXiNq{y`zI(5@3%6~&J{B-APKE%!2}ee7merLqd}wNx0tOpeUVOFlvlL9*U>qXWN~c08#?XBX zT7BPA3Q6`Q=w2q9-FaZIPHd!xCE>%`ViEN-ntHL*gek8NE@&vkROUghA`Nct&9 yMORmI1f$|J{Sx4OJzjqp1ONb3b?ZU^0jvk4VgLX{Nb#0FFb#_W000000a;oVtJ;PD literal 1001 zcmVr&VX%&Zq=l|>|uN8o>nO%fwaJ;?EzX=Ri#Wy zVe0l01xRV8ltlT#Rw1PQjr)VfY_Lnhf^pIn+Rl|o&UfE;ceXE1tXkeb&1X(C9LFWN zR3gD8l0Zx)z~up#;?m&0*43T1sdQQ#m)rzxh$$dm>l8^t^^lnAd9JepdEK*HYEMzUj_xuQNfoU7&AccU_`H}C;YEU%0y4b< zrW{a+J3Io3rEugXLPj%f1YHxg>4l1oc`-t?FLBRidk!vn@fL%guh^agit%jbuk3KH za=RFrE5ggTOy17+PMX)d++7FF8@6TH(^pSwe8mQy%aVWIuCGla?R69>=#)whE^Zr= zDDCo6X}8GlNcjTOGA+~ITkXuV50*Eua*vlxz97P7Wd#0^H6iAF61L5|hjGxCl`l$s z)l8g%NGIJ;7ICwYLZwAx8;q9Bi6X5SHXpO|>aU1|e1N4|1xuCs-_{V_qrFe%lSU1< z4(qjYeV@WM^+iMxGoxgN6Ch!qZA68GW;bXImUwH>|wcM!6 zN)WJAW^l=U(bddvj@jd_)*0`dTfEcn@~&x(l?=l$48t%C!!Z906MX*&1MP=96yOK6 zA|EINTXRgqb9J*fJXQvmnraV~fo3_~VRno}v@J|KK2~ZK0#NV)D|KrBep<}5U^FTq z^gkE)n&45HY&+=jlZ{CLU!WeJuxJt3A+hlw*Bf$_xhYW7NGVgW7o;4cE+CDnT<`yo zOd3M1+>F9P!RpP%NtE#^Q`3}M^>a-b!2eq+hSt}N`SBy9U8bfjh`;4?L@XqU0F2Pb z|8b0q6Gu%Ml;&V!kCMk~>DwW6VxesL2t?pE0f<8_nIQNGGh=i_ImBdIXw=ox34Nw5 zs|8O-#H4SO9{gA=ox85(yc2}+QK2`EX7}~B=47>YR`YDrQo&8==#Fdat+98ZpBLb< zA;far$(iYH0%_JAOLcYCa4#(lgQmNE z9Ms=Pg53rZ*HlYa&U6Da)3B|9*Y4#^)@j@Pp2e9z1;4~ka2bt8zh=AFHdF_94=Xbr X)m5`+HsFKSZ}|HIRCVh@BryO0b(--b diff --git a/data/tgs00026.rda b/data/tgs00026.rda index f56fb5cd7d2b5a735b06079487ad7491eb04a3fc..94388ec2c992d212233042715c1a01112fb8443a 100644 GIT binary patch literal 4816 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 literal 5015 zcmX|Fdpy(o|DW0179lpb+;6#TVRRQFgyUX}tyv~TT0(9W%OuM+Y%51|EBD+s#uUn> zaB|Nz)F>j9(BNyP_j>H{zQ3QZ%lr9x{xK^|;2|SRZ*6z)@yd&ypu(w}J3BkE zLtT4szQ4IMvvqT8=Jl^DT}m56{PmrUoetkCvj`RQt(MvpaOR~f^oYHU$SMc~60rap z!6gdN`UQD<+6{QR|8hd(RR=Qj?weT*LG#fUw)_%QqEh`geUpd)Y% zEjSF^0)b>bemM$Sfbn$t$vAOHx2c&0z5n84UiYJujAV3lUOH$9I4o$P00JopI+YNe z`?Q7bJDDmMTHbRXo-5#BU zw1PzA0AG7Rfk69b@Tb#ogotG8JuG?PmN{64Rx;}8F0H#mIs-=T4q^zr9^Hc-WG*#Bc8_ZNX@h(?dl z{z+X-Puitl{}wZqS+JHGfLR>k?!IA}

pY2z2?=lANjK@52KT7)@u=sc;+JQ)Vaj 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 J>& diff --git a/giscoR.Rproj b/giscoR.Rproj index f332bedd..b07e3df9 100644 --- a/giscoR.Rproj +++ b/giscoR.Rproj @@ -19,5 +19,6 @@ BuildType: Package PackageUseDevtools: Yes PackageInstallArgs: --no-multiarch --with-keep.source PackageRoxygenize: rd,collate,namespace,vignette + MarkdownWrap: Column MarkdownWrapAtColumn: 80 diff --git a/img/README-thematic-1.png b/img/README-thematic-1.png index 1fff255401872c86de179e7a3a297d424de104fa..303e9315eae463ce0bc9b8917dde0adb6cae2e16 100644 GIT binary patch delta 765307 zcmc$_bySqy8!n8m0g8&EfP#cbr?j+6D6PQIA<`{5^n)lM-CYXOEgb_2(k0zPcMP2~ zaQ5K)JLjKoo%K84ch>q?E@7T$X7;}KzT>*Cdq3$Y_IVV05yfjrjPJ{98K%_NStBF) z432QrSg|8~X{?HP)qip_HT8X}S1O^`4LtvU8asD!r&>~SpHgvr+H$TxAb7S^U3e;> zpV!HA$X~yAl9iJ!CtS^+M*emu*!G;Me`q*=ta`i5edW>3Gr4>=5&o*H9#7P#$~o2y z`qr)MGja+QmLDRyo3#OO`U%x>!z)H;>*?`b@H%yxoE zoU8ku-6vD$%XUoBe!w~weEO-e0O#w^xg}W~&zBG5;ydei3geO-RJ=-#tX^07@X&AS z#vFXi(^CH3VBg$kX)Dqix8MCck4vzma?VjwYfafQj?DKGFD2AhvLAbizb7J~liWhm zLOZeP-Em=6S;^eqJx#kqxK~EO!4Wh(|GuGimkcw*^s`<0@Dak!xqCNOa7tPzfCU9@Z5VPOQ@h1W9Tv(j0o;(!6mVOS4?mhc#n#kn(ATGm>?#9;# z)sokC*-$);R$&nHC=+)!X1E~gYF#$F%H5D7W2vCqUAqiW;ng_=?qO@%JdP(i&GY=6 z5GRyi<-uxCRZ)#q2yaz*{$Z-07++UU8iFcMn!i(|LZ&|JZ8=xumc8Z&2VHqiw|-lL zso)6TMH(@b#J%xA@>qhy4TnNq_kmzTel$m&ZNN395KHJdUGDmi)}gWiH1qixam@|1 zBvg5$=tmh-5BNq+UH0*Zz~n@a_vSiiBl)!aLcWEqW)T^>?SS0Z1!cJ`JEF0gC=a7g zV9QIG7T%d9=&hA5e9>C2yUhR1+~Da_t+fQIn!mH(s^ROewZ(Y}bAC#~+%Kmr$8A3AwV<^?IYENzV+ z@-J!Bw7)<9G%9GTE~8*P673D;CC9-9(_=?TAYCW-^P(<%3vHQ&URK)<>pkCG9AHV& zdUu$GTe30@F+7fAr*M*aw}5MVLy~9Awa~*pqif`2)kx}xd~L(6lPWIxg$6(NtA2)3 zHP=1NUu~#mOmD@fk`7-HuRKu;g=c8T;uNgA3dFQP6Y$ka9YogO7G)5 zH_b~T&m^BBJ=<&AE)y)=6pU`twkg}+Cq3ABlN%7yQ11EX&(MkferI&r356~KlZu*= zg>U^C8a5aC{wirR->#T-J4lQ_#t;q#Pd@u#JB2PoHBxg0!E@#}xl$EYR+Ephvp%UyG1oT^kQ@7Zk?DE6<^YK&hX9g+=HaN6G*&Baw{ z^m>W(mJs*#fzBSJL>}?zTDtGnph4ttmzJHdBrkK-9)4^h;}qcBa}~JeA_tuRPgUi#}xg{YmMql(UUlAejNjP)TX64~D#Z`~XkI<46 zt16l&FyF(G*q@l8;WGPGAPUI`id+Oj!oYu2R~WcRw6^w3=v#7(a8uvz-3i>dd^ ziPsn$3Nm-xb7aviFDi4y!J&?0Ii-Jf2`5w&B&F8rKYwsv{DMr^H1MT!)F*eD3@x#CFbTsesGr%=u3UMPOz=J*Fdc1%J zT@!1-sM=U0qk03>pYIe$$S>5E7W!t0lFjXjl>F_g-R10agfSlq;l6z$CLYNR%gN8w z-!w7bG?`N#Z7kMOxAUEqhF;OZ!cPvG){4GPs}iJmU%d+9h4}k@IoVk$k)_KrH#1pT ziM?OJ&1m&@pfB%>cXm~p90!?%b30@bT7{`ij2}`?xqk_8 zp(MeG9Gfee`HO4IC@H<_7#JEG=xzu9XILctFu zhD%@nr1D?FVHofz1HW)QU^z4n&$9(YML*4gB$Gwn5vfRs0}@#9CO7znLq%|P@-+l! zK|K~G(!B{T>|Bq(hrQt`WN)&Pk%9|31l^Q&sb;Es04~non#Brvjqh4(*^Gs>c zyot)+OH%>YzKWwY?_h6+ss`sHlQ%0>Ycg&WTmcu3Z**P9-gusT^oRs9o7+rjL5%T% z3asQN3@*2dVpA&k+4;R0$J|G5&6AVj#SA9@+(XO``UiU_^fY;@4$@otmD19|lV@sS znsMZUyaO5Td3erT62QZ|oiDKX-UY$26kl51M3R7_<>DL9n<$&64c}c;HRPVXx^T z7;CVWUHrWH@_~x?f4*S&YXSE4^KbtyC-#Lm)*1f&x$nPtVFdQ&oB#F$(0@MtUw`8N z?guW$|Nm^o|NA*X|LsEkuOVQDBo{B7*+80rGRJKH;jORED0;so>|qLS+@QbME6*Kw zf6RjuDh8TqJ@F4F2CccVU$P2Q>RZ1n^4z+0If7cEGvHx-9P~glHhz?ZudIU2%+l)3 zfLdN^XUkVwM#hx)BF*BGEp_fB_a5#)7GmP17B~~LK%d4c6jLgNhey=YNzrDT#jlQ? zxHMU?$mOvH=671O3yfAjdl(n@<+n702#-YSQ35sdQ9AGthR+vHb6@tnTie}!pZAyp zpqJ%(H#3O%p3%w5VtPf$gV_6RQc^Nj6r9|w@yt!iW;)PMf77WD3v$tO0FTwBk^_iO zDY-eh!tRB}Q&+j8(I08a8dK_C^HI?<@^gqh=A0kwQKA)^oLE(6omtVSm6amDjF`xN zW={P{tYyF?ChE16bUVnqlnqlNcmJuo ztpD;LT(q9(2(9vNY}lcuVpGIe_F#u0nH%QPcKC;ON^Gb*__B(8g`=agqXZZY!nq%G zxfqOlql{I5k+J4;!|Qk^ZBe(A)Ply6$+)9m!#%pTv>{#yXF{QGR+;zA;Y>9bSP-2#*-qi9B;YLkob_*iA+03WYn{~Hp&CXjY{Xcu-{6t+?NsbY=E$XfX6 z^6{Zwn143EHg$2Or0?S37(*pKsi>*kp%Kum3M8#M+yJxP9nCTnZXy!msZrQO2{e()YG53(Hr zS6aqEpK_JV?8c$naZL1d0Gg$?xABBWMt)iP_N#*OGZKP!=on~tIRzfm$hz$$D&R$T=FjYKb(gwH$8$c~8LSM4e@)3DLr(vDao&4j3CIMxl#a ziX#6$n2z@ZYOfHRzvr{(*>x52#HhS?S7+a!5cRNC z97GMu`!R#6`~2}==R7wCT)}TUB~n}BBW>90`A&eCU~06|VGmNMM1ST)BEWEdfT#Pw zwmfWEsmO*iGG6lrC-PTJrs#^&w_o42&`|AO?}d$*I0;JG?kqsUuQ=le+06`=G^D#1 zZm2N=dv0)Dth0BR678XVi=pBQ0DDAQvNM2CQW-n;B-VqB)8PNM769RS+{nDxGwTkw zmvj-92}K_ozr^u(?#^rcJQ^bxg*uC1Y3Z3t+0KYSBP=5PT;DYowAt$H`0ex)Od?026l5*Esv?3QAQ71tL&MLX=Glx9?5IMYd{k1e>c|eN zS?E-;9Arpilqk5^J7O$k^L&{DjiyX04-WJtjqzBYoSbb1fE+!Pe zu32;dfZ*rYO0V9mBQ%Ge)wrmLBounD-+l9e_h7^=xPq?8&Y@^k>{F2cPiD9{TT`sRC@}`BDZp3bqvodd?4snSlJmYRlP% zl*|IkXQQ_EqFjRJO{%aWe%MZ{^hnDx0d9GO>aGWC ze<3e?*sT-BHE!_+_ytkDBAEYujlapga7GW__DcilrPhG|46Uxu^+I2Lywl_)aj!8nMK(|Bih3j;l*uwhWf(aP z{30mb-#^>Y)$yAXDYlHHv)LPfUJC13#SO5rkEyknn;|Y3U(i$21ZJZ z5U3_NSCwE&Ya)k*_L&sgRYWeLuYvPjn>5Ni_cF$=k8sI3g=#K_YFKiq0;M304%hTv zc#}iJ!y^%Xpi3-x4@eB;bhp%<&z(e2vTm3}CyPN|{!91JLq?@nh+t7j{FZS8x1rYt zAC>{xS&?6PNEWr76Wa@U8&{kqFiCZp@UpF9a(xxJ;w?{JsTNBMh+bzh$7Vf-#J|wR zEUI?RxHPHTCyWcf`6KSJ^jqfL+xKvngcM%NPAt|h?!j~1+YUoz;|E*r?}TV1xvN}B zHsLG^$f>UWVczx|!L@VnYR7D<6PXs6h!dtZVTV-XzeEDTA9b3vyM71>%uoyu|8$wc zfZKI#nV%n?*IVpdJtwVokr4h82=90`i3!)<-}ae0qAmyXW}aSaj5kRM*89G~Pqn0I z<)W+}aM(#lP=NGgOZ%-sYsBVVk!D&Wb2(U!taS}e8^fNr{3UYN?Ay3M$&D)78Uf)1 zN`6c7C;NvlC=-$-$&)+Ql1eQq#+8{7KphD@3H#6Z-52>`UCT`6hohq`yd^3q&4{gb zF{ZGamjOqd`fbd^CrP={=dM4mNJ&d~-}6Bd#H$tVCgRuGB3qMtYkLBIw$w)sjWpQL z>|^)~*u-=RMNmm4t3PLeOS(K zZ+vg=9-%1R@`Ke(SG|aj+6U|!DVyGWx06>(oKmZ!7YXL9b?e%eb-bubAB-_i+ARD{ zGj}f1OoKcP;l9o@J+uB~Q3Zr6xy|W_bB~b&kuK~bq*`Z_PxP?`LtG$;FjeR-0V!-k z$Y|4(sGsx3YdP=}hE|m4e?>Z<8u@*`9ygGn>a=KX{@d|Z>HN_lhpmyJqA7dLs(Ra# z^CpOrIIdUofJeZ|cp&l4m6;jZbK6_yXHT8>r}Q5-}eYZYuvLh?+6UbC?DeQbhMn>{)1b;_HdDYXj7=v zKH^92>sML>uE&?Af-l9Kr=V#70^*A2Eaxt9==xCjea_qw{ggUFTETLwi=ob=&@so% zY(<{Y{lcFuoNTc$3t$}K#UO}$Zt!4f8-RNDV~U)~vZz@ZCK?d;q~?J5yS?O9Od6XWw;mmsV0$WKlzi6n7?(4fo0fk;2A%n3`p@Z7LDE>IAT6W1 zhmSk{kc#POQEWa;C;GTUq{&_RMBB~hP-o1}zFJ8Eg97v<%iI9kvZUGj)z5xCg-aTi zskyd37^->S4oh&*#Q$@ii??}+5dBkirl<2wZMqS*GZb-_W4rji3r56o1bleykzv_V z>5Ka(tO?b0%j-F>GFvb;)lFN-#o%)Fo)3noVlDpP)Jx*;i>otyUU29GO=(==QSIia zcL5jl%Fty{^d2$8*K%FzrJyq{ny8vj(dHXW@1t%)AMl^qY@b@QuRjZY`@JeHKTg|+ zV0qp*>H>IQaB9!<6(LLU>N!TKHn20D&K^9s9F8w#hv#ilMy=T3#UYtf`gu4%6lm1# zFQ4tQZKxlvH%#x_k+)YFEEvuBoC5q$g(D^YLb*YfZ|Us~BA&q$#8}Woxwyv&W_Orq zm-v{y)uoZ8Co3m+crC13NzODlf9znx959(CZCoz@y@$P;NXwmH7gap#Laq3D{va-H z05!@snGLp}SzLVKX}#6m%g2{MTKEyWy0#>Ke95KRM_o4R+;r6pa^=nET4>F%aaHX& zzTzGaFQmS&1mmq7%vZ^F7CzA7{)N`Dgm!iLpln95-_5$w>Ft=Aq@lM9(c_c5O3dMK$5L zK8}GHE}+B-qWUPVM(P1o&di*g=!9-^bnR5Zg<$hBUc*YzLt>>gLK?u$jRWSeY}S{jF38x*d^lzao@!Yv(Kii2la3gKMvP=5b^BM-0mHrlgN0 z%jR*vXMC^c85&4Su&a;PHICno!!=FS^Wm^^|s#+|v;> zFsoJq-eAF-<*GOvBS_DlK}Lo5@>3o8{8EqTUoiQr94kp3g)~E#1(te0-l7{?+_`K; zDVWlveAulOM)}UnII2mxp2R`!*72qI>M{Rp8dpx?EFoHcb&e>5w;3U)weH&*98r{HBmM1r%4+P5G0_`t$C8Bo-%{rvcz9VxmftnzY9+} zxIQApj(h@e0bu^2lqJRoQ*n#@wb1(jv?r$y5o};*?krtbl(vA3H{aS%1F+XF#lz@AG8u+P^H1k-4XRNQvoP~<K9e?@?ZKA<{xhsQl-C3Z5MPK3GG}i*buCPdQVam=H;J6 zv~^?V;06mS$5N~NCJ|jH_o;a#Y~OEm*XL9`)Gpg^()N8nRo5}=O~8I){Xj%a-V=P8 zPRf;J0Ex$cdjn~~Xm0H58XUCg!YTCuaME;G_y&qVYh096x{OPpY}EHN#cmKg<8&;K z-sEhqKyvjT+Dqls=|8=%N3Utt*|1u=Bl5%-|1RFs)(}bt0FFHS0JpPLoS2M(4yMxy5W zC*{H2`RAzGh&%V-o0Ro-=SK@qLlP|^+erZSa?fLF@Vt@|N{maYgBP>{S-bZ9ADAth zq?f_IXG493Dfgxjw;}tL#jyJG zW@<7QI(BuETb9~8^u?QH6G}DsRvubYHze2LJ@c43J6_|@`)<}DSwE2YhvSbO%ToCM z5xV38sXJXD^-z%|vjt17L>*zb_!?7TC}FVJffc}A26%r4M>%)yaGIr#LHD_ZR^obO zF@0ahPkQ#tDf2=h<#jq~9^`h(^y~lw9cuE@=0AM$s=z*$GygY2r_9y3z=#9s`hg(q zh~z~0_=2u8Z0*b~g@ZH`O8G@R6^TzjFEQ3D7y~*23m!(rPUt!wrW_`yD*3qLsS{?R z^cAs(QW~61X}C|>k?3L0Y=05J4ebRl?_BxT_On2pAR20RsNU(hs5C_veDS#t=o(^C z^qT3u{{wm9atW9mD~X-|?^)0Xl=at~f8RaT`X^`?a1Ev!|8=tM9ztK;QTNx3)v}at z0pmAReH;npEf-|xCPlplMfsMjzrh^wvB3pO8M#2+&yy*3o987oI>H?T&;+rg>PynR zpl=8&DWiI?u<8$tj`;iSB3AqkzJm1imp|G-Smc!mPOia}93RKs^J@|&2}A*aXxnio z_e%n1RG2voDdu8;`d@=U*gX84LP>LtiIr?o!srQC1V724eXcoC%4mhlcS!%3qc9ox0gvXV3a_?g09 zE2oL=8p4CChYG?Qm4RC15X)^KG3{qz(Y!ENr=G!KM!MP!!I%wlxnH#MUDSn3%^yd= zd|JhUWK)O|jU$PJDZ@w)R^HT<^aP1zDin4nM0ow%d+{ZwY;SG1<&D8`wW{}-s10EeIuYfiuxuHgkVM6a^2xEEI*$&UzaCFx6 z>fo>Oe0dmHt;GA&YIPPLeqQG12s(v#A0IPI>t1Brr(v>mN{+XHIi6H_4ND={^%T6s zHbrjW-?$AO?C9_LhM@Enl^_}>vz(J=$!kr4UE~&^txGPXl_x#A_K=LR2C22n&n9vL zbNam-(_7duUG0;6W(A+mPSXC(_r9>tZ_Domk za?*qI6->exfE)V#L;M1Rg93vC&O*Z@Syb-knwu>Xad4NFuo;;fLhlW&7EP3D?fpP| zi{DL!PB$z=I!)KNzH;{|z@@4o$<3c%wTMfCR$8uUmN{tY368{$5wRPYo2oZ-_q8E^ zkInLJwBUK0V!ifXg$(=!oa)<+?pM(le}eyhT7Ue1?2bVHm-{LI8SlSsr$GPbEt~(- zA^x``{O$kz|JQ(l{@aE6-&*k|lwKj3hK}y+Y2~|LwIc2=>EFLIq|;zmO8T#&>`DFm z_wRvx&GDvmdpEaQDm*DEDGv{id`RPXeWVx`PFiBrWoAf%?ZiE|`P*P?wd0J-vzpZC zH@>}_u{_Tj(JoS<&4NmN5g~TuF_j3Ux!j;czBG#XX8R1GItk*#E;*O%C;=sUw z2gK;7%%ojom9Iuq{^N&$>u(Pqja(=!~S3Guu18tA4FGXPRf2Z;UAtJlcRYP z;^SR5C-~!JjdspWO-u|ROYD>*gD%3$(;lp`jDoI(mCpKdSVvE?cV~*Ibr;ZNLQ?GQ z>^fY+@k!WjlJow_G|VsJL$M`7_4~6;YXmkiH*eZ6=sKKDJT2E3R1t2(`J zZSK+S^D?Dcn`;W~4PtmL*Aj(Y7h?#kYijU0iHwbF9LVSr5k*5#d;9ui&4_HFM*ZgV z(}ScscR`asKOc*YZ;p#XjTutD!7O!)^~dV1zdBUA!N4%;F!U-ZpfWh~xEFW=2OaX7 zCcN#thK5E*G;5X3oQBqfs(HY*j_8mZ9?n^Yx$&<;w9F@~gJkIvxJ?^Y`ZIroZ~gjo z>gagT=)>|Fl8e&NOb~%=T6=p1`g7mw-+M$ZgFY|RM@`m@m%sy1m$`Wc4=J^dgpTB= z>JW951UGL^)H>VQ+Ww%zW7nKS}K5?h{ zaKYf&;c4(BUQ+_}ZYAD&@t2CqUO3K*Ct zhzrf~^$MG8W#EA$9jbilYQ$U|989W6=aH>$Q>9&!+oo#gA-hXG3Q3&VVl9%ZW*MUM zf&Tu|va+QmC8r)+b1fl5Lq>85&fY$fEU||@TVY8ukqm70<%?aCH^~KLWn`E)#zRA= z!{t|W!^6V~iHT$Z$);rPTw!JHG8<&# zGaGOk%;9;IhIO_1dqNj2_xl3uI<;E|2UZi6+dn^I>M2PAntXh&(I#1>E3Wj>3jTu< z#_+;^mDoq+Y`Pv;EstcM`OWdsDI}j@yhA8O3v>|Dn3J*|DDk-G+kIx$0-ds*H#Qy3 za%8u-_?Rave@#Q>6vtH**~(0KFQxtG*B_q$iJ5sK8F<1=^uTGjt&MIH_KbgYY%IRQ zd>Gl0Yu1CjRbiE2^zN%>o?6(^(dS!aLk_4>7S=q6glcvjaz-<1tMT$dc7!x`@po=3 zTpY>p?uL%G_512fkhR|8)Nz9F;DiL%x#l3SC%10hQo$gMyK>x{{Nr#%2{fzB0;%v` zy!h7pmNK3@pVwiB6m0Tk+}mWNq#h|ny7frrGm7-IG#-bYPM7^vcQQB}F6w&lQd-(S zK0clb54>}4k7YQ+QrOb6%bFuoL7Q>}3eJIY%oG)EoBWCREJo0lOpJ^x=;Pho;ahDc zk9o@%#e8m7IXNqpt!_?T6LmkCU$oM#F2z*bg~6g`o(K--VvIH9A?O_V#n`x@{l*w; z4f|tYp68>#2QKcbg@uK^3Zck;^Q(Vy5_7s8!>-G_TR`;iA^E*~_Xr6&P5U5&7k4N` zJ=WLPYi;JDg;pHt*WXjFF!aW z5pg>ziY!57WVlG;KN3k*>W4B0>rk?IUU$w8N~4FMa_f^F+HB33w#jM--74EA5a~=# zK(^GjI#^#>=ul=k=PVuebLMeOy9?CmCl#A2TsADP}8!oa45GJrUzs zOBLQ`&|ZK|!p}FEH3p6veIHyDG-cTNZt-^_<`_zTw+|DQQaok@cLJJvQbZy2kBfLtp?O+BmG8Jr}j!lFw|L2z%Mb-Dx zl9>E_ZOqBOYMz>i$)9&G?o>N&%uhC?IV8BebVPVy%0DA2LKJrABP)}jx{`V*i&{Xy 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 _Z&)NcJWKhJW_ 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