From bfaeb0b43d702bbe9f45e571c6fd093363efde77 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Sun, 18 Jul 2021 13:54:27 +0200 Subject: [PATCH 1/5] add base_url for raster images --- R/call_waterinfo.R | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/R/call_waterinfo.R b/R/call_waterinfo.R index c79f349..ec4d22d 100644 --- a/R/call_waterinfo.R +++ b/R/call_waterinfo.R @@ -9,6 +9,10 @@ waterinfo_pro_base <- function() { hic_base <- function() { "https://www.waterinfo.be/tsmhic/KiWIS/KiWIS" } +hydro_base <- function() { + "https://hydro.vmm.be/grid/kiwis/KiWIS" +} + #' http call to waterinfo.be #' @@ -26,20 +30,15 @@ hic_base <- function() { #' #' @importFrom httr GET http_type status_code http_error content add_headers #' @importFrom jsonlite fromJSON -call_waterinfo <- function(query, base_url = "vmm", token = NULL) { - - hic_base - +call_waterinfo <- function( + query, base_url = c("vmm", "hic", "pro", "hydro"), token = NULL +) { # check the base url, which depends of the query to execute - if (base_url == "vmm") { - base <- waterinfo_base() - } else if (base_url == "hic") { - base <- hic_base() - } else if (base_url == "pro") { - base <- waterinfo_pro_base() - } else { - stop("Base url should be vmm, hic or pro") - } + base_url <- match.arg(base_url) + base <- switch( + base_url, vmm = waterinfo_base(), hic = hic_base(), + pro = waterinfo_pro_base(), hydro = hydro_base() + ) if (is.null(token)) { res <- GET(base, query = query) From 1d963c7628f19a03c7a729e6c85a4ebdb4160224 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Sun, 18 Jul 2021 20:52:30 +0200 Subject: [PATCH 2/5] upgrade to Roxygen2 7.1.1 --- DESCRIPTION | 2 +- man/air_pressure.Rd | 6 ++++-- man/call_waterinfo.Rd | 2 +- man/get_stations.Rd | 6 ++++-- man/get_timeseries_tsid.Rd | 16 ++++++++++++---- man/get_token.Rd | 14 +++++++++++--- man/get_variables.Rd | 6 ++++-- man/liedekerke.Rd | 6 ++++-- man/wateRinfo-package.Rd | 6 +++--- wateRinfo.Rproj | 1 + 10 files changed, 45 insertions(+), 20 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 847f377..071c71d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -36,4 +36,4 @@ Suggests: LazyData: true Encoding: UTF-8 VignetteBuilder: knitr -RoxygenNote: 6.1.1 +RoxygenNote: 7.1.1 diff --git a/man/air_pressure.Rd b/man/air_pressure.Rd index d1c6c25..7d9b05d 100644 --- a/man/air_pressure.Rd +++ b/man/air_pressure.Rd @@ -4,7 +4,8 @@ \name{air_pressure} \alias{air_pressure} \title{Air pressure data of January 1st, 2017} -\format{A data frame with 710 rows and 13 variables: +\format{ +A data frame with 710 rows and 13 variables: \describe{ \item{ts_id}{identifier of the downloaded time serie} \item{Timestamp}{datetime} @@ -19,7 +20,8 @@ \item{parametertype_name}{parameter type name} \item{ts_unitsymbol}{unit of the variable} \item{dataprovider}{provider of the time series value} -}} +} +} \source{ \url{https://www.waterinfo.be/} } diff --git a/man/call_waterinfo.Rd b/man/call_waterinfo.Rd index 7d2da3f..5a2ff60 100644 --- a/man/call_waterinfo.Rd +++ b/man/call_waterinfo.Rd @@ -4,7 +4,7 @@ \alias{call_waterinfo} \title{http call to waterinfo.be} \usage{ -call_waterinfo(query, base_url = "vmm", token = NULL) +call_waterinfo(query, base_url = c("vmm", "hic", "pro", "hydro"), token = NULL) } \arguments{ \item{query}{list of query options to be used together with the base string} diff --git a/man/get_stations.Rd b/man/get_stations.Rd index 305313d..5fe7220 100644 --- a/man/get_stations.Rd +++ b/man/get_stations.Rd @@ -3,7 +3,8 @@ \name{get_stations} \alias{get_stations} \title{Get list of stations for a variable} -\format{A data.frame with 10 variables: +\format{ +A data.frame with 10 variables: \describe{ \item{ts_id}{Unique timeseries identifier to access time series data corresponding to a combination of the station, measured variable and @@ -20,7 +21,8 @@ \item{dataprovider}{Data provider of the time series data.} } The URL of the specific request is provided as a comment attribute to the -returned data.frame. Use \code{comment(df)} to get the request URL.} +returned data.frame. Use \code{comment(df)} to get the request URL. +} \usage{ get_stations(variable_name = NULL, frequency = "15min", token = NULL) } diff --git a/man/get_timeseries_tsid.Rd b/man/get_timeseries_tsid.Rd index 631599c..503e7a3 100644 --- a/man/get_timeseries_tsid.Rd +++ b/man/get_timeseries_tsid.Rd @@ -3,7 +3,8 @@ \name{get_timeseries_tsid} \alias{get_timeseries_tsid} \title{Download timeseries data from waterinfo.be} -\format{A data.frame with 3 variables: +\format{ +A data.frame with 3 variables: \describe{ \item{Timestamp}{Datetime of the measurement.} \item{Value}{Measured value.} @@ -46,10 +47,17 @@ } } The URL of the specific request is provided as a comment attribute to the -returned data.frame. Use \code{comment(df)} to get the request URL.} +returned data.frame. Use \code{comment(df)} to get the request URL. +} \usage{ -get_timeseries_tsid(ts_id, period = NULL, from = NULL, to = NULL, - datasource = 1, token = NULL) +get_timeseries_tsid( + ts_id, + period = NULL, + from = NULL, + to = NULL, + datasource = 1, + token = NULL +) } \arguments{ \item{ts_id}{waterinfo.be database ts_id, defining a timeserie variable and diff --git a/man/get_token.Rd b/man/get_token.Rd index b13bbb3..67e442e 100644 --- a/man/get_token.Rd +++ b/man/get_token.Rd @@ -11,8 +11,12 @@ \alias{is.expired.token} \title{Get waterinfo Token} \usage{ -get_token(client = NULL, client_id = NULL, client_secret = NULL, - token_url = "http://download.waterinfo.be/kiwis-auth/token") +get_token( + client = NULL, + client_id = NULL, + client_secret = NULL, + token_url = "http://download.waterinfo.be/kiwis-auth/token" +) is.expired(token) @@ -59,12 +63,16 @@ client_id <- '32dceece-826c-4b98-9c2d-b16978f0ca6a' client_secret <- '4ada871a-9528-4b4d-bfd5-b570ce8f4d2d' my_token <- get_token(client_id = client_id,client_secret = client_secret) print(my_token) + # get token via client client <- paste0('MzJkY2VlY2UtODI2Yy00Yjk4LTljMmQtYjE2OTc4ZjBjYTZhOjRhZGE4', 'NzFhLTk1MjgtNGI0ZC1iZmQ1LWI1NzBjZThmNGQyZA==') my_token <- get_token(client = client) print(my_token) is.expired(my_token) -expires.in(my_token) +expires.in + +# Use the token when requesting for data (i.e. get_* functions), e.g. +get_stations(variable_name = "verdamping_monteith", token = my_token) } diff --git a/man/get_variables.Rd b/man/get_variables.Rd index aa34602..85bf13c 100644 --- a/man/get_variables.Rd +++ b/man/get_variables.Rd @@ -3,7 +3,8 @@ \name{get_variables} \alias{get_variables} \title{Get list of variables for a given station} -\format{A data.frame with 6 variables: +\format{ +A data.frame with 6 variables: \describe{ \item{station_name}{Official name of the measurement station.} \item{station_no}{Station ID as provided on the waterinfo.be website.} @@ -16,7 +17,8 @@ \item{stationparameter_name}{Station specific variable description.} } The URL of the specific request is provided as a comment attribute to the -returned data.frame. Use \code{comment(df)} to get the request URL.} +returned data.frame. Use \code{comment(df)} to get the request URL. +} \usage{ get_variables(station_no, token = NULL) } diff --git a/man/liedekerke.Rd b/man/liedekerke.Rd index 3abc2c2..63be85c 100644 --- a/man/liedekerke.Rd +++ b/man/liedekerke.Rd @@ -4,7 +4,8 @@ \name{liedekerke} \alias{liedekerke} \title{Soil moisture data of Liedekerke, January 2017} -\format{A data frame with 23,816 rows and 9 variables: +\format{ +A data frame with 23,816 rows and 9 variables: \describe{ \item{ts_id}{identifier of the downloaded time serie} \item{Timestamp}{datetime} @@ -15,7 +16,8 @@ \item{ts_name}{type/frequency of the time serie} \item{parametertype_name}{parameter type name} \item{stationparameter_name}{parameter name on station level} -}} +} +} \source{ \url{https://www.waterinfo.be/} } diff --git a/man/wateRinfo-package.Rd b/man/wateRinfo-package.Rd index 2444085..1767e45 100644 --- a/man/wateRinfo-package.Rd +++ b/man/wateRinfo-package.Rd @@ -6,7 +6,7 @@ \alias{wateRinfo-package} \title{wateRinfo: Download Time Series Data from Waterinfo.be} \description{ -\if{html}{\figure{logo.png}{options: align='right'}} +\if{html}{\figure{logo.png}{options: align='right' alt='logo' width='120'}} wateRinfo facilitates access to waterinfo.be (), a website managed by the Flanders Environment @@ -26,12 +26,12 @@ Useful links: } \author{ -\strong{Maintainer}: Stijn Van Hoey \email{stijnvanhoey@gmail.com} (0000-0001-6413-3185) +\strong{Maintainer}: Stijn Van Hoey \email{stijnvanhoey@gmail.com} (\href{https://orcid.org/0000-0001-6413-3185}{ORCID}) Other contributors: \itemize{ \item Willem Maetens \email{w.maetens@vmm.be} [contributor] - \item Peter Desmet \email{peter.desmet@inbo.be} (0000-0002-8442-8025) [contributor] + \item Peter Desmet \email{peter.desmet@inbo.be} (\href{https://orcid.org/0000-0002-8442-8025}{ORCID}) [contributor] \item Research Institute for Nature and Forest (INBO) \email{info@inbo.be} [copyright holder] } diff --git a/wateRinfo.Rproj b/wateRinfo.Rproj index f50e39c..e4a061f 100644 --- a/wateRinfo.Rproj +++ b/wateRinfo.Rproj @@ -19,3 +19,4 @@ BuildType: Package PackageUseDevtools: Yes PackageInstallArgs: --no-multiarch --with-keep.source PackageCheckArgs: --as-cran +PackageRoxygenize: rd,collate,namespace From b3e48b1421ef9d5473cea70d5e7ce6716ddf1aae Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 19 Jul 2021 15:57:58 +0200 Subject: [PATCH 3/5] add get_raster_points() --- DESCRIPTION | 2 ++ NAMESPACE | 8 +++++++ R/get_raster_points.R | 47 ++++++++++++++++++++++++++++++++++++ man/get_raster_points.Rd | 51 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 R/get_raster_points.R create mode 100644 man/get_raster_points.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 071c71d..96f41ee 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -20,10 +20,12 @@ BugReports: https://github.com/ropensci/wateRinfo/issues Depends: R (>= 2.10) Imports: + assertthat, dplyr, httr, jsonlite, openssl, + purrr, lubridate (>= 1.6.0), rlang, utils diff --git a/NAMESPACE b/NAMESPACE index 51a45e6..bc0b86e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,6 +6,7 @@ S3method(print,token) S3method(print,waterinfo_api) export(check_period_format) export(expires.in) +export(get_raster_points) export(get_stations) export(get_timeseries_tsid) export(get_token) @@ -17,9 +18,14 @@ export(resolve_timeseriesgroupid) export(show.token) export(supported_frequencies) export(supported_variables) +importFrom(assertthat,assert_that) +importFrom(assertthat,has_name) importFrom(dplyr,"%>%") +importFrom(dplyr,bind_cols) +importFrom(dplyr,bind_rows) importFrom(dplyr,filter) importFrom(dplyr,filter_) +importFrom(dplyr,mutate) importFrom(dplyr,select) importFrom(httr,GET) importFrom(httr,POST) @@ -32,6 +38,8 @@ importFrom(jsonlite,fromJSON) importFrom(lubridate,parse_date_time) importFrom(lubridate,ymd_hms) importFrom(openssl,base64_encode) +importFrom(purrr,map) +importFrom(purrr,map2) importFrom(rlang,.data) importFrom(rlang,quo) importFrom(utils,read.csv) diff --git a/R/get_raster_points.R b/R/get_raster_points.R new file mode 100644 index 0000000..6a31ad6 --- /dev/null +++ b/R/get_raster_points.R @@ -0,0 +1,47 @@ +#' Get timeseries data for specific points on a raster +#' @inheritParams get_timeseries_tsid +#' @param points a matrix or data.frame with coordinates in decimal degrees +#' using the EPSG 4326 coordinate system. +#' It must have the colnames `lat` and `long`. +#' @export +#' @importFrom assertthat assert_that has_name +#' @importFrom dplyr bind_cols bind_rows mutate %>% +#' @importFrom lubridate ymd_hms +#' @importFrom purrr map map2 +get_raster_points <- function( + ts_id = 911010, period = NULL, from = NULL, to = NULL, points, + datasource = 10, token = NULL +) { + # check and handle the date/period information + period_info <- parse_period(from, to, period) + assert_that( + inherits(points, "data.frame"), has_name(points, c("long", "lat")) + ) + + query_list <- list( + type = "queryServices", service = "kisters", + request = "getRasterToPointValues", ts_id = ts_id, format = "json", + datasource = datasource, raster_epsg = 4326, metadata = "True", + raster_x = paste(points$long, collapse = ","), + raster_y = paste(points$lat, collapse = ",") + ) + time_series <- call_waterinfo( + query = c(query_list, period_info), base_url = "hydro", token = token + ) + map( + seq_along(points$long), + function(i) { + cbind(points[i, c("long", "lat")], ts_id = ts_id) + } + ) %>% + map(`rownames<-`, NULL) -> points_list + + map(time_series$content$data, `colnames<-`, c("timestamp", "value")) %>% + map(data.frame) %>% + map2(points_list, bind_cols) %>% + bind_rows() %>% + mutate( + timestamp = ymd_hms(timestamp), + value = as.numeric(value) + ) +} diff --git a/man/get_raster_points.Rd b/man/get_raster_points.Rd new file mode 100644 index 0000000..ef1571c --- /dev/null +++ b/man/get_raster_points.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_raster_points.R +\name{get_raster_points} +\alias{get_raster_points} +\title{Get timeseries data for specific points on a raster} +\usage{ +get_raster_points( + ts_id = 911010, + period = NULL, + from = NULL, + to = NULL, + points, + datasource = 10, + token = NULL +) +} +\arguments{ +\item{ts_id}{waterinfo.be database ts_id, defining a timeserie variable and +frequency it is defined.} + +\item{period}{input string according to format required by waterinfo: +De period string is provided as P#Y#M#DT#H#M#S, with P defines `Period`, +each # is an integer value and the codes define the number of... +Y - years +M - months +D - days +T required if information about sub-day resolution is present +H - hours +D - days +M - minutes +S - seconds +Instead of D (days), the usage of W - weeks is possible as well +Examples of valid period strings: P3D, P1Y, P1DT12H, PT6H, P1Y6M3DT4H20M30S.} + +\item{from}{date of datestring as start of the time series} + +\item{to}{date of datestring as end of the time series} + +\item{points}{a matrix or data.frame with coordinates in decimal degrees +using the EPSG 4326 coordinate system. +It must have the colnames `lat` and `long`.} + +\item{datasource}{int [0-4] defines the `meetnet` of which the measurement +station is part of. VMM based stations are net '1', MOW-HIC is net '2'} + +\item{token}{token to use with the call (optional, can be retrieved via +\code{\link{get_token}})} +} +\description{ +Get timeseries data for specific points on a raster +} From 78315bc752fc6e6dbfac8c27e6bce87e6b140162 Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 19 Jul 2021 15:58:36 +0200 Subject: [PATCH 4/5] add contributor --- DESCRIPTION | 1 + 1 file changed, 1 insertion(+) diff --git a/DESCRIPTION b/DESCRIPTION index 96f41ee..3e85822 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -12,6 +12,7 @@ Authors@R: c( person("Stijn", "Van Hoey", role = c("aut", "cre"), email = "stijnvanhoey@gmail.com", comment = c(ORCID = "0000-0001-6413-3185")), person("Willem", "Maetens", role = "ctb", email = "w.maetens@vmm.be"), person("Peter", "Desmet", role = "ctb", email = "peter.desmet@inbo.be", comment = c(ORCID = "0000-0002-8442-8025")), + person(given = "Thierry", family = "Onkelinx", role = "ctb", email = "thierry.onkelinx@inbo.be", comment = c(ORCID = "0000-0001-8804-4216")), person("Research Institute for Nature and Forest (INBO)", role = "cph", email = "info@inbo.be") ) License: MIT + file LICENSE From 724ab2105b9392a542358fb8fdd7d33195abda3f Mon Sep 17 00:00:00 2001 From: Thierry Onkelinx Date: Mon, 19 Jul 2021 16:10:31 +0200 Subject: [PATCH 5/5] update failing unit test --- man/wateRinfo-package.Rd | 1 + tests/testthat/test-waterinfo_call.R | 106 ++++++++++++++------------- 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/man/wateRinfo-package.Rd b/man/wateRinfo-package.Rd index 1767e45..0ceef2a 100644 --- a/man/wateRinfo-package.Rd +++ b/man/wateRinfo-package.Rd @@ -32,6 +32,7 @@ Other contributors: \itemize{ \item Willem Maetens \email{w.maetens@vmm.be} [contributor] \item Peter Desmet \email{peter.desmet@inbo.be} (\href{https://orcid.org/0000-0002-8442-8025}{ORCID}) [contributor] + \item Thierry Onkelinx \email{thierry.onkelinx@inbo.be} (\href{https://orcid.org/0000-0001-8804-4216}{ORCID}) [contributor] \item Research Institute for Nature and Forest (INBO) \email{info@inbo.be} [copyright holder] } diff --git a/tests/testthat/test-waterinfo_call.R b/tests/testthat/test-waterinfo_call.R index 5c545f7..5d66803 100644 --- a/tests/testthat/test-waterinfo_call.R +++ b/tests/testthat/test-waterinfo_call.R @@ -1,52 +1,54 @@ -context("waterinfo_call") - -test_that("base url is valid", { - query <- list() - expect_error(call_waterinfo(query, base_url = "www"), - regexp = "Base url should be vmm, hic or pro" - ) -}) - -test_that("wrong token object", { - query <- list() - expect_error(call_waterinfo(query, token = "3AGZ")) -}) - -test_that("non existing tsid to API", { - query <- list( - type = "queryServices", service = "kisters", - request = "getTimeseriesvalues", - ts_id = "notsid", format = "json", - datasource = 1 - ) - expect_error(call_waterinfo(query), - regexp = "Waterinfo API request failed.*InvalidParameterValue" - ) -}) - -# tackle specific case when error is thrown by the server on missing datasource -test_that("datasource not included in the API call", { - query <- list( - type = "queryServices", service = "kisters", - request = "getTimeseriesvalues", - ts_id = "5156042", format = "json" - ) - expect_error(call_waterinfo(query), - regexp = "Waterinfo API request failed.*InvalidParameterValue.*Could not find a datasource" - ) -}) - -test_that("add call to waterinfo explicitly to the print output", { - skip_on_cran() - - query <- list( - type = "queryServices", service = "kisters", - request = "getTimeseriesvalues", - ts_id = "5156042", format = "json", datasource = 1 - ) - response <- call_waterinfo(query) - raw_call_info <- paste0("Waterinfo API query applied: type=queryServices&", - "service=kisters&request=getTimeseriesvalues&", - "ts_id=5156042&format=json&datasource=1") - expect_equal(capture.output(print(response))[1], raw_call_info) -}) +context("waterinfo_call") + +options(useFancyQuotes = FALSE) + +test_that("base url is valid", { + query <- list() + expect_error(call_waterinfo(query, base_url = "www"), + regexp = "'arg' should be one of \"vmm\", \"hic\", \"pro\", \"hydro\"" + ) +}) + +test_that("wrong token object", { + query <- list() + expect_error(call_waterinfo(query, token = "3AGZ")) +}) + +test_that("non existing tsid to API", { + query <- list( + type = "queryServices", service = "kisters", + request = "getTimeseriesvalues", + ts_id = "notsid", format = "json", + datasource = 1 + ) + expect_error(call_waterinfo(query), + regexp = "Waterinfo API request failed.*InvalidParameterValue" + ) +}) + +# tackle specific case when error is thrown by the server on missing datasource +test_that("datasource not included in the API call", { + query <- list( + type = "queryServices", service = "kisters", + request = "getTimeseriesvalues", + ts_id = "5156042", format = "json" + ) + expect_error(call_waterinfo(query), + regexp = "Waterinfo API request failed.*InvalidParameterValue.*Could not find a datasource" + ) +}) + +test_that("add call to waterinfo explicitly to the print output", { + skip_on_cran() + + query <- list( + type = "queryServices", service = "kisters", + request = "getTimeseriesvalues", + ts_id = "5156042", format = "json", datasource = 1 + ) + response <- call_waterinfo(query) + raw_call_info <- paste0("Waterinfo API query applied: type=queryServices&", + "service=kisters&request=getTimeseriesvalues&", + "ts_id=5156042&format=json&datasource=1") + expect_equal(capture.output(print(response))[1], raw_call_info) +})