diff --git a/.Rbuildignore b/.Rbuildignore index dde50c4ed94c4e248b7326787171e0c149ff9d42..0c51051b11ebbdf7186d1dd310c9236ea5062d82 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -5,5 +5,5 @@ ./.nc$ .*\.gitlab-ci.yml$ # Ignore tests when submitting to CRAN -^tests$ +#^tests$ diff --git a/R/SelBox.R b/R/SelBox.R index 5b7cd5982583f278142a8321c250539115676027..bab99bd5e14e8cf7baab8c4381478d6d5dec873c 100644 --- a/R/SelBox.R +++ b/R/SelBox.R @@ -1,21 +1,35 @@ -#'Select apatial region from multidimensional arrays +#'Select spatial region from multidimensional arrays #' -#'@description This function subsets an spatial region from spatial data giving a vector with the maximum and minimum of latitudes and longitudes of the selected region. +#'@description Subset a spatial region from spatial data giving a vector with +#' the maximum and minimum of latitudes and longitudes of the selected region. #' #'@param data An array with minimum two dimensions of latitude and longitude. -#'@param lon Numeric vector of longitude locations of the cell centers of the grid of \code{data}'. -#'@param lat Numeric vector of latitude locations of the cell centers of the grid of \code{data}'. -#'@param region A vector of length four indicating the minimum longitude, the maximum longitude, the minimum latitude and the maximum latitude. -#'@param londim An integer number indicating the position of the longitude dimension in the \code{data} object. If NULL (by deafault), the function search for a dimension call 'lon' in the \code{data} input. -#'@param latdim An integer number indicating the position of the latitude dimension in the \code{data} object. If NULL (by deafault), the function search for a dimension call 'lat' in the \code{data} input. +#'@param lon Numeric vector of longitude locations of the cell centers of the +#' grid of \code{data}'. +#'@param lat Numeric vector of latitude locations of the cell centers of the +#' grid of \code{data}'. +#'@param region A vector of length four indicating the minimum longitude, the +#' maximum longitude, the minimum latitude and the maximum latitude. +#'@param londim An integer number indicating the position of the longitude +#' dimension in the \code{data} object. If NULL (by deafault), the function +#' search for a dimension call 'lon' in the \code{data} input. +#'@param latdim An integer number indicating the position of the latitude +#' dimension in the \code{data} object. If NULL (by default), the function +#' searches for a dimension call 'lat' in the \code{data} input. #'@param mask A matrix with the same spatial dimensions of \code{data}. #' #'@return A list of length 4: #'\itemize{ -#' \item\code{$data}{An array with the same dimensions as the input \code{data} array, but with spatial dimension reduced to the selected \code{region}} -#' \item\code{$lat}{A vector with the new corresponding latitudes for the selected \code{region}} -#' \item\code{$lon}{A vector with the new corresponding longitudes for the selected \code{region}} -#' \item\code{$mask}{If parameter \code{mask} is supplied, an array with reduced length of the dimensions to the selected \code{region}. Otherwise, a NULL element is returned.}} +#' \item\code{$data}{ +#' An array with the same dimensions as the input \code{data} array, but with +#' spatial dimension reduced to the selected \code{region}} +#' \item\code{$lat}{A vector with the new corresponding latitudes for the +#' selected \code{region}} +#' \item\code{$lon}{A vector with the new corresponding longitudes for the +#' selected \code{region}} +#' \item\code{$mask}{If parameter \code{mask} is supplied, an array with +#' reduced length of the dimensions to the selected \code{region}. Otherwise, +#' a NULL element is returned.}} #' #'@examples #'## Example with synthetic data: @@ -29,11 +43,12 @@ #'str(a) #'@export SelBox <- function(data, lon, lat, region, londim = NULL, latdim = NULL, mask = NULL) { - if (is.null(data) | is.null(lon) | is.null(lat) | is.null(region)){ + + if (is.null(data) | is.null(lon) | is.null(lat) | is.null(region)) { stop("Parameters 'data', 'lon', 'lat' or 'region' cannot be NULL.") } - if (!is.numeric(data) | !is.numeric(lon) | !is.numeric(lat) | !is.numeric(region)){ - stop("Parameters 'data', 'lon', 'lat' or 'region' must be numeric.") + if (!is.numeric(lon) | !is.numeric(lat) | !is.numeric(region)) { + stop("Parameters 'lon', 'lat' or 'region' must be numeric.") } if (!is.array(data) && !is.matrix(data)) { stop("Parameter 'data' must be an array or matrix.") @@ -41,8 +56,9 @@ SelBox <- function(data, lon, lat, region, londim = NULL, latdim = NULL, mask = if (!is.null(dim(lat)) | !is.null(dim(lon))) { stop("Parameter 'lon' and lat' need to be a vector.") } - if (length(region) != 4){ - stop("The region argument has to be a vector of length four indicating the minimum longitude, the maximum longitude, the minimum latitude and the maximum latitude.") + if (length(region) != 4) { + stop("The region argument has to be a vector of length four indicating the ", + "minimum longitude, the maximum longitude, the minimum latitude and the maximum latitude.") } dims <- 1:length(dim(data)) if (is.null(londim)) { @@ -51,7 +67,8 @@ SelBox <- function(data, lon, lat, region, londim = NULL, latdim = NULL, mask = } else if (length(lon) %in% dim(data)) { londim <- which(dim(data) == length(lon)) if (length(londim) > 1) { - stop("More than one dimension of the parameter 'data' has the same length as 'lon' parameter.") + stop("More than one dimension of the parameter 'data' has the same length as ", + "'lon' parameter.") } } else { stop("Non of the dimensions of the parameter 'data' are of the same length as 'lon'.") diff --git a/R/ShiftLon.R b/R/ShiftLon.R index 88b034d929f246dc677ab80af4fac430d80e527b..1467108581c8bfe5adc5b1a2248fdd20db3bce0d 100644 --- a/R/ShiftLon.R +++ b/R/ShiftLon.R @@ -35,15 +35,20 @@ #' #'@import multiApply #'@export -ShiftLon <- function(data, lon, westB, lon_dim = 'lon', ncores = NULL) { +ShiftLon <- function(data, lon, westB, lon_dim = 'lon', ncores = NULL) { # Check inputs ## data if (is.null(data)) { stop("Parameter 'data' cannot be NULL.") } - if (!is.array(data) | !is.numeric(data)) { - stop("Parameter 'data' must be a numeric array.") + if (is.vector(data)) { + data <- as.array(data) + names(dim(data)) <- lon_dim + warning("Parameter 'data' is a vector. Transfer it to an array and assign ", lon_dim, " as dimension name.") + } + if (!is.array(data)) { + stop("Parameter 'data' must be an array.") } if(any(is.null(names(dim(data))))| any(nchar(names(dim(data))) == 0)) { stop("Parameter 'data' must have dimension names.") @@ -106,13 +111,15 @@ ShiftLon <- function(data, lon, westB, lon_dim = 'lon', ncores = NULL) { } else { new.lon <- c(lon[first:length(lon)],lon[1:(first-1)]) } - ## Order to monotonically increasing + ## Order to monotonically increasing if (!all(diff(new.lon) > 0)) { new.lon[(which(diff(new.lon) < 0) + 1):length(new.lon)] <- new.lon[(which(diff(new.lon) < 0) + 1):length(new.lon)] + 360 } # Shifting the data + ori_dim <- dim(data) + output <- Apply(data = data, target_dims = lon_dim, fun = .ShiftLon, @@ -122,13 +129,16 @@ ShiftLon <- function(data, lon, westB, lon_dim = 'lon', ncores = NULL) { # Shift new.lon back to start at westB new.lon <- new.lon + shft_westB_back - + + # Change dimension order back + output <- aperm(output, match(names(ori_dim), names(dim(output)))) + return(list(data = output, lon = new.lon)) } .ShiftLon <- function(data, lon, new.lon) { # data: [lon] - new.data <- NA * data + new.data <- data new.data[new.lon %in% lon] <- data[lon %in% new.lon, drop = F] new.data[!new.lon %in% lon] <- data[!lon %in% new.lon, drop = F] diff --git a/man/SelBox.Rd b/man/SelBox.Rd index 38e3547bf6ae6d6e699e78821aaefb1311896535..fa856298ade82bd606c309e5e4719e96dc93fd13 100644 --- a/man/SelBox.Rd +++ b/man/SelBox.Rd @@ -2,35 +2,49 @@ % Please edit documentation in R/SelBox.R \name{SelBox} \alias{SelBox} -\title{Select apatial region from multidimensional arrays} +\title{Select spatial region from multidimensional arrays} \usage{ SelBox(data, lon, lat, region, londim = NULL, latdim = NULL, mask = NULL) } \arguments{ \item{data}{An array with minimum two dimensions of latitude and longitude.} -\item{lon}{Numeric vector of longitude locations of the cell centers of the grid of \code{data}'.} +\item{lon}{Numeric vector of longitude locations of the cell centers of the +grid of \code{data}'.} -\item{lat}{Numeric vector of latitude locations of the cell centers of the grid of \code{data}'.} +\item{lat}{Numeric vector of latitude locations of the cell centers of the +grid of \code{data}'.} -\item{region}{A vector of length four indicating the minimum longitude, the maximum longitude, the minimum latitude and the maximum latitude.} +\item{region}{A vector of length four indicating the minimum longitude, the +maximum longitude, the minimum latitude and the maximum latitude.} -\item{londim}{An integer number indicating the position of the longitude dimension in the \code{data} object. If NULL (by deafault), the function search for a dimension call 'lon' in the \code{data} input.} +\item{londim}{An integer number indicating the position of the longitude +dimension in the \code{data} object. If NULL (by deafault), the function +search for a dimension call 'lon' in the \code{data} input.} -\item{latdim}{An integer number indicating the position of the latitude dimension in the \code{data} object. If NULL (by deafault), the function search for a dimension call 'lat' in the \code{data} input.} +\item{latdim}{An integer number indicating the position of the latitude +dimension in the \code{data} object. If NULL (by default), the function +searches for a dimension call 'lat' in the \code{data} input.} \item{mask}{A matrix with the same spatial dimensions of \code{data}.} } \value{ A list of length 4: \itemize{ - \item\code{$data}{An array with the same dimensions as the input \code{data} array, but with spatial dimension reduced to the selected \code{region}} - \item\code{$lat}{A vector with the new corresponding latitudes for the selected \code{region}} - \item\code{$lon}{A vector with the new corresponding longitudes for the selected \code{region}} - \item\code{$mask}{If parameter \code{mask} is supplied, an array with reduced length of the dimensions to the selected \code{region}. Otherwise, a NULL element is returned.}} + \item\code{$data}{ + An array with the same dimensions as the input \code{data} array, but with + spatial dimension reduced to the selected \code{region}} + \item\code{$lat}{A vector with the new corresponding latitudes for the + selected \code{region}} + \item\code{$lon}{A vector with the new corresponding longitudes for the + selected \code{region}} + \item\code{$mask}{If parameter \code{mask} is supplied, an array with + reduced length of the dimensions to the selected \code{region}. Otherwise, + a NULL element is returned.}} } \description{ -This function subsets an spatial region from spatial data giving a vector with the maximum and minimum of latitudes and longitudes of the selected region. +Subset a spatial region from spatial data giving a vector with + the maximum and minimum of latitudes and longitudes of the selected region. } \examples{ ## Example with synthetic data: diff --git a/tests/testthat/test-ShiftLon.R b/tests/testthat/test-ShiftLon.R index efa358ebb90cb2ac44903dd28f12492fab7a4cd1..e414b5c9641fec7a05abd21cd980879459c77851 100644 --- a/tests/testthat/test-ShiftLon.R +++ b/tests/testthat/test-ShiftLon.R @@ -17,6 +17,11 @@ dat3 <- array(1:512, dim = c(lon = 512, lat = 216, time = 2)) lon3 <- seq(0, 360, length.out = 513)[1:512] lat3 <- seq(-90, 90, length.out = 216) +# dat4: vector, logical +set.seed(1) +dat4 <- as.logical(sample(c(0, 1), replace = TRUE, size = 360)) +lon4 <- 0:359 + ############################################## test_that("1. Input checks", { # data @@ -24,14 +29,15 @@ test_that("1. Input checks", { ShiftLon(c()), "Parameter 'data' cannot be NULL." ) - expect_error( - ShiftLon(1:10), - "Parameter 'data' must be a numeric array." - ) expect_error( ShiftLon(array(1:10)), "Parameter 'data' must have dimension names." ) + expect_warning( + ShiftLon(1:10, lon = 1:10, westB = 2), + "Parameter 'data' is a vector. Transfer it to an array and assign lon as dimension name." + ) + # lon_dim expect_error( ShiftLon(dat1, lon1, lon_dim = 1), @@ -340,3 +346,15 @@ test_that("4. dat3", { ) }) + + +############################################## +test_that("5. dat4", { + + westB <- -10 +expect_equal( +suppressWarnings(as.vector(ShiftLon(dat4, lon4, westB)$data)), +dat4[c(351:360, 1:350)] +) + +})