Skip to content

Commit 77fcc63

Browse files
authored
Merge pull request #17 from bcgov/devel
v0.2.4
2 parents e738afe + 97f4187 commit 77fcc63

23 files changed

+454
-132
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: tidyhydat
22
Title: Extract tidy hydrometric data
3-
Version: 0.2.3
3+
Version: 0.2.4
44
Authors@R: c(person("Sam", "Albers", email = "sam.albers@gov.bc.ca", role = c("aut", "cre"),
55
), person("Dave", "Hutchinson", email = "david.hutchinson@canada.ca", role = "ctb"))
66
Description: tidyhydat provides functions to extract river data from Water Survey of Canada sources and make it tidy.

NAMESPACE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export(STN_OPERATION_SCHEDULE)
1818
export(STN_REGULATION)
1919
export(STN_REMARKS)
2020
export(VERSION)
21+
export(download_hydat)
2122
export(download_realtime_dd)
2223
export(download_realtime_ws)
2324
export(get_ws_token)
@@ -35,3 +36,5 @@ importFrom(lubridate,year)
3536
importFrom(lubridate,ymd)
3637
importFrom(tibble,tibble)
3738
importFrom(tidyr,gather)
39+
importFrom(utils,download.file)
40+
importFrom(utils,unzip)

NEWS.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1+
#tidyhydat 0.2.4
2+
* download_realtime_dd can now accept stations from multiple provinces or simply select multiple provinces
3+
* better error messages for get_ws_token and download_realtime_ws
4+
* All functions that previously accepted STATION_NUMBER == "ALL" now throw an error.
5+
* Added function to download hydat
6+
17
#tidyhydat 0.2.3
28
* Remove significant redundancy in station selecting mechanism
39
* Added package startup message when HYDAT is out of date
410
* Add internal allstations data
511
* Added all the tables as functions or data from HYDAT
6-
* Made missing station ouput truncated at 10 missign stations
12+
* Made missing station ouput truncated at 10 missing stations
713

814
# tidyhdyat 0.2.2
915
* Adding several new tables

R/ANNUAL_STATISTICS.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
ANNUAL_STATISTICS <- function(hydat_path=NULL, STATION_NUMBER =NULL, PROV_TERR_STATE_LOC=NULL,
3838
start_year = "ALL", end_year = "ALL") {
3939

40+
if(!is.null(STATION_NUMBER) && STATION_NUMBER == "ALL"){
41+
stop("Deprecated behaviour.Omit the STATION_NUMBER = \"ALL\" argument. See ?ANNUAL_STATISTICS for examples.")
42+
}
43+
4044
if(is.null(hydat_path)){
4145
hydat_path = Sys.getenv("hydat")
4246
if(is.na(hydat_path)){

R/DLY_FLOWS.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737

3838
DLY_FLOWS <- function(hydat_path=NULL, STATION_NUMBER = NULL, PROV_TERR_STATE_LOC = NULL, start_date ="ALL", end_date = "ALL") {
3939

40+
if(!is.null(STATION_NUMBER) && STATION_NUMBER == "ALL"){
41+
stop("Deprecated behaviour.Omit the STATION_NUMBER = \"ALL\" argument. See ?DLY_FLOWS for examples.")
42+
}
43+
4044
if(start_date == "ALL" & end_date == "ALL"){
4145
message("No start and end dates specified. All dates available will be returned.")
4246
} else {

R/DLY_LEVELS.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636
DLY_LEVELS <- function(hydat_path=NULL, STATION_NUMBER = NULL, PROV_TERR_STATE_LOC = NULL, start_date ="ALL", end_date = "ALL") {
3737

38+
if(!is.null(STATION_NUMBER) && STATION_NUMBER == "ALL"){
39+
stop("Deprecated behaviour.Omit the STATION_NUMBER = \"ALL\" argument. See ?DLY_LEVELS for examples.")
40+
}
41+
3842
if(start_date == "ALL" & end_date == "ALL"){
3943
message("No start and end dates specified. All dates available will be returned.")
4044
} else {

R/STATIONS.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@
4141

4242
STATIONS <- function(hydat_path=NULL, STATION_NUMBER = NULL, PROV_TERR_STATE_LOC = NULL) {
4343

44-
#if(STATION_NUMBER == "ALL" | PROV_TERR_STATE_LOC == "ALL"){
45-
# stop("Specifying ALL for STATION_NUMBER OR PROV_TERR_STATE_LOC is deprecrated. See examples for usage.")
46-
#}
44+
if(!is.null(STATION_NUMBER) && STATION_NUMBER == "ALL"){
45+
stop("Deprecated behaviour.Omit the STATION_NUMBER = \"ALL\" argument. See ?download_realtime_dd for examples.")
46+
}
4747

4848
if(is.null(hydat_path)){
4949
hydat_path = Sys.getenv("hydat")

R/download.R

Lines changed: 156 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
#'
1616
#' @description Download realtime discharge data from the Meteorological Service of Canada (MSC) datamart. The function will prioritize
1717
#' downloading data collected at the highest resolution. In instances where data is not available at high (hourly or higher) resolution
18-
#' daily averages are used. Currently, if a station does not exist or is not found, no data is returned. Both the province and the station number
19-
#' should be specified.
18+
#' daily averages are used. Currently, if a station does not exist or is not found, no data is returned.
2019
#'
21-
#' @param STATION_NUMBER Water Survey of Canada station number. No default. Can also take the "ALL" argument.
22-
#' @param PROV_TERR_STATE_LOC Province, state or territory. See also for argument options.
20+
#' @param STATION_NUMBER Water Survey of Canada station number. If this argument is omitted from the function call, the value of \code{PROV_TERR_STATE_LOC}
21+
#' is returned.
22+
#' @param PROV_TERR_STATE_LOC Province, state or territory. If this argument is omitted from the function call, the value of \code{STATION_NUMBER}
23+
#' is returned. See \code{unique(realtime_network_meta()$PROV_TERR_STATE_LOC)}
2324
#'
2425
#' @return A tibble of water flow and level values
2526
#'
@@ -28,39 +29,67 @@
2829
#'
2930
#'
3031
#' @examples
31-
#' download_realtime_dd(STATION_NUMBER="08MF005", PROV_TERR_STATE_LOC="BC")
32+
#' ## Download from multiple provinces
33+
#' download_realtime_dd(STATION_NUMBER=c("01CD005","08MF005"))
3234
#'
3335
#' # To download all stations in Prince Edward Island:
34-
#' download_realtime_dd(STATION_NUMBER = "ALL", PROV_TERR_STATE_LOC = "PE")
36+
#' download_realtime_dd(PROV_TERR_STATE_LOC = "PE")
3537
#'
3638
#' @export
37-
download_realtime_dd <- function(STATION_NUMBER, PROV_TERR_STATE_LOC) {
38-
39-
if(missing(STATION_NUMBER) | missing(PROV_TERR_STATE_LOC))
40-
stop("STATION_NUMBER or PROV_TERR_STATE_LOC argument is missing. These arguments must match jurisdictions.")
39+
download_realtime_dd <- function(STATION_NUMBER = NULL, PROV_TERR_STATE_LOC) {
4140

4241
## TODO: HAve a warning message if not internet connection exists
43-
44-
prov = PROV_TERR_STATE_LOC
45-
46-
if(STATION_NUMBER[1] == "ALL"){
47-
STATION_NUMBER = realtime_network_meta(PROV_TERR_STATE_LOC = prov)$STATION_NUMBER
42+
if(!is.null(STATION_NUMBER) && STATION_NUMBER == "ALL"){
43+
stop("Deprecated behaviour.Omit the STATION_NUMBER = \"ALL\" argument. See ?download_realtime_dd for examples.")
4844
}
4945

50-
output_c <- c()
51-
for (i in 1:length(STATION_NUMBER) ){
52-
STATION_NUMBER_SEL = STATION_NUMBER[i]
5346

54-
base_url = "http://dd.weather.gc.ca/hydrometric"
47+
if(!is.null(STATION_NUMBER)){
48+
stns = STATION_NUMBER
49+
choose_df = realtime_network_meta()
50+
choose_df = filter(choose_df, STATION_NUMBER %in% stns)
51+
choose_df = select(choose_df, STATION_NUMBER, PROV_TERR_STATE_LOC)
52+
}
5553

56-
# build URL
57-
type <- c("hourly", "daily")
58-
url <- sprintf("%s/csv/%s/%s", base_url, PROV_TERR_STATE_LOC, type)
59-
infile <- sprintf("%s/%s_%s_%s_hydrometric.csv", url, PROV_TERR_STATE_LOC, STATION_NUMBER_SEL, type)
54+
if(is.null(STATION_NUMBER) ){
55+
choose_df = realtime_network_meta(PROV_TERR_STATE_LOC = PROV_TERR_STATE_LOC)
56+
choose_df = select(choose_df, STATION_NUMBER, PROV_TERR_STATE_LOC)
57+
}
6058

61-
# Define column names as the same as HYDAT
62-
colHeaders <- c("STATION_NUMBER", "Date", "LEVEL", "LEVEL_GRADE", "LEVEL_SYMBOL", "LEVEL_CODE",
63-
"FLOW", "FLOW_GRADE", "FLOW_SYMBOL", "FLOW_CODE")
59+
output_c <- c()
60+
for (i in 1:nrow(choose_df) ){
61+
## Specify from choose_df
62+
STATION_NUMBER_SEL = choose_df$STATION_NUMBER[i]
63+
PROV_SEL = choose_df$PROV_TERR_STATE_LOC[i]
64+
65+
66+
base_url = "http://dd.weather.gc.ca/hydrometric"
67+
68+
# build URL
69+
type <- c("hourly", "daily")
70+
url <-
71+
sprintf("%s/csv/%s/%s", base_url, PROV_SEL, type)
72+
infile <-
73+
sprintf("%s/%s_%s_%s_hydrometric.csv",
74+
url,
75+
PROV_SEL,
76+
STATION_NUMBER_SEL,
77+
type)
78+
79+
# Define column names as the same as HYDAT
80+
colHeaders <-
81+
c(
82+
"STATION_NUMBER",
83+
"Date",
84+
"LEVEL",
85+
"LEVEL_GRADE",
86+
"LEVEL_SYMBOL",
87+
"LEVEL_CODE",
88+
"FLOW",
89+
"FLOW_GRADE",
90+
"FLOW_SYMBOL",
91+
"FLOW_CODE"
92+
)
6493

6594

6695
h <- tryCatch(
@@ -126,7 +155,8 @@ download_realtime_dd <- function(STATION_NUMBER, PROV_TERR_STATE_LOC) {
126155
output = dplyr::mutate(output, key = ifelse(key=="","Value", key))
127156
output = tidyr::spread(output,key, val)
128157
output = dplyr::rename(output,Code = CODE, Grade = GRADE, Symbol = SYMBOL)
129-
output = dplyr::select(output, STATION_NUMBER, Date, Parameter, Value, Grade, Symbol, Code)
158+
output = dplyr::mutate(output, PROV_TERR_STATE_LOC = PROV_SEL)
159+
output = dplyr::select(output, STATION_NUMBER, PROV_TERR_STATE_LOC, Date, Parameter, Value, Grade, Symbol, Code)
130160
output = dplyr::arrange(output, Parameter, STATION_NUMBER, Date)
131161
output$Value = as.numeric(output$Value)
132162

@@ -157,18 +187,19 @@ download_realtime_dd <- function(STATION_NUMBER, PROV_TERR_STATE_LOC) {
157187
#'
158188
#' @description Returns all stations in the Realtime Water Survey of Canada hydrometric network operated by Environment and Cliamte Change Canada
159189
#'
160-
#' @param PROV_TERR_STATE_LOC Province/State/Territory or Location. See examples for list of available options. Use "ALL" for all stations.
190+
#' @param PROV_TERR_STATE_LOC Province/State/Territory or Location. See examples for list of available options. realtime_network_meta() for all stations.
161191
#'
162192
#' @export
163193
#'
164194
#' @examples
165195
#' ## Available inputs for PROV_TERR_STATE_LOC argument:
166-
#' unique(realtime_network_meta(PROV_TERR_STATE_LOC = "ALL")$PROV_TERR_STATE_LOC)
196+
#' unique(realtime_network_meta()$PROV_TERR_STATE_LOC)
167197
#'
168198
#' realtime_network_meta(PROV_TERR_STATE_LOC = "BC")
199+
#' realtime_network_meta(PROV_TERR_STATE_LOC = c("QC","PE"))
169200

170201

171-
realtime_network_meta <- function(PROV_TERR_STATE_LOC){
202+
realtime_network_meta <- function(PROV_TERR_STATE_LOC = NULL){
172203
prov = PROV_TERR_STATE_LOC
173204
## Need to implement a search by station
174205
#try((if(hasArg(PROV_TERR_STATE_LOC_SEL) == FALSE) stop("Stopppppte")))
@@ -187,7 +218,7 @@ realtime_network_meta <- function(PROV_TERR_STATE_LOC){
187218
col_types = readr::cols()
188219
)
189220

190-
if((prov == "ALL")[1]){
221+
if(is.null(prov) ){
191222
return(net_tibble)
192223
}
193224

@@ -221,6 +252,16 @@ get_ws_token <- function(username, password){
221252

222253
## If the POST request was not a successful, print out why.
223254
## Possibly could provide errors as per Webservice guidelines
255+
if(httr::status_code(r)==422){
256+
stop("422 Unprocessable Entity: Username and/or password are missing or are formatted incorrectly.")
257+
}
258+
259+
if(httr::status_code(r)==403){
260+
stop("403 Forbidden: the webservice is denying your request. Try any of the following options: ensure you are not currently using all 5 tokens,
261+
wait a few minutes and try again or copy the get_ws_token code and paste it directly into the console.")
262+
}
263+
264+
## Catch all error for anything not covered above.
224265
httr::stop_for_status(r)
225266

226267
message(paste0("This token will expire at ",format(Sys.time() + 10*60, "%H:%M:%S")))
@@ -300,6 +341,11 @@ download_realtime_ws <- function(STATION_NUMBER, parameters = c(46,16,52,47,8,5,
300341
## Get data
301342
get_ws = httr::GET(url_for_GET)
302343

344+
if(httr::status_code(get_ws)==403){
345+
stop("403 Forbidden: the webservice is denying your request. Try any of the following options: wait a few minutes and try
346+
again or copy the get_ws_token code and paste it directly into the console.")
347+
}
348+
303349
## Check the GET status
304350
httr::stop_for_status(get_ws)
305351

@@ -318,10 +364,14 @@ download_realtime_ws <- function(STATION_NUMBER, parameters = c(46,16,52,47,8,5,
318364
csv_df = dplyr::select(csv_df, STATION_NUMBER, Date, Name_En, Value, Unit, Grade, Symbol, Approval, Parameter, Code)
319365

320366
## What stations were missed?
321-
differ = setdiff(unique(STATION_NUMBER), unique(csv_df$STATION_NUMBER))
367+
differ = setdiff(unique(stns), unique(csv_df$STATION_NUMBER))
322368
if( length(differ) !=0 ){
323-
message("The following station(s) were not retrieved: ", paste0(differ, sep = " "))
324-
message("See ?download_realtime_ws for possible reasons why.")
369+
if( length(differ) <= 10) {
370+
message("The following station(s) were not retrieved: ", paste0(differ, sep = " "))
371+
message("Check station number typos or if it is a valid station in the network") }
372+
else {
373+
message("More than 10 stations from the initial query were not returned. Ensure realtime and active status are correctly specified.")
374+
}
325375
} else{
326376
message("All station successfully retrieved")
327377
}
@@ -332,18 +382,77 @@ download_realtime_ws <- function(STATION_NUMBER, parameters = c(46,16,52,47,8,5,
332382
## Need to output a warning to see if any stations weren't retrieved
333383
}
334384

385+
#' @title A function to download hydat
386+
#'
387+
#' @description Download the hydat sqlite database. The function will check for a existing sqlite file and stop if the same version
388+
#' is already present. \code{download_hydat} also looks to see if you have the hydat environmental variable set.
389+
#'
390+
#' @param dl_hydat_here Directory to the hydat database. The hydat path can also be set in the \code{.Renviron} file so that it doesn't have to specified every function call. The path should
391+
#' set as the variable \code{hydat}. Open the \code{.Renviron} file using this command: \code{file.edit("~/.Renviron")}.
392+
#'
393+
#' @export
394+
#'
395+
#' @examples \donttest{
396+
#' download_hydat()
397+
#' }
398+
#'
399+
400+
download_hydat <- function(dl_hydat_here = NULL) {
401+
402+
response <- readline(prompt="Downloading HYDAT will take approximately 10 minutes. Are you sure you want to continue? (Y/N) ")
403+
404+
if(!response %in% c("Y","Yes","yes","y")){
405+
stop("Maybe another day...")
406+
}
407+
408+
if(is.null(dl_hydat_here)){
409+
hydat_path = Sys.getenv("hydat")
410+
if(is.na(hydat_path)){
411+
stop("No Hydat.sqlite3 path set either in this function or in your .Renviron file. See tidyhydat for more documentation.")
412+
}
413+
} else {
414+
## Create actual hydat_path
415+
hydat_path = paste0(dl_hydat_here,"Hydat.sqlite3")
416+
#path_to = gsub("Hydat.sqlite3", "",hydat_path)
417+
}
418+
335419

420+
421+
temp = tempfile()
422+
336423

337-
#download_hydat <- function() {
338-
# url <- 'http://collaboration.cmc.ec.gc.ca/cmc/hydrometrics/www/'
339-
#
340-
# date_string <- substr(gsub("^.*\\Hydat_sqlite3_","",
341-
# RCurl::getURL(url)), 1,8)
342-
#
343-
# to_get_hydat <-paste0(url, "Hydat_sqlite3_", date_string,".zip")
344-
#
345-
# message(paste0("Proceed to this link to download a zip file of hydat", to_get_hydat))
346-
#
347-
#
348-
#
349-
#}
424+
425+
## If there is an existing hydat file get the date of release
426+
if( length(list.files(dl_hydat_here, pattern = "Hydat.sqlite3")) == 1 ){
427+
VERSION(hydat_path) %>%
428+
mutate(condensed_date = paste0(substr(Date, 1,4),
429+
substr(Date, 6,7),
430+
substr(Date, 9,10)
431+
)) %>%
432+
pull(condensed_date) -> existing_hydat
433+
} else{
434+
existing_hydat = "HYDAT not present"
435+
}
436+
437+
438+
## Create the link to download HYDAT
439+
base_url = "http://collaboration.cmc.ec.gc.ca/cmc/hydrometrics/www/"
440+
x <- httr::GET(base_url)
441+
new_hydat = substr(gsub("^.*\\Hydat_sqlite3_", "",
442+
httr::content(x, "text")
443+
), 1, 8)
444+
445+
## Do we need to download a new version?
446+
if(new_hydat == existing_hydat){
447+
stop(paste0("Existing version of hydat, published on ",lubridate::ymd(existing_hydat),", is the most recent version available."))
448+
} else{
449+
message(paste0("Downloading version of hydat published on ",lubridate::ymd(new_hydat)))
450+
}
451+
452+
url = paste0(base_url , "Hydat_sqlite3_", new_hydat , ".zip")
453+
454+
utils::download.file(url,temp)
455+
456+
utils::unzip(temp, files=(unzip(temp, list=TRUE)$Name[1]), exdir=dl_hydat_here, overwrite=TRUE)
457+
458+
}

0 commit comments

Comments
 (0)