diff --git a/R/CST_Subset.R b/R/CST_Subset.R index 35717757c0679bec88b8cdc293b99a24425f4116..372e39812329c4cc06624b37a427086d5a971cf2 100644 --- a/R/CST_Subset.R +++ b/R/CST_Subset.R @@ -71,6 +71,12 @@ CST_Subset <- function(x, along, indices, drop = FALSE, var_dim = NULL, stop("Parameter 'dat_dim' must be a character string.") } } + # Check indices + if (!is.list(indices)) { + if (length(along) == 1) { + indices <- list(indices) + } + } # Subset data x$data <- ClimProjDiags::Subset(x$data, along = along, @@ -85,12 +91,7 @@ CST_Subset <- function(x, along, indices, drop = FALSE, var_dim = NULL, # Only rename coordinates that have not been dropped if (dim_name %in% names(x$dims)) { # Subset coordinate by indices - if (is.null(dim(x$coords[[dim_name]])) | length(dim(x$coords[[dim_name]])) == 1) { - x$coords[[dim_name]] <- .subset_with_attrs(x$coords[[dim_name]], index) - } else { - x$coords[[dim_name]] <- ClimProjDiags::Subset(x$coords[[dim_name]], along = dim_name, - indices = index) - } + x$coords[[dim_name]] <- .subset_with_attrs(x$coords[[dim_name]], indices = index) } } # Remove dropped coordinates @@ -117,17 +118,6 @@ CST_Subset <- function(x, along, indices, drop = FALSE, var_dim = NULL, indices = index, drop = drop) } - if ((dim_name %in% names(x$dims)) && - (dim_name %in% names(x$attrs$Variable$metadata))) { - variable <- x$attrs$Variable$metadata[[dim_name]] - # Subset coords by indices - if (is.null(dim(variable)) | length(dim(variable)) == 1) { - x$attrs$Variable$metadata[[dim_name]] <- .subset_with_attrs(variable, index) - } else { - x$attrs$Variable$metadata[[dim_name]] <- ClimProjDiags::Subset(variable, along = dim_name, - indices = index) - } - } } # Remove metadata from variables that were dropped vars_to_keep <- na.omit(match(c(names(x$dims), (x$attrs$Variable$varName)), @@ -143,20 +133,33 @@ CST_Subset <- function(x, along, indices, drop = FALSE, var_dim = NULL, indices = time_indices, drop = drop) } + # Subset metadata + for (variable in 1:length(names(x$attrs$Variable$metadata))) { + if (any(along %in% names(dim(x$attrs$Variable$metadata[[variable]])))) { + dim_along <- along[along %in% names(dim(x$attrs$Variable$metadata[[variable]]))] + index_along <- indices[[which(along == dim_along)]] + x$attrs$Variable$metadata[[variable]] <- .subset_with_attrs(x$attrs$Variable$metadata[[variable]], + along = dim_along, + indices = index_along, + drop = drop) + } + } return(x) } -# Function to subset vectors with attributes +# Function to subset with attributes .subset_with_attrs <- function(x, ...) { - l <- x[...] - x.dims <- names(dim(x)) + args_subset <- list(...) + if (is.null(dim(x)) | length(dim(x)) == 1) { + l <- x[args_subset[['indices']]] + } else { + l <- ClimProjDiags::Subset(x, along = args_subset[['along']], + indices = args_subset[['indices']], + drop = args_subset[['drop']]) + } attr.names <- names(attributes(x)) attr.names <- attr.names[attr.names != 'names'] attr.names <- attr.names[attr.names != 'dim'] attributes(l)[attr.names] <- attributes(x)[attr.names] - if (is.null(dim(l))) { - dim(l) <- length(l) - } - names(dim(l)) <- x.dims return(l) } diff --git a/R/as.s2dv_cube.R b/R/as.s2dv_cube.R index e39e5cadb2130830631c994291c8a30ec19a71f6..75d6a6da8fbed42cda36f42af09af68c1d1c69b1 100644 --- a/R/as.s2dv_cube.R +++ b/R/as.s2dv_cube.R @@ -21,33 +21,30 @@ #'functions with the prefix \code{CST} from CSTools and CSIndicators packages. #'The object is mainly a list with the following elements:\cr #'\itemize{ -#' \item{'data', array with named dimensions.} -#' \item{'dims', named vector of the data dimensions.} -#' \item{'coords', named list with elements of the coordinates corresponding to -#' the dimensions of the data parameter. If any coordinate is not provided, it -#' is set as an index vector with the values from 1 to the length of the -#' corresponding dimension. The attribute 'indices' indicates wether the -#' coordinate is an index vector (TRUE) or not (FALSE).} +#' \item{'data', array with named dimensions;} +#' \item{'dims', named vector of the data dimensions;} +#' \item{'coords', list of named vectors with the coordinates corresponding to +#' the dimensions of the data parameter;} #' \item{'attrs', named list with elements: #' \itemize{ #' \item{'Dates', array with named temporal dimensions of class 'POSIXct' -#' from time values in the data.} +#' from time values in the data;} #' \item{'Variable', has the following components: #' \itemize{ #' \item{'varName', character vector of the short variable name. It is #' usually specified in the parameter 'var' from the functions -#' Start and Load.} +#' Start and Load;} #' \item{'metadata', named list of elements with variable metadata. #' They can be from coordinates variables (e.g. longitude) or -#' main variables (e.g. 'var').} +#' main variables (e.g. 'var');} #' } #' } #' \item{'Datasets', character strings indicating the names of the -#' datasets.} +#' datasets;} #' \item{'source_files', a vector of character strings with complete paths -#' to all the found files involved in loading the data.} +#' to all the found files involved in loading the data;} #' \item{'when', a time stamp of the date issued by the Start() or Load() -#' call to obtain the data.} +#' call to obtain the data;} #' \item{'load_parameters', it contains the components used in the #' arguments to load the data from Start() or Load() functions.} #' } @@ -148,6 +145,7 @@ as.s2dv_cube <- function(object, remove_attrs_coords = FALSE, obj_i$coords$lon <- as.vector(obj_i$attrs$lon) } else { obj_i$coords$lon <- obj_i$attrs$lon + dim(obj_i$coords$lon) <- NULL attr(obj_i$coords$lon, 'indices') <- FALSE } obj_i$attrs$Variable$metadata$lon <- obj_i$attrs$lon @@ -159,6 +157,7 @@ as.s2dv_cube <- function(object, remove_attrs_coords = FALSE, obj_i$coords$lat <- as.vector(obj_i$attrs$lat) } else { obj_i$coords$lat <- obj_i$attrs$lat + dim(obj_i$coords$lat) <- NULL attr(obj_i$coords$lat, 'indices') <- FALSE } obj_i$attrs$Variable$metadata$lat <- obj_i$attrs$lat @@ -183,7 +182,7 @@ as.s2dv_cube <- function(object, remove_attrs_coords = FALSE, if (isTRUE(remove_null)) { obj_i$attrs$load_parameters <- .rmNullObs(obj_i$attrs$load_parameters) } - obj_i <- obj_i[c('data','dims','coords','attrs')] + obj_i <- obj_i[c('data', 'dims', 'coords', 'attrs')] class(obj_i) <- 's2dv_cube' if (names(obs_exp)[[i]] == 'exp') { result$exp <- obj_i @@ -231,8 +230,8 @@ as.s2dv_cube <- function(object, remove_attrs_coords = FALSE, result$coords[[i_coord]] <- as.vector(coord_in_fileselector[[i_coord]][[1]]) } else { result$coords[[i_coord]] <- coord_in_fileselector[[i_coord]][[1]] + attr(result$coords[[i_coord]], 'indices') <- FALSE } - if (!remove_attrs_coords) attr(result$coords[[i_coord]], 'indices') <- FALSE } else { result$coords[[i_coord]] <- 1:dims[i_coord] if (!remove_attrs_coords) attr(result$coords[[i_coord]], 'indices') <- TRUE @@ -246,14 +245,15 @@ as.s2dv_cube <- function(object, remove_attrs_coords = FALSE, if (length(coord_in_common) == dims[i_coord]) { if (remove_attrs_coords) { if (inherits(coord_in_common, "POSIXct")) { - result$coords[[i_coord]] <- coord_in_common + result$coords[[i_coord]] <- 1:dims[i_coord] + attr(result$coords[[i_coord]], 'indices') <- TRUE } else { result$coords[[i_coord]] <- as.vector(coord_in_common) } } else { result$coords[[i_coord]] <- coord_in_common + attr(result$coords[[i_coord]], 'indices') <- FALSE } - if (!remove_attrs_coords) attr(result$coords[[i_coord]], 'indices') <- FALSE } else { result$coords[[i_coord]] <- 1:dims[i_coord] if (!remove_attrs_coords) attr(result$coords[[i_coord]], 'indices') <- TRUE @@ -273,8 +273,8 @@ as.s2dv_cube <- function(object, remove_attrs_coords = FALSE, } } else { result$coords[[i_coord]] <- coord_in_dat + attr(result$coords[[i_coord]], 'indices') <- FALSE } - if (!remove_attrs_coords) attr(result$coords[[i_coord]], 'indices') <- FALSE } else { result$coords[[i_coord]] <- 1:dims[i_coord] if (!remove_attrs_coords) attr(result$coords[[i_coord]], 'indices') <- TRUE @@ -287,6 +287,7 @@ as.s2dv_cube <- function(object, remove_attrs_coords = FALSE, result$coords[[i_coord]] <- 1:dims[i_coord] if (!remove_attrs_coords) attr(result$coords[[i_coord]], 'indices') <- TRUE } + dim(result$coords[[i_coord]]) <- NULL } # attrs diff --git a/R/s2dv_cube.R b/R/s2dv_cube.R index 5f9c465b8490dda0c6635ba43cbd2a65b7f7d33c..f4e5be6689bc9f86cc4b55d4e37cf08bbc8b127b 100644 --- a/R/s2dv_cube.R +++ b/R/s2dv_cube.R @@ -12,11 +12,12 @@ #' #'@param data A multidimensional array with named dimensions, typically with #' dimensions: dataset, member, sdate, ftime, lat and lon. -#'@param coords A named list with elements of the coordinates corresponding to -#' the dimensions of the data parameter. The names and length of each element -#' must correspond to the names of the dimensions. If any coordinate is not -#' provided, it is set as an index vector with the values from 1 to the length -#' of the corresponding dimension. +#'@param coords A list of named vectors with the coordinates corresponding to +#' the dimensions of the data parameter. If any coordinate has dimensions, they +#' will be set as NULL. If any coordinate is not provided, it is set as an +#' index vector with the values from 1 to the length of the corresponding +#' dimension. The attribute 'indices' indicates wether the coordinate is an +#' index vector (TRUE) or not (FALSE). #'@param varName A character string indicating the abbreviation of the variable #' name. #'@param metadata A named list where each element is a variable containing the @@ -36,33 +37,30 @@ #'@return The function returns an object of class 's2dv_cube' with the following #' elements in the structure:\cr #'\itemize{ -#' \item{'data', array with named dimensions.} -#' \item{'dims', named vector of the data dimensions.} -#' \item{'coords', named list with elements of the coordinates corresponding to -#' the dimensions of the data parameter. If any coordinate is not provided, it -#' is set as an index vector with the values from 1 to the length of the -#' corresponding dimension. The attribute 'indices' indicates wether the -#' coordinate is an index vector (TRUE) or not (FALSE).} +#' \item{'data', array with named dimensions;} +#' \item{'dims', named vector of the data dimensions;} +#' \item{'coords', list of named vectors with the coordinates corresponding to +#' the dimensions of the data parameter;} #' \item{'attrs', named list with elements: #' \itemize{ #' \item{'Dates', array with named temporal dimensions of class 'POSIXct' from -#' time values in the data.} +#' time values in the data;} #' \item{'Variable', has the following components: #' \itemize{ #' \item{'varName', with the short name of the loaded variable as specified -#' in the parameter 'var'.} -#' \item{''metadata', named list of elements with variable metadata. +#' in the parameter 'var';} +#' \item{'metadata', named list of elements with variable metadata. #' They can be from coordinates variables (e.g. longitude) or -#' main variables (e.g. 'var').} +#' main variables (e.g. 'var');} #' } #' } -#' \item{'Datasets', character strings indicating the names of the dataset.} -#' \item{'source_files', a vector of character strings with complete paths to -#' all the found files involved in loading the data.} -#' \item{'when', a time stamp of the date issued by the Start() or Load() call to -#' obtain the data.} -#' \item{'load_parameters', it contains the components used in the arguments to -#' load the data from Start() or Load() functions.} +#' \item{'Datasets', character strings indicating the names of the dataset;} +#' \item{'source_files', a vector of character strings with complete paths +#' to all the found files involved in loading the data;} +#' \item{'when', a time stamp of the date issued by the Start() or Load() +#' call to obtain the data;} +#' \item{'load_parameters', it contains the components used in the +#' arguments to load the data from Start() or Load() functions.} #' } #' } #'} @@ -144,6 +142,7 @@ s2dv_cube <- function(data, coords = NULL, varName = NULL, metadata = NULL, attr(coords[[i_coord]], 'indices') <- TRUE } } + dim(coords[[i_coord]]) <- NULL } else { coords <- sapply(names(dims), function(x) 1:dims[x]) for (i in 1:length(coords)) { diff --git a/data/lonlat_prec.rda b/data/lonlat_prec.rda index db5f1f06b3f4be4c9336de8d7281d3d43f8cc59e..f8212aac52a213aaa7c08b779de86cf77ecb0078 100644 Binary files a/data/lonlat_prec.rda and b/data/lonlat_prec.rda differ diff --git a/data/lonlat_temp.rda b/data/lonlat_temp.rda index 94db7af93b455d8899346cfd62977e051489bb4e..513be2c0c7b0634ab7cf7ecfd7afaa1231b00efe 100644 Binary files a/data/lonlat_temp.rda and b/data/lonlat_temp.rda differ diff --git a/man/as.s2dv_cube.Rd b/man/as.s2dv_cube.Rd index e80044f5dcd8455e91a1527b8ddbe57934df90e1..30f9abd40e6f2d9bd26143a4cc9d12a588d48d11 100644 --- a/man/as.s2dv_cube.Rd +++ b/man/as.s2dv_cube.Rd @@ -25,33 +25,30 @@ The function returns an 's2dv_cube' object to be easily used with functions with the prefix \code{CST} from CSTools and CSIndicators packages. The object is mainly a list with the following elements:\cr \itemize{ - \item{'data', array with named dimensions.} - \item{'dims', named vector of the data dimensions.} - \item{'coords', named list with elements of the coordinates corresponding to - the dimensions of the data parameter. If any coordinate is not provided, it - is set as an index vector with the values from 1 to the length of the - corresponding dimension. The attribute 'indices' indicates wether the - coordinate is an index vector (TRUE) or not (FALSE).} + \item{'data', array with named dimensions;} + \item{'dims', named vector of the data dimensions;} + \item{'coords', list of named vectors with the coordinates corresponding to + the dimensions of the data parameter;} \item{'attrs', named list with elements: \itemize{ \item{'Dates', array with named temporal dimensions of class 'POSIXct' - from time values in the data.} + from time values in the data;} \item{'Variable', has the following components: \itemize{ \item{'varName', character vector of the short variable name. It is usually specified in the parameter 'var' from the functions - Start and Load.} + Start and Load;} \item{'metadata', named list of elements with variable metadata. They can be from coordinates variables (e.g. longitude) or - main variables (e.g. 'var').} + main variables (e.g. 'var');} } } \item{'Datasets', character strings indicating the names of the - datasets.} + datasets;} \item{'source_files', a vector of character strings with complete paths - to all the found files involved in loading the data.} + to all the found files involved in loading the data;} \item{'when', a time stamp of the date issued by the Start() or Load() - call to obtain the data.} + call to obtain the data;} \item{'load_parameters', it contains the components used in the arguments to load the data from Start() or Load() functions.} } diff --git a/man/s2dv_cube.Rd b/man/s2dv_cube.Rd index ff302ccd93252143b387eb102991c3d1edb29caa..e17a460781b027e02e4fcf5b401a8c0ebbd7ddd6 100644 --- a/man/s2dv_cube.Rd +++ b/man/s2dv_cube.Rd @@ -20,11 +20,12 @@ s2dv_cube( \item{data}{A multidimensional array with named dimensions, typically with dimensions: dataset, member, sdate, ftime, lat and lon.} -\item{coords}{A named list with elements of the coordinates corresponding to -the dimensions of the data parameter. The names and length of each element -must correspond to the names of the dimensions. If any coordinate is not -provided, it is set as an index vector with the values from 1 to the length -of the corresponding dimension.} +\item{coords}{A list of named vectors with the coordinates corresponding to +the dimensions of the data parameter. If any coordinate has dimensions, they +will be set as NULL. If any coordinate is not provided, it is set as an +index vector with the values from 1 to the length of the corresponding +dimension. The attribute 'indices' indicates wether the coordinate is an +index vector (TRUE) or not (FALSE).} \item{varName}{A character string indicating the abbreviation of the variable name.} @@ -52,33 +53,30 @@ stored in the end of 'attrs' element. Multiple elements are accepted.} The function returns an object of class 's2dv_cube' with the following elements in the structure:\cr \itemize{ - \item{'data', array with named dimensions.} - \item{'dims', named vector of the data dimensions.} - \item{'coords', named list with elements of the coordinates corresponding to - the dimensions of the data parameter. If any coordinate is not provided, it - is set as an index vector with the values from 1 to the length of the - corresponding dimension. The attribute 'indices' indicates wether the - coordinate is an index vector (TRUE) or not (FALSE).} + \item{'data', array with named dimensions;} + \item{'dims', named vector of the data dimensions;} + \item{'coords', list of named vectors with the coordinates corresponding to + the dimensions of the data parameter;} \item{'attrs', named list with elements: \itemize{ \item{'Dates', array with named temporal dimensions of class 'POSIXct' from - time values in the data.} + time values in the data;} \item{'Variable', has the following components: \itemize{ \item{'varName', with the short name of the loaded variable as specified - in the parameter 'var'.} - \item{''metadata', named list of elements with variable metadata. + in the parameter 'var';} + \item{'metadata', named list of elements with variable metadata. They can be from coordinates variables (e.g. longitude) or - main variables (e.g. 'var').} + main variables (e.g. 'var');} } } - \item{'Datasets', character strings indicating the names of the dataset.} - \item{'source_files', a vector of character strings with complete paths to - all the found files involved in loading the data.} - \item{'when', a time stamp of the date issued by the Start() or Load() call to - obtain the data.} - \item{'load_parameters', it contains the components used in the arguments to - load the data from Start() or Load() functions.} + \item{'Datasets', character strings indicating the names of the dataset;} + \item{'source_files', a vector of character strings with complete paths + to all the found files involved in loading the data;} + \item{'when', a time stamp of the date issued by the Start() or Load() + call to obtain the data;} + \item{'load_parameters', it contains the components used in the + arguments to load the data from Start() or Load() functions.} } } } diff --git a/tests/testthat/test-CST_Subset.R b/tests/testthat/test-CST_Subset.R index cb567279f715e40de2d3b5116c2a04961fbc94c1..9123000b3aad32497879d55d9a748213d2b8955f 100644 --- a/tests/testthat/test-CST_Subset.R +++ b/tests/testthat/test-CST_Subset.R @@ -241,7 +241,7 @@ test_that("3. Output checks with Start", { ) expect_equal( dim(res11$coords$time), - c(sdate = 1, time = 2) + NULL ) expect_equal( dim(res11$attrs$source_files), diff --git a/tests/testthat/test-as.s2dv_cube.R b/tests/testthat/test-as.s2dv_cube.R index 5d6303d583b53f61435a57d57917cc8eccbbf92a..4872c9c372f6eff71a628ac138bcb5eddd4c5920 100644 --- a/tests/testthat/test-as.s2dv_cube.R +++ b/tests/testthat/test-as.s2dv_cube.R @@ -53,6 +53,18 @@ test_that("2. Tests from Load()", { attributes(res1$coords$ftime), list(indices = TRUE) ) + expect_equal( + dim(res1$coords$lat), + NULL + ) + expect_equal( + dim(res1$coords$lon), + NULL + ) + expect_equal( + length(res1$coords$lat), + 6 + ) # Dates expect_equal( dim(res1$attrs$Dates), @@ -94,6 +106,14 @@ test_that("3. Tests from Load()", { unlist(res2$coords)[1:4], c(dataset = "ERA5", member = "1", sdate = "20180301", ftime = "1") ) + expect_equal( + dim(res2$coords$ftime), + NULL + ) + expect_equal( + length(res2$coords$lat), + 3 + ) # Dates expect_equal( dim(res2$attrs$Dates), @@ -176,6 +196,18 @@ test_that("5. Tests from Start()", { names(res4$coords), c("dat", "var", "sdate", "ensemble", "time", "latitude", "longitude") ) + expect_equal( + dim(res4$coords$dat), + NULL + ) + expect_equal( + dim(res4$coords$latitude), + NULL + ) + expect_equal( + length(res4$coords$latitude), + 10 + ) # Dates expect_equal( dim(res4$attrs$Dates), @@ -235,6 +267,10 @@ test_that("6. Tests from Start()", { names(res5$coords), c('dat', 'var', 'latitude', 'longitude', 'member', 'time', 'syear', 'sweek', 'sday') ) + expect_equal( + dim(res5$coords$longitude), + NULL + ) # Dates expect_equal( dim(res5$attrs$Dates), diff --git a/tests/testthat/test-s2dv_cube.R b/tests/testthat/test-s2dv_cube.R index 5737486ce4637670d829241c1a19a2e6114d414e..a88f6eec5cb5dafbd052812d3dd644f7614e659f 100644 --- a/tests/testthat/test-s2dv_cube.R +++ b/tests/testthat/test-s2dv_cube.R @@ -127,9 +127,32 @@ test_that("2. Output checks", { attributes(object$coords$var), list(indices = TRUE) ) - }) ############################################## - +test_that("3. Output checks", { + dim(coords1$sdate) <- c(sdate = 5) + dim(coords1$var) <- c(var = 1) + suppressWarnings( + object <- s2dv_cube(data = dat1, coords = list(sdate = coords1[[1]]), varName = 'tas', + metadata = list(tas = list(level = '2m')), + Dates = dates1) + ) + expect_equal( + names(object$coords), + c('sdate', 'var') + ) + expect_equal( + dim(object$coords$sdate), + NULL + ) + expect_equal( + dim(object$coords$var), + NULL + ) + expect_equal( + length(object$coords$sdate), + 5 + ) +})