diff --git a/R/gefs.R b/R/gefs.R index 4160f06c..73e265af 100644 --- a/R/gefs.R +++ b/R/gefs.R @@ -116,9 +116,19 @@ gefs_GET <- function(var, lat, lon, raw = FALSE, ...) { - #Sanity Checks + ###Sanity Checks if (missing(var)) stop("Need to specify the variable to get. A list of variables is available from gefs_variables().") + # lats and lons must be sequential and within ranges + lats <- sort(round(lat, 0)) + if (!all(lats == seq(lats[1], length.out = length(lats)))) stop("Latitudes must be sequential.") + if (any(lats < -90 | lats > 90)) stop("Latitudes must be in c(-90,90).") + + lons <- sort(round(lon, 0)) + if (!all(lons == seq(lons[1], length.out = length(lons)))) stop("Longitudes must be sequential.") + if (any(lons < -180 | lons > 360)) stop("Longitudes must be in c(-180,180) or c(0,360).") + + #get a connection con <- gefs_CONNECT(date, forecast_time) @@ -165,11 +175,13 @@ gefs_GET <- function(var, lat, lon, #create the data frame #For now, if lat/lon are not specified, just return a matrix. - if (raw==FALSE) { + if (!raw) { dim_vals <- lapply(1:length(dim_idxs), function(i) { v$dim[[i]]$vals[dim_idxs[[i]]] }) names(dim_vals) <- names(dim_idxs) d = cbind(as.data.frame(as.vector(d_raw)), expand.grid(dim_vals)) names(d)[[1]] <- var + } else { + d <- d_raw } fname <- strsplit(con$filename, "_")[[1]] diff --git a/man/gefs.Rd b/man/gefs.Rd index de749556..e093e5c2 100644 --- a/man/gefs.Rd +++ b/man/gefs.Rd @@ -34,11 +34,11 @@ gefs_dimension_values(dim, con = NULL, ...) \item{var}{the variable to get. Must be one of the variables listed in \code{gefs_variables()}} -\item{lat}{the latitude. Values must be sequential and are rounded to the nearest GEFS available -latitude.} +\item{lat}{the latitude. Values must be sequential and are rounded to the +nearest GEFS available latitude.} -\item{lon}{the longitude. Values must be sequential and are rounded to the nearest GEFS available -longitude.} +\item{lon}{the longitude. Values must be sequential and are rounded to the +nearest GEFS available longitude.} \item{...}{additional parameters passed to \code{ncvar_get}} diff --git a/tests/testthat/test-gefs.R b/tests/testthat/test-gefs.R index 6bc964ec..9f248064 100644 --- a/tests/testthat/test-gefs.R +++ b/tests/testthat/test-gefs.R @@ -1,11 +1,11 @@ context("gefs") #set a location -lat = 46.28125 -lon = -116.2188 +lons <- c(-1.1, 0, 0.8, 2) +lats <- c(50.1, 51, 51.9, 53, 54) #variable -var = "Temperature_height_above_ground_ens" +temp = "Temperature_height_above_ground_ens" test_that("gefs errors", { skip_on_cran() @@ -13,51 +13,64 @@ test_that("gefs errors", { skip_on_travis() expect_error(gefs(lat=lat, lon=lon), "Need to specify the variable to get. A list of variables is available from gefs_variables().") + expect_error(gefs(var = temp, lat = c(-43, -41), lon = lons, ens_idx = 1, time_idx = 1), "Latitudes must be sequential.", fixed = TRUE) + expect_error(gefs(var = temp, lat = lats, lon = c(213, 211), ens_idx = 1, time_idx = 1), "Longitudes must be sequential.", fixed = TRUE) + expect_error(gefs(var = temp, lat = -91, lon = lons, ens_idx = 1, time_idx = 1), "Latitudes must be in c(-90,90).", fixed = TRUE) + expect_error(gefs(var = temp, lat = 91, lon = lons, ens_idx = 1, time_idx = 1), "Latitudes must be in c(-90,90).", fixed = TRUE) + expect_error(gefs(var = temp, lat = lats, lon = 361, ens_idx = 1, time_idx = 1), "Longitudes must be in c(-180,180) or c(0,360).", fixed = TRUE) + expect_error(gefs(var = temp, lat = lats, lon = -181, ens_idx = 1, time_idx = 1), "Longitudes must be in c(-180,180) or c(0,360).", fixed = TRUE) }) -test_that("gefs latitude and longitude selection returns correct values", { +test_that("gefs HTTP requests", { skip_on_cran() skip_on_travis() skip_on_appveyor() - a <- gefs("u-component_of_wind_height_above_ground_ens", - ens_idx = 1, - time_idx = 1, + ### Get raw and processed data + d_raw <- gefs(var = temp, + ens_idx = 1:2, + time_idx = 1:2, + forecast_time = "0000", + lon = lons, lat = lats, raw = TRUE) + d <- gefs(var = temp, + ens_idx = 1:2, + time_idx = 1:2, forecast_time = "0000", - lon = c(-1:2), lat = c(50:54)) + lon = lons, lat = lats) - expect_true(all(unique(a$data$lon) == c(0,1,2,359))) - expect_true(all(unique(a$data$lat) == c(54,54,54,54))) -}) + ### Tests of object type + expect_type(d, "list") + expect_equal(names(d), + c("forecast_date", "forecast_time", "dimensions", "data")) + expect_equal(d$forecast_date, format(Sys.time(), "%Y%m%d")) + expect_equal(d$forecast_time, "0000") + expect_s3_class(d$data, "data.frame") -test_that("gefs time and ensemble selection returns correct indices.", { - skip_on_cran() - skip_on_travis() - skip_on_appveyor() + ### Tests of indices + expect_true(all(sort(unique(d$data$lon)) == sort(round(lons %% 360, 0)))) + expect_true(all(sort(unique(d$data$lat)) == sort(round(lats, 0)))) - ens_idx = 2:4 - time_idx = 5:10 - d = gefs(var, lat, lon, ens_idx = ens_idx, time_idx = time_idx) + ### Tests of data transformation from multidimensional array to data frame + grid <- expand.grid(lon = round(lons %% 360, 0), lat = round(lats, 0), + ens = 1:2, time = 1:2) - time_var <- names(d$data)[6] - expect_equal(dim(d$data), c(length(ens_idx) * length(time_idx), 6)) - expect_equal(unique(d$data$ens), ens_idx - 1) -}) + expect_equal(nrow(d$data), nrow(grid)) -test_that("gefs metadata", { - skip_on_cran() - skip_on_travis() - skip_on_appveyor() + # NOTE: Remember that GEFS returns latitude in reverse order, i.e. -90:90 - today = format(as.Date(Sys.time()) - 2, "%Y%m%d") - forecast_time = "0600" - d = gefs(var, lat, lon, ens=1, date=today, forecast_time=forecast_time) + # 2nd lon, all lats, 1st ens, 2nd time + expect_true(all(d_raw$data[2,,1,2] == d$data[d$data$lon == lons[[2]] & + d$data$ens == 0 & + d$data$time2 == 1,][[temp]])) - expect_equal(d$forecast_date, today) - expect_equal(d$forecast_time, forecast_time) - expect_equal(d$dimensions[1:4], c("lon", "lat", "height_above_ground", "ens")) -}) + # All lons, last lat, 1st ens, 1st time + expect_true(all(d_raw$data[,length(lats),1,2] == d$data[ + d$data$lat == round(sort(lats, decreasing = TRUE)[[length(lats)]]) & + d$data$ens == 0 & + d$data$time2 == 1,][[temp]])) +}) + test_that("gefs_variables returns characters.", { skip_on_cran() skip_on_travis()