diff --git a/DESCRIPTION b/DESCRIPTION index 0699598dd1c5b68462fe88bc685decf6a3118831..82932749662559bc2486703db321dbabde0f3b4d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -29,5 +29,6 @@ LazyData: true RoxygenNote: 5.0.0 Suggests: knitr, + testthat, rmarkdown VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index e844fcba507d50c74a4134ac8da2afb5cc73769f..03fa0de4a2997108d8994eac872d50842c898dab 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -7,6 +7,7 @@ export(DTRIndicator) export(DTRRef) export(DailyAno) export(Extremes) +export(Lon2Index) export(SeasonSelect) export(SelBox) export(Subset) diff --git a/R/Climdex.R b/R/Climdex.R index 261815c87202730a27012c9d64bc924017db340b..20c3e4301c453c1eb8fc7b41f9044298a415a9b7 100644 --- a/R/Climdex.R +++ b/R/Climdex.R @@ -373,7 +373,7 @@ Climdex <- function(data, metric, threshold = NULL, base.range = NULL, dates = N #' @noRd .nday.consec.prec.max <- function(daily.prec, date.factor, ndays, center.mean.on.last.day=FALSE) { if(ndays == 1) { - return(suppressWarnings(tapply.fast(daily.prec, date.factor, max, na.rm=TRUE))) + return(suppressWarnings(.tapply.fast(daily.prec, date.factor, max, na.rm=TRUE))) } ## Ends of the data will be de-emphasized (padded with zero precip data); NAs replaced with 0 daily.prec[is.na(daily.prec)] <- 0 diff --git a/R/Extremes.R b/R/Extremes.R index 30dd5698cd89eed9dd3bcfd445c98a4ec358229b..a60934044e546f29c5758e1b4f482c4fb75be81e 100644 --- a/R/Extremes.R +++ b/R/Extremes.R @@ -91,9 +91,9 @@ Extremes <- function(data, threshold, op = ">", min.length = 6, spells.can.span. if (!any(class(dates) %in% c('POSIXct'))) { dates <- try( { if (is.character(dates)) { - as.POSIXct(dates, format = "%Y%m%d") + as.POSIXct(dates, format = "%Y%m%d", tz = "CET") } else { - as.POSIXct(dates) + as.POSIXct(dates, format = "%Y%m%d", tz = "CET") } }) if ('try-error' %in% class(dates) | sum(is.na(dates)) == length(dates)) { @@ -113,8 +113,8 @@ Extremes <- function(data, threshold, op = ">", min.length = 6, spells.can.span. if (stop_error) { stop("Parameter 'dates' must be of the same length as the 'time' dimension of the parameter 'data'.") } - dates <- as.PCICt(dates, cal = calendar) - dates = as.character(dates) + dates <- as.PCICt(dates, cal = calendar, format = "%Y%m%d") +# dates = as.character(dates) jdays <- as.numeric(strftime(dates, format = "%j")) if (calendar == "gregorian" | calendar == "standard" | calendar == "proleptic_gregorian") { year <- as.numeric(strftime(dates, format = "%Y")) diff --git a/R/Lon2Index.R b/R/Lon2Index.R new file mode 100644 index 0000000000000000000000000000000000000000..1ab719714f75954d954e2a58cb9cea48ab9eb826 --- /dev/null +++ b/R/Lon2Index.R @@ -0,0 +1,87 @@ +#'Obtain the index of positions for a region in longitudes +#' +#'@description This auxiliary function returns the index of position of a region of longitudes in a given vector of longitudes. +#' +#'@param lon vector of longitudes values. +#'@param lonmin a numeric value indicating the minimum longitude of the region (understand as the left marging of the region). +#'@param lonmax a numeric value indicating the maximum longitude of the region (understand as the right mariging of the region). +#' +#'@return the index of positions of all values inside the region in the vector lon. +#' +#'@examples +#' +#'lon <- 1 : 360 +#'pos <- Lon2Index(lon, lonmin = -20, lonmax = 20) +#'lon[pos] +#'pos <- Lon2Index(lon, lonmin = 340, lonmax = 20) +#'lon[pos] +#'lon <- -180 : 180 +#'pos <- Lon2Index(lon, lonmin = -20, lonmax = 20) +#'lon[pos] +#'pos <- Lon2Index(lon, lonmin = 340, lonmax = 20) +#'lon[pos] +#' +#'@export +Lon2Index <- function(lon, lonmin, lonmax) { + if (is.null(lon)) { + stop("Parameter 'lon' cannot be NULL.") + } + if (!is.numeric(lon)) { + stop("Parameter 'lon' must be numeric.") + } + if (!is.vector(lon)) { + stop("Parameter 'lon' must be a vector.") + } + if (!is.numeric(lonmin) | !is.numeric(lonmax)) { + stop("Parameter 'lonmin' and 'lonmax' must be numeric.") + } + if (!is.vector(lonmin) | !is.vector(lonmax)) { + stop("Parameter 'lonmin'and 'lonmax' must be a vector.") + } + + vlonmax <- max(lon) + vlonmin <- min(lon) + if (vlonmin < 0 & !(vlonmax > 180)) { # -180 to 180 + if (lonmin < -180) { + stop("Change parameter 'lonmin' to match longitudes ", + "in the range -180 to 180.") + } else if (lonmin > 180) { + lonmin <- lonmin - 360 + } + if (lonmax < -180) { + stop("Change parameter 'lonmax' to match longitudes ", + "in the range -180 to 180.") + } else if (lonmax > 180) { + lonmax <- lonmax - 360 + } + if (lonmin > lonmax) { + index <- c(which(lon >= lonmin), which(lon <= lonmax)) + } else { + index <- which(lon >= lonmin & lon <= lonmax) + } + } else if (vlonmin < 0 & vlonmax > 180) { # -360 to 360 + if (lonmin > lonmax) { + index <- c(which(lon >= lonmin), which(lon <= lonmax)) + } else { + index <- which(lon >= lonmin & lon <= lonmax) + } + } else { # 0 : 360 + if (lonmin < 0) { + lonmin <- lonmin + 360 + } else if (lonmin > 360) { + lonmin <- lonmin - 360 + } + if (lonmax < 0) { + lonmax <- lonmax + 360 + } else if (lonmax > 360) { + lonmax <- lonmax - 360 + } + if (lonmin > lonmax) { + index <- c(which(lon >= lonmin), which(lon <= lonmax)) + } else { + index <- which(lon >= lonmin & lon <= lonmax) + } + } + +return(index) +} diff --git a/R/SelBox.R b/R/SelBox.R index 608e19e0d65121960a1488765ed3f6b1f1d4ef98..5b7cd5982583f278142a8321c250539115676027 100644 --- a/R/SelBox.R +++ b/R/SelBox.R @@ -83,11 +83,13 @@ SelBox <- function(data, lon, lat, region, londim = NULL, latdim = NULL, mask = } else { LatIdx <- which(lat <= region[3] | lat >= region[4]) } - if (region[1] <= region[2]) { - LonIdx <- which(lon >= region[1] & lon <= region[2]) - } else { - LonIdx <- which(lon >= region[1] | lon <= region[2]) - } + #if (region[1] <= region[2]) { + # LonIdx <- which(lon >= region[1] & lon <= region[2]) + #} else { + # LonIdx <- which(lon >= region[1] | lon <= region[2]) + #} + LonIdx <- Lon2Index(lon, lonmin = region[1], lonmax = region[2]) + data <- Subset(data, along = londim, indices = LonIdx, drop = "none") data <- Subset(data, along = latdim, indices = LatIdx, drop = "none") if (!is.null(mask)) { diff --git a/man/Extremes.Rd b/man/Extremes.Rd index 0939fa67275433b18b9f62df84150911ea72e352..61b312a1914f656ed97245920cfa4c447052e535 100644 --- a/man/Extremes.Rd +++ b/man/Extremes.Rd @@ -46,7 +46,8 @@ This routine compares data to the thresholds using the given operator, generatin ##Example synthetic data: data <- 1:(2 * 3 * 372 * 1) dim(data) <- c(time = 372, lon = 2, lat = 3, model = 1) -time <- as.POSIXct(paste(sort(rep(1900:1911, 31)), 1, 1:31, sep = "-"), tz = "CET") +time <- as.POSIXct(paste(sort(rep(1900:1911, 31)), 1, 1:31, sep = "-"), tz = "CET", + format = "\%Y-\%m-\%d") metadata <- list(time = list(standard_name = 'time', long_name = 'time', calendar = 'noleap', units = 'days since 1970-01-01 00:00:00', prec = 'double', dim = list(list(name = 'time', unlim = FALSE)))) diff --git a/man/Lon2Index.Rd b/man/Lon2Index.Rd new file mode 100644 index 0000000000000000000000000000000000000000..b2012a61f97126ee886ba942f3e5020961d29994 --- /dev/null +++ b/man/Lon2Index.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Lon2Index.R +\name{Lon2Index} +\alias{Lon2Index} +\title{Obtain the index of positions for a region in longitudes} +\usage{ +Lon2Index(lon, lonmin, lonmax) +} +\arguments{ +\item{lon}{vector of longitudes values.} + +\item{lonmin}{a numeric value indicating the minimum longitude of the region (understand as the left marging of the region).} + +\item{lonmax}{a numeric value indicating the maximum longitude of the region (understand as the right mariging of the region).} +} +\value{ +the index of positions of all values inside the region in the vector lon. +} +\description{ +This auxiliary function returns the index of position of a region of longitudes in a given vector of longitudes. +} +\examples{ + +lon <- 1 : 360 +pos <- Lon2Index(lon, lonmin = -20, lonmax = 20) +lon[pos] +pos <- Lon2Index(lon, lonmin = 340, lonmax = 20) +lon[pos] +lon <- -180 : 180 +pos <- Lon2Index(lon, lonmin = -20, lonmax = 20) +lon[pos] +pos <- Lon2Index(lon, lonmin = 340, lonmax = 20) +lon[pos] + +} + diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 0000000000000000000000000000000000000000..6b1f95fe7d2e17b7d026368643c5dd5ffb760f3e --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,5 @@ +library(testthat) +library(ClimProjDiags) + +test_check("ClimProjDiags") + diff --git a/tests/testthat/test-Lon2index.R b/tests/testthat/test-Lon2index.R new file mode 100644 index 0000000000000000000000000000000000000000..8f530796f4911d759b3972a588fbcc265e59b763 --- /dev/null +++ b/tests/testthat/test-Lon2index.R @@ -0,0 +1,98 @@ +context("Generic tests") +test_that("Sanity checks", { + expect_error(Lon2Index(lon = NULL), "Parameter 'lon' cannot be NULL.") + expect_error(Lon2Index(lon = 'a'), "Parameter 'lon' must be numeric.") + expect_error(Lon2Index(lon = 1), + 'argument "lonmin" is missing, with no default') + expect_error(Lon2Index(lon = 1, lonmin = 'a'), + 'argument "lonmax" is missing, with no default') + expect_error(Lon2Index(lon = 1, lonmin = 'a', lonmax = 1), + "Parameter 'lonmin' and 'lonmax' must be numeric.") + expect_error(Lon2Index(lon = 1, lonmin = 1, lonmax = 'b'), + "Parameter 'lonmin' and 'lonmax' must be numeric.") + expect_equal(Lon2Index(lon = 1, lonmin = 1, lonmax = 1), 1) +}) + +test_that("Case 1 to 360", { +lon <- 1 : 360 + expect_equal(Lon2Index(lon, lonmin = -20, lonmax = 20), + c(340 : 360, 1 : 20)) + expect_equal(Lon2Index(lon, lonmin = 340, lonmax = 20), + c(340 : 360, 1 : 20)) + expect_equal(Lon2Index(lon, lonmin = 20, lonmax = 340), + 20 : 340) + expect_equal(Lon2Index(lon, lonmin = -40, lonmax = -20), + 320 : 340) + expect_equal(Lon2Index(lon, lonmin = 320, lonmax = 340), + 320 : 340) + expect_equal(Lon2Index(lon, lonmin = -220, lonmax = -170), + 140 : 190) + expect_equal(Lon2Index(lon, lonmin = -350, lonmax = -300), + 10 : 60) + expect_equal(Lon2Index(lon, lonmin = -400, lonmax = -370), integer(0)) + expect_equal(Lon2Index(lon, lonmin = 340, lonmax = 380), + c(340 : 360, 1 : 20)) +}) + +test_that("Case -180 to 180", { +lon <- -180 : 180 + expect_equal(Lon2Index(lon, lonmin = -20, lonmax = 20), + 161 : 201) + expect_equal(Lon2Index(lon, lonmin = 340, lonmax = 20), + 161 : 201) + expect_equal(Lon2Index(lon, lonmin = 20, lonmax = 340), + c(201 : 361, 1 : 161)) + expect_equal(Lon2Index(lon, lonmin = -40, lonmax = -20), + 141 : 161) + expect_equal(Lon2Index(lon, lonmin = 320, lonmax = 340), + 141 : 161) + expect_error(Lon2Index(lon, lonmin = -220, lonmax = -170), + "Change parameter 'lonmin' to match longitudes in the range -180 to 180.") + expect_error(Lon2Index(lon, lonmin = -350, lonmax = -300), + "Change parameter 'lonmin' to match longitudes in the range -180 to 180.") + expect_error(Lon2Index(lon, lonmin = -400, lonmax = -370), + "Change parameter 'lonmin' to match longitudes in the range -180 to 180.") + expect_equal(Lon2Index(lon, lonmin = 340, lonmax = 380), + 161 : 201) +}) + +test_that("Case -360 to 360", { +lon <- -360 : 360 + expect_equal(Lon2Index(lon, lonmin = -20, lonmax = 20), + 341 : 381) + expect_equal(Lon2Index(lon, lonmin = 340, lonmax = 20), + c(701 : 721, 1 : 381)) + expect_equal(Lon2Index(lon, lonmin = 20, lonmax = 340), + 381 : 701) + expect_equal(Lon2Index(lon, lonmin = -40, lonmax = -20), + 321 : 341) + expect_equal(Lon2Index(lon, lonmin = 320, lonmax = 340), + 681 : 701) + expect_equal(Lon2Index(lon, lonmin = -220, lonmax = -170), + 141 : 191) + expect_equal(Lon2Index(lon, lonmin = -350, lonmax = -300), + 11 : 61) + expect_equal(Lon2Index(lon, lonmin = -400, lonmax = -370), integer(0)) + expect_equal(Lon2Index(lon, lonmin = 340, lonmax = 380), + 701 : 721) +}) + + + + + + + + + + + + + + + + + + + +