Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
khufkens committed Nov 6, 2018
0 parents commit ca29144
Show file tree
Hide file tree
Showing 22 changed files with 1,427 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
^\.travis\.yml$
^.*\.Rproj$
^.*\.Renviron$
^\.Rproj\.user$
^README\.Rmd$
^README\.md$
^_config\.yml$
^cran-comments\.md$
^CONDUCT\.md$
^NEWS\.md$
^LICENSE$
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.Rproj.user
.Rhistory
.Renviron
.RData
.Ruserdata
inst/doc
20 changes: 20 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
language: R
sudo: required
cache: packages
warnings_are_errors: true

before_install:
- sudo apt-get install --yes udunits-bin libudunits2-dev
- sudo apt-get install --yes libproj-dev libgeos-dev libgdal-dev libgdal1-dev
- sudo apt-get install --yes libnetcdf-dev netcdf-bin

r:
- release
- devel

r_packages:
- devtools
- covr

after_success:
- Rscript -e 'covr::codecov()'
25 changes: 25 additions & 0 deletions CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Contributor Code of Conduct

As contributors and maintainers of this project, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.

We are committed to making participation in this project a harassment-free experience for
everyone, regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.

Examples of unacceptable behavior by participants include the use of sexual language or
imagery, derogatory comments or personal attacks, trolling, public or private harassment,
insults, or other unprofessional conduct.

Project maintainers have the right and responsibility to remove, edit, or reject comments,
commits, code, wiki edits, issues, and other contributions that are not aligned to this
Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed
from the project team.

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
opening an issue or contacting one or more of the project maintainers.

This Code of Conduct is adapted from the Contributor Covenant
(http:contributor-covenant.org), version 1.0.0, available at
http://contributor-covenant.org/version/1/0/0/
24 changes: 24 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Package: ecmwfr
Title: Interface to the public 'ECMWF' Web Services
Version: 0.0.2
Authors@R: person("Hufkens","Koen",
email="[email protected]",
role=c("aut", "cre"))
Description: Programmatic interface to the 'ECMWF' public dataset
web services. Allows for easy downloads of
climate data directly to your R workspace or your computer.
Depends:
R (>= 3.4.0)
Imports:
httr,
keyring
License: AGPL-3
LazyData: true
ByteCompile: true
RoxygenNote: 6.1.0
Suggests:
knitr,
rmarkdown,
covr,
testthat
VignetteBuilder: knitr
664 changes: 664 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# ecmwfr 0.0.2

* working verion, yeah!


# ecmwfr 0.0.1

* experimental release
* trying to get things working
55 changes: 55 additions & 0 deletions R/ecmwf_delete.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#' ECMWF delete request
#'
#' Deletes a staged download from the queue
#'
#' @param email email address used to sign up for the ECMWF data service and
#' used to retrieve the token set by \code{\link[ecmwfr]{ecmwf_set_key}}
#' @param url url to query
#' @keywords data download, climate, re-analysis
#' @seealso \code{\link[ecmwfr]{ecmwf_set_key}}
#' \code{\link[ecmwfr]{ecmwf_download}}
#' \code{\link[ecmwfr]{ecmwf_request}}
#' @export
#' @examples
#'
#' \donttest{
#' # set key
#' ecmwf_set_key(email = "[email protected]", key = "123")
#'
#' # get key
#' ecmwf_get_key(email = "[email protected]")
#'}


ecmwf_delete <- function(
email,
url
){

# check the login credentials
if(missing(email) | missing(url)){
stop("Please provide ECMWF login email / url!")
}

# get key from email
key <- ecmwf_get_key(email)

# Finally when all went well we have to remove the subset
# from the queued list so that memory is de-allocated on the
# ECMWF server!
response <- httr::DELETE(
url,
httr::add_headers(
"Accept" = "application/json",
"Content-Type" = "application/json",
"From" = email,
"X-ECMWF-KEY" = key)
)

# check purging of request
if(response$status == 204){
message("Request purged from queue!")
} else {
warning("Request not purged from queue, check download!")
}
}
69 changes: 69 additions & 0 deletions R/ecmwf_download.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#' ECMWF download request
#'
#' Returns the contents of the requested url as a netCDF file downloaded
#' to disk.
#'
#' @param email email address used to sign up for the ECMWF data service and
#' used to retrieve the token set by \code{\link[ecmwfr]{ecmwf_set_key}}
#' @param url url to query
#' @param path path were to store the downloaded data
#' @param filename filename to use for the downloaded data
#' @return a netCDF of data on disk as specified by a
#' \code{\link[ecmwfr]{ecmwf_request}}
#' @keywords data download, climate, re-analysis
#' @seealso \code{\link[ecmwfr]{ecmwf_set_key}}
#' \code{\link[ecmwfr]{ecmwf_download}}
#' \code{\link[ecmwfr]{ecmwf_request}}
#' @export
#' @examples
#'
#' \donttest{
#' # set key
#' ecmwf_set_key(email = "[email protected]", key = "123")
#'
#' # get key
#' ecmwf_get_key(email = "[email protected]")
#'}


ecmwf_download <- function(
email,
url,
path = tempdir(),
filename = "ecmwf_tmp.nc"
){

# check the login credentials
if(missing(email) | missing(url)){
stop("Please provide ECMWF login email / url!")
}

# get key from email
key <- ecmwf_get_key(email)

# create temporary output file
ecmwf_tmp_files <- file.path(tempdir(), filename)

# provide some feedback on the url which is
# downloaded
message("Downloading request at:")
message(ct$href)

# submit download query
response <- httr::GET(
ct$href,
httr::add_headers(
"Accept" = "application/json",
"Content-Type" = "application/json",
"From" = email,
"X-ECMWF-KEY" = key),
httr::progress(),
encode = "json",
httr::write_disk(path = ecmwf_tmp_file, overwrite = TRUE)
)

# trap errors on download, return a general error statement
if (httr::http_error(response)){
stop("Your requested download failed", call. = FALSE)
}
}
23 changes: 23 additions & 0 deletions R/ecmwf_get_key.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#' Get secret ECMWF token
#'
#' Returns you token set by ecmwf_set_key()
#'
#' @param email email address used to sign up for the ECMWF data service
#' @return the key set using ecmwf_set_key() saved in the keychain
#' @keywords key management
#' @seealso \code{\link[ecmwfr]{ecmwf_set_key}}
#' @export
#' @examples
#'
#' \donttest{
#' # set key
#' ecmwf_set_key(email = "[email protected]", key = "123")
#'
#' # get key
#' ecmwf_get_key(email = "[email protected]")
#'}

ecmwf_get_key <- function(email, key){
keyring::key_get(service = "ecmwfr",
username = email)
}
141 changes: 141 additions & 0 deletions R/ecmwf_request.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#' ECMWF data request and download
#'
#' Stage a data request, and optionally download the data to disk. Alternatively
#' you can only stage requests, logging the request URLs to submit download
#' queries later on using \code{\link[ecmwfr]{ecmwf_download}}
#'
#' @param email email address used to sign up for the ECMWF data service and
#' used to retrieve the token set by \code{\link[ecmwfr]{ecmwf_set_key}}
#' @param path path were to store the downloaded data
#' @param time_out how long to wait on a download to start
#' @param download logical, download data TRUE or FALSE (default = FALSE)
#' @param request nested list with query parameters following the layout
#' as specified on the ECMWF API page
#' @return a download query staging url or a netCDF of data on disk
#' @keywords data download, climate, re-analysis
#' @seealso \code{\link[ecmwfr]{ecmwf_set_key}}
#' \code{\link[ecmwfr]{ecmwf_download}}
#' \code{\link[ecmwfr]{ecmwf_status}}
#' @export
#' @examples
#'
#' \donttest{
#' # set key
#' ecmwf_set_key(email = "[email protected]", key = "123")
#'
#' # get key
#' ecmwf_get_key(email = "[email protected]")
#'}

ecmwf_request <- function(
email,
path = tempdir(),
time_out = 3600,
download = FALSE,
request = list(stream = "oper",
levtype = "sfc",
param = "165.128/166.128/167.128",
dataset = "interim",
step = "0",
grid = "0.75/0.75",
time = "00/06/12/18",
date = "2014-07-01/to/2014-07-31",
type = "an",
class = "ei",
area = "73.5/-27/33/45",
format = "netcdf",
target = "tmp.nc")){

# check the login credentials
if(missing(email) | missing(request)){
stop("Please provide ECMWF login credentials and data request!")
}

# get key from email
key <- ecmwf_get_key(email)

# get the response from the query provided
response <- httr::POST(
paste(ecmwf_server(),
"datasets",
request$dataset,
"requests", sep = "/"),
httr::add_headers(
"Accept" = "application/json",
"Content-Type" = "application/json",
"From" = email,
"X-ECMWF-KEY" = key),
body = request,
encode = "json"
)

# line to trap general httr error (server not reachable etc.)

# grab content, to look at the status
ct <- httr::content(response)

# if the status code is >= 400 stop
if(ct$code >= 400){
stop("Your request was malformed, check your request statement",
call. = FALSE)
}

# only return the content of the query
if(!download){
return(ct)
}

# set spinner count for some feedback
# downloads can take a while it seems
spinner_count <- 1

# start time-out counter
time_out_start <- Sys.time()

# keep waiting for the download order to come online
# with status code 303
while(ct$code == 202){

# update spinner count
spinner_count <- ifelse(spinner_count < 4, spinner_count + 1, 1)

# update spinner message
message(paste0(c("-","\\","|","/")[spinner_count],
" Your request is ",
ct$status,
", waiting on server response...\r"), appendLF = FALSE)

# sleep for the time (in seconds) provided
# in the content returned upon query
Sys.sleep(ct$retry)

# check the status of the download, no download
ct <- ecmwf_status(email = email, url = ct$href)
}

# if the http code is 303 (a redirect)
# follow this query and download the data
if(ct$code == 303){
ecmwf_download(email = email)
}

# Copy data from temporary file to final location
# and delete original, with an exception for tempdir() location.
# The latter to facilitate package integration.
if (path != tempdir()) {

# copy temporary file to final destination
file.copy(ecmwf_tmp_file,
file.path(path, request$target),
overwrite = TRUE,
copy.mode = FALSE)

# cleanup of temporary file
invisible(file.remove(ecmwf_tmp_file))
} else {
message("Output path == tempdir(), file not copied and removed!")
}

# delete the request upon succesful download
ecmwf_delete(email = email, url = ct$href)
}
Loading

0 comments on commit ca29144

Please sign in to comment.