From f6b2f3cadbee689f84cfa6e5eba0e0953a1aae1a Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 13 Jul 2020 22:48:14 +0200 Subject: [PATCH 01/30] Bugfix for first file missing case. The error happened when retrieving metadata. --- R/Start.R | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/R/Start.R b/R/Start.R index b23e0eb..54236e1 100644 --- a/R/Start.R +++ b/R/Start.R @@ -3104,6 +3104,9 @@ Start <- function(..., # dim = indices/selectors, .message(progress_message, appendLF = FALSE) } } + +# NOTE: In .LoadDataFile(), metadata is saved in metadata_folder/1 or /2 etc. Before here, +# the path name is created in work_pieces but the path hasn't been built yet. if (num_procs == 1) { found_files <- lapply(work_pieces, .LoadDataFile, shared_matrix_pointer = shared_matrix_pointer, @@ -3264,7 +3267,13 @@ Start <- function(..., # dim = indices/selectors, # Load metadata and remove the metadata folder if (!is.null(metadata_dims)) { loaded_metadata_files <- list.files(metadata_folder) - loaded_metadata <- lapply(paste0(metadata_folder, '/', loaded_metadata_files), readRDS) + + if (!identical(loaded_metadata_files, character(0))) { # old code + loaded_metadata <- lapply(paste0(metadata_folder, '/', loaded_metadata_files), readRDS) + } else { + loaded_metadata <- NULL + } + unlink(metadata_folder, recursive = TRUE) return_metadata <- vector('list', length = prod(dim(array_of_metadata_flags)[metadata_dims])) return_metadata[as.numeric(loaded_metadata_files)] <- loaded_metadata @@ -3332,7 +3341,18 @@ Start <- function(..., # dim = indices/selectors, if (!silent) { .message("Successfully retrieved data.") } - var_backup <- attr(data_array, 'Variables')[[1]] + + if (all(sapply(attr(data_array, 'Variables'), is.null))) { + var_backup <- NULL + .warning(paste0("Metadata cannot be retrieved. The reason may be the ", + "non-existence of the first file. Use parameter 'metadata_dims'", + " to assign to file dimensions along which to return metadata, ", + "or check the existence of the first file.")) + } else { + zxc <- unlist(lapply(attr(data_array, 'Variables'), is.null)) + var_backup <- attr(data_array, 'Variables')[!zxc][[1]] + } + attr(data_array, 'Variables') <- NULL attributes(data_array) <- c(attributes(data_array), list(Variables = c(list(common = c(picked_common_vars, var_backup)), -- GitLab From 9e449d9ca60ffc892e1540fc6da490edc58111a3 Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 14 Jul 2020 09:59:17 +0200 Subject: [PATCH 02/30] Add unit test for first file missing case --- .../testthat/test-Start-first_file_missing.R | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 tests/testthat/test-Start-first_file_missing.R diff --git a/tests/testthat/test-Start-first_file_missing.R b/tests/testthat/test-Start-first_file_missing.R new file mode 100644 index 0000000..5f7a5a6 --- /dev/null +++ b/tests/testthat/test-Start-first_file_missing.R @@ -0,0 +1,123 @@ +context("Start() retrieves files that the first file is missing") + +# When some of the files are missing, Start() still can retrieve the data and +# put NA in those missing positions. However, when the first file is missing, +# Start() returned error before because of failing to find metadata. The bug is +# fixed now, so even the first file does not exist, Start() will still retrieve +# the data. The parameter 'metadata_dims' can also be used in this case. + +file <- "/esarchive/exp/ncep/cfs-v2/weekly_mean/s2s/$var$_f24h/$var$_$file_date$.nc" +var <- 'tas' +sdates1 <- c('20130611') #exists +sdates2 <- c('20130618') #does not exist +sdates3 <- c("20130611", "20130618") #1st exists, 2nd missing +sdates4 <- c("20130618", "20130611") #1st missing, 2nd exists + + +test_that("1. first file missing, no assign parameter 'metadata_dims'", { + +data <- Start(dat = file, + var = var, + file_date = sdates4, + time = indices(1:4), + latitude = values(list(20, 30)), + latitude_reorder = Sort(decreasing = TRUE), + longitude = values(list(-20, -10)), + longitude_reorder = CircularSort(-180, 180), + ensemble = indices(1), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude')), + return_vars = list(latitude = 'dat', + longitude = 'dat', + time = 'file_date'), + #metadata_dims = c('file_date'), + retrieve = T) + + expect_equal( + dim(data), + c(dat = 1, var = 1, file_date = 2, time = 4, latitude = 11, longitude = 11, ensemble = 1) + ) + expect_equal( + data[1, 1, , 1, 1, 1, 1], + c(NA, 293.9133), + tolerance = 0.0001 + ) + expect_equal( + length(data[is.na(data)]), + 484 + ) + expect_equal( + names(attr(data, 'Variables')$common), + 'time' + ) + +}) + +test_that("2. Use parameter 'metadata_dims'", { + +data <- Start(dat = file, + var = var, + file_date = sdates4, + time = indices(1:4), + latitude = values(list(20, 30)), + latitude_reorder = Sort(decreasing = TRUE), + longitude = values(list(-20, -10)), + longitude_reorder = CircularSort(-180, 180), + ensemble = indices(1), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude')), + return_vars = list(latitude = 'dat', + longitude = 'dat', + time = 'file_date'), + metadata_dims = c('file_date'), + retrieve = T) + + expect_equal( + dim(data), + c(dat = 1, var = 1, file_date = 2, time = 4, latitude = 11, longitude = 11, ensemble = 1) + ) + expect_equal( + data[1, 1, , 1, 1, 1, 1], + c(NA, 293.9133), + tolerance = 0.0001 + ) + expect_equal( + length(data[is.na(data)]), + 484 + ) + expect_equal( + names(attr(data, 'Variables')$common), + c('time', 'tas') + ) +}) + +test_that("3. Use parameter 'metadata_dims', all common attributes", { + +data <- Start(dat = file, + var = var, + file_date = sdates4, + time = indices(1:4), + latitude = values(list(20, 30)), + latitude_reorder = Sort(decreasing = TRUE), + longitude = values(list(-20, -10)), + longitude_reorder = CircularSort(-180, 180), + ensemble = indices(1), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude')), + return_vars = list(latitude = NULL, + longitude = NULL, + time = 'file_date'), + metadata_dims = c('file_date'), + retrieve = T) + + expect_equal( + names(attr(data, 'Variables')$common), + c('latitude', 'longitude', 'time', 'tas') + ) + expect_equal( + as.vector(attr(data, 'NotFoundFiles')), + c("/esarchive/exp/ncep/cfs-v2/weekly_mean/s2s/tas_f24h/tas_20130618.nc", NA) + ) + +}) + -- GitLab From a67438fb088dca54de29e3e9c61e490a4623b656 Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 14 Jul 2020 10:05:22 +0200 Subject: [PATCH 03/30] Add the fix in NEWS.md --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index baf436e..8db9ba4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,9 @@ +# startR v1.0.4 (Release date: 2020-) +- Bugfix for non-existent first file. Start() could not retireve the data if the first file +is missing because the metadata is not found. The fix allows Start() to retrieve data without +metadata. To get the metadata from the following files, assign the parameter 'metadata_dims' +in Start(). + # startR v1.0.3 (Release date: 2020-06-19) - Bugfix for requiring the repetitive values from a single file when using 'merge_across_dims' and 'split_multiselected_dims'. The value positions were not -- GitLab From d62bed35db732ba2be004a633e31d8ce9aa587ce Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 14 Jul 2020 15:22:40 +0200 Subject: [PATCH 04/30] Add FAQ for first-file-missing case --- inst/doc/faq.md | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/inst/doc/faq.md b/inst/doc/faq.md index 4ad94a0..5572da5 100644 --- a/inst/doc/faq.md +++ b/inst/doc/faq.md @@ -22,6 +22,7 @@ This document intends to be the first reference for any doubts that you may have 16. [Use parameter 'return_vars' in Start()](#16-use-parameter-return_vars-in-start) 17. [Use parameter 'split_multiselected_dims' in Start()](#17-use-parameter-split_multiselected_dims-in-start) 18. [Use glob expression '*' to define the file path](#18-use-glob-expression-to-define-the-file-path) + 19. [Get metadata when the first file does not exist](#19-get-metadata-when-the-first-file-does-not-exist) 2. **Something goes wrong...** @@ -692,6 +693,84 @@ This is different from the common definition of glob expression that tries to ex There is a parameter 'path_glob_permissive' in Start(). If set it to TRUE, the '*' in the filename itself will remain (i.e., as the common definition), while the ones in the path to the filename will still be replaced by the pattern in the first found file. +### 19. Get metadata when the first file does not exist +Start() can retrieve the data even if some of them do not exist. The returned array will be filled with NA at the positions of missing files. +However, Start() retrieves the metadata from the first file of each data set by default. When the first file does not exist, the metadata cannot be found then the returned array will be lack of metadata of the variable. +In this case, Start() shows a warning: `Metadata cannot be retrieved. The reason may be the non-existence of the first file. Use parameter 'metadata_dims' to assign to file dimensions along which to return metadata, or check the existence of the first file.` + +To get the metadata, we can ensure the first file exists, or use the parameter 'metadata_dims' in Start(). + +(1) Ensure the first file exists +If the first file exists, you have no problem with metadata. You can check manually, or use the script like below: +```r + first.exists <- FALSE + n <- 1 + while(!first.exists) { + if(!file.exists(dir[n])) { + n <- n + 1 + } else { + first.exists <- TRUE + if (n > 1) { + init.year <- init.year + (n - 1) + all.years <- paste(strtoi(init.year):strtoi(end.year), sep = "") + warning(paste0("NEW INIT YEAR: ", init.year)) + } + } + } +``` + +(2) Use parameter 'metadata_dims' +This parameter expects to receive a vector of character strings with the names of the file dimensions which to return metadata for. +Start() by default returns the auxiliary data read for only the first file of each data set in the pattern dimension. +However, it can be configured to return the metadata for all the files along any set of file dimensions. The following example uses `metadata_dims = 'file_date'`, so even the first file is missing, Start() can find the metatdata from the second files. + +```r +file <- "/esarchive/exp/ncep/cfs-v2/weekly_mean/s2s/$var$_f24h/$var$_$file_date$.nc" +var <- 'tas' +sdates <- c("20130618", "20130611") #1st missing, 2nd exists + +dat1 <- Start(dat = file, + var = var, + file_date = sdates4, + time = indices(1:4), + latitude = values(list(20, 30)), + latitude_reorder = Sort(decreasing = TRUE), + longitude = values(list(-20, -10)), + longitude_reorder = CircularSort(-180, 180), + ensemble = indices(1), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude')), + return_vars = list(latitude = 'dat', + longitude = 'dat', + time = 'file_date'), + retrieve = T) + +# Check the attributes. There is no 'tas' metadata +names(attr(data, 'Variables')$common) +[1] "time" + +dat1 <- Start(dat = file, + var = var, + file_date = sdates4, + time = indices(1:4), + latitude = values(list(20, 30)), + latitude_reorder = Sort(decreasing = TRUE), + longitude = values(list(-20, -10)), + longitude_reorder = CircularSort(-180, 180), + ensemble = indices(1), + metadata_dims = 'file_date', + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude')), + return_vars = list(latitude = 'dat', + longitude = 'dat', + time = 'file_date'), + retrieve = T) + +# Check the attributes. 'tas' metadata exists +names(attr(data, 'Variables')$common) +[1] "time" "tas" +``` + # Something goes wrong... -- GitLab From 5c5b1b511692ce3d47572fef022a40be2c7c657f Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 10 Aug 2020 12:12:46 +0200 Subject: [PATCH 05/30] Bugfix for Start() parameter 'path_glob_permissive' and write the explanation in FAQ and Start() header. --- R/Start.R | 31 ++++++++++++++++++++++++++++--- inst/doc/faq.md | 10 ++++++++-- man/Start.Rd | 15 ++++++++++++--- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/R/Start.R b/R/Start.R index 62d7e8c..927a67e 100644 --- a/R/Start.R +++ b/R/Start.R @@ -644,8 +644,8 @@ #'When specifying a path pattern for a dataset, it might contain shell glob #'experissions. For each dataset, the first file matching the path pattern is #'found, and the found file is used to work out fixed values for the glob -#'expressions that will be used for all the files of the dataset. However in -#'some cases the values of the shell glob expressions may not be constant for +#'expressions that will be used for all the files of the dataset. However, in +#'some cases, the values of the shell glob expressions may not be constant for #'all files in a dataset, and they need to be worked out for each file #'involved.\cr\cr #'For example, a path pattern could be as follows: \cr @@ -667,7 +667,16 @@ #' pattern with the original glob expressions in the 1st and 2nd levels (in the #' example, both asterisks would be preserved, thus would allow Start() #' to recognize files such as \cr -#' \code{'/path/to/dataset/precipitation_zzz/19901101_yyy_foo.nc'}). +#' \code{'/path/to/dataset/precipitation_zzz/19901101_yyy_foo.nc'}).\cr\cr +#'Note that each glob expression can only represent one possibility (Start() +#'chooses the first). Because /code{*} is not the tag, which means it cannot +#'be a dimension of the output array. Therefore, only one possibility can be +#'adopted. For example, if \cr +#'\code{'/path/to/dataset/precipitation_*/19901101_*_foo.nc'}\cr +#'has two matches:\cr +#'\code{'/path/to/dataset/precipitation_xxx/19901101_yyy_foo.nc'} and\cr +#'\code{'/path/to/dataset/precipitation_zzz/19901101_yyy_foo.nc'},\cr +#'only the first found file will be used. #'@param retrieve A logical value indicating whether to retrieve the data #' defined in the Start() call or to explore only its dimension lengths #' and names, and the values for the file and inner dimensions. The default @@ -1671,6 +1680,8 @@ Start <- function(..., # dim = indices/selectors, replace_values[[u_file_dim]] <- '*' depended_dim <- NULL depended_dim_values <- NA + +#NOTE: Here 'selectors' is always 1. Is it supposed to be like this? selectors <- dat_selectors[[u_file_dim]][[1]] if (u_file_dim %in% names(depending_file_dims)) { depended_dim <- depending_file_dims[[u_file_dim]] @@ -1772,6 +1783,20 @@ Start <- function(..., # dim = indices/selectors, sub_array_of_not_found_files[j] <- TRUE } else { file_path <- .ReplaceVariablesInString(dat[[i]][['path']], replace_values) + +#NOTE: After replacing tags, there is still * if path_glob_permissive is not FALSE. + if (grepl('\\*', file_path)) { + found_files <- Sys.glob(file_path) + file_path <- found_files[1] # choose only the first file. +#NOTE: Above line chooses only the first found file. Because * is not tags, which means +# it is not a dimension. So it cannot store more than one item. If use * to define +# the path, that * should only represent one possibility. + if (length(found_files) > 1) { + .warning("Using glob expression * to define the path, but more ", + "than one match is found. Choose the first match only.") + } + } + if (!(length(grep("^http", file_path)) > 0)) { if (grepl(file_path, '*', fixed = TRUE)) { file_path_full <- Sys.glob(file_path)[1] diff --git a/inst/doc/faq.md b/inst/doc/faq.md index 4ad94a0..a4971c7 100644 --- a/inst/doc/faq.md +++ b/inst/doc/faq.md @@ -685,12 +685,18 @@ The glob expression, or wildcard, '*', can also be used in the path definition, Please note that **'*' can only be used to replace the common part of all the files**. For example, if all the required files have the folder 'EC-Earth-Consortium/' in their path, then this part can be substituted with '*/'. It can save some effort to define the long and uncritical path, and also make the script cleaner. -However, if the part replaced by '*' is not same among all the files, Start() will use the first pattern it finds in the first file to substitute '*'. +However, if the part replaced by '*' is not same among all the files, Start() will use **the first pattern it finds in the first file to substitute '*'**. As a result, the rest files may not be found due to the wrong path pattern. For example, if the first file is under a folder named 'v20190302/' and the second file is under another one named 'v20190308/', and you define the path pattern as 'v*/', then Start() will use 'v20190302/' for both file paths. This is different from the common definition of glob expression that tries to expand to match all the existing patterns, so please be careful when using it. -There is a parameter 'path_glob_permissive' in Start(). If set it to TRUE, the '*' in the filename itself will remain (i.e., as the common definition), while the ones in the path to the filename will still be replaced by the pattern in the first found file. +There is a parameter 'path_glob_permissive' in Start() can be used to perserve the +functionality of '*'. It can be FALSE/TRUE or an integer indicating how many folder layers +in the path pattern, beginning from the end, the shell glob expressions to be preserved. + +The default value is FALSE (equal to 0), which means no '*' is preserved. +If set it to TRUE (equal to 1), the '*' in the filename will remain and represent different possiblities of the file path pattern. See more details in Start() parameter +'path_glob_permissive'. # Something goes wrong... diff --git a/man/Start.Rd b/man/Start.Rd index d69562c..9411940 100644 --- a/man/Start.Rd +++ b/man/Start.Rd @@ -333,8 +333,8 @@ is FALSE.} When specifying a path pattern for a dataset, it might contain shell glob experissions. For each dataset, the first file matching the path pattern is found, and the found file is used to work out fixed values for the glob -expressions that will be used for all the files of the dataset. However in -some cases the values of the shell glob expressions may not be constant for +expressions that will be used for all the files of the dataset. However, in +some cases, the values of the shell glob expressions may not be constant for all files in a dataset, and they need to be worked out for each file involved.\cr\cr For example, a path pattern could be as follows: \cr @@ -356,7 +356,16 @@ For example, a path pattern could be as follows: \cr pattern with the original glob expressions in the 1st and 2nd levels (in the example, both asterisks would be preserved, thus would allow Start() to recognize files such as \cr - \code{'/path/to/dataset/precipitation_zzz/19901101_yyy_foo.nc'}).} + \code{'/path/to/dataset/precipitation_zzz/19901101_yyy_foo.nc'}).\cr\cr +Note that each glob expression can only represent one possibility (Start() +chooses the first). Because /code{*} is not the tag, which means it cannot +be a dimension of the output array. Therefore, only one possibility can be +adopted. For example, if \cr +\code{'/path/to/dataset/precipitation_*/19901101_*_foo.nc'}\cr +has two matches:\cr +\code{'/path/to/dataset/precipitation_xxx/19901101_yyy_foo.nc'} and\cr +\code{'/path/to/dataset/precipitation_zzz/19901101_yyy_foo.nc'},\cr +only the first found file will be used.} \item{retrieve}{A logical value indicating whether to retrieve the data defined in the Start() call or to explore only its dimension lengths -- GitLab From 97b9c5a4c0945edecc8777d89c5deb87c94a97fb Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 10 Aug 2020 12:18:40 +0200 Subject: [PATCH 06/30] Format fix for how-to-18 --- inst/doc/faq.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/inst/doc/faq.md b/inst/doc/faq.md index a4971c7..0cc5256 100644 --- a/inst/doc/faq.md +++ b/inst/doc/faq.md @@ -685,7 +685,7 @@ The glob expression, or wildcard, '*', can also be used in the path definition, Please note that **'*' can only be used to replace the common part of all the files**. For example, if all the required files have the folder 'EC-Earth-Consortium/' in their path, then this part can be substituted with '*/'. It can save some effort to define the long and uncritical path, and also make the script cleaner. -However, if the part replaced by '*' is not same among all the files, Start() will use **the first pattern it finds in the first file to substitute '*'**. +However, if the part replaced by '\*' is not same among all the files, Start() will use **the first pattern it finds in the first file to substitute '*'**. As a result, the rest files may not be found due to the wrong path pattern. For example, if the first file is under a folder named 'v20190302/' and the second file is under another one named 'v20190308/', and you define the path pattern as 'v*/', then Start() will use 'v20190302/' for both file paths. This is different from the common definition of glob expression that tries to expand to match all the existing patterns, so please be careful when using it. @@ -693,10 +693,9 @@ This is different from the common definition of glob expression that tries to ex There is a parameter 'path_glob_permissive' in Start() can be used to perserve the functionality of '*'. It can be FALSE/TRUE or an integer indicating how many folder layers in the path pattern, beginning from the end, the shell glob expressions to be preserved. - -The default value is FALSE (equal to 0), which means no '*' is preserved. -If set it to TRUE (equal to 1), the '*' in the filename will remain and represent different possiblities of the file path pattern. See more details in Start() parameter -'path_glob_permissive'. +The default value is FALSE (equal to 0), which means no '\*' is preserved. +If set it to TRUE (equal to 1), the '\*' in the filename will remain and represent different possiblities of the file path pattern. See more details in Start() parameter +'path\_glob\_permissive'. # Something goes wrong... -- GitLab From 5ea9d45126d610f6b8565b170221dbcfbfbb9607 Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 11 Aug 2020 21:31:24 +0200 Subject: [PATCH 07/30] A typo leads to wrong reordered metadata when return_vars is NULL. --- R/Start.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/Start.R b/R/Start.R index 62d7e8c..6bf0b72 100644 --- a/R/Start.R +++ b/R/Start.R @@ -1978,7 +1978,7 @@ Start <- function(..., # dim = indices/selectors, picked_common_vars[[var_to_read]] <- new_array pick_ordered <- FALSE if (var_to_read %in% unlist(var_params)) { - if (associated_dim_name %in% names(dim_reorder_param) && !aiat) { + if (associated_dim_name %in% names(dim_reorder_params) && !aiat) { picked_common_vars_ordered[[var_to_read]] <- new_array pick_ordered <- TRUE } -- GitLab From 9eb02f4c0ee9fef8960f371f98cfe9c1cf2e09de Mon Sep 17 00:00:00 2001 From: aho Date: Wed, 12 Aug 2020 16:31:45 +0200 Subject: [PATCH 08/30] Bugfix for transformation lon/lat metadatawhen return_vars is NULL --- R/Start.R | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/R/Start.R b/R/Start.R index 6bf0b72..70b5320 100644 --- a/R/Start.R +++ b/R/Start.R @@ -3416,7 +3416,13 @@ Start <- function(..., # dim = indices/selectors, if (i == length(dat)) { for (common_var_to_crop in names(common_vars_to_crop)) { if (inner_dim %in% names(dim(common_vars_to_crop[[common_var_to_crop]]))) { + + if (type_of_var_to_crop == 'transformed' & !aiat) { + common_vars_to_crop[[common_var_to_crop]] <- Subset(transformed_subset_var, inner_dim, crop_indices) + } else { #old code common_vars_to_crop[[common_var_to_crop]] <- Subset(common_vars_to_crop[[common_var_to_crop]], inner_dim, crop_indices) + } + } } } -- GitLab From 3c7e816d80657fee54008dbbf7991d41edac7734 Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 13 Aug 2020 03:22:54 +0200 Subject: [PATCH 09/30] Add unit tests for checking metadata when using reorder or transform, under the condition that returns_var = NULL/'dat'. --- tests/testthat/test-Start-reorder-metadata.R | 276 ++++++++++++++++++ .../testthat/test-Start-transform-metadata.R | 272 +++++++++++++++++ 2 files changed, 548 insertions(+) create mode 100644 tests/testthat/test-Start-reorder-metadata.R create mode 100644 tests/testthat/test-Start-transform-metadata.R diff --git a/tests/testthat/test-Start-reorder-metadata.R b/tests/testthat/test-Start-reorder-metadata.R new file mode 100644 index 0000000..b522a36 --- /dev/null +++ b/tests/testthat/test-Start-reorder-metadata.R @@ -0,0 +1,276 @@ +context("Start() reorder metadata check") +# Ensure returns_vars = NULL or 'dat' have the same metadata + +test_that("1. Sort() and CircularSort(0, 360)", { + +# Original lon is [-180, 180] +path_exp <- '/esarchive/recon/ecmwf/era5/original_files/reorder/daily_mean/$var$/$var$_$sdate$.nc' +lons.min <- -10 +lons.max <- 10 +lats.min <- 10 +lats.max <- 20 + +# return_vars is NULL +res_null <- Start(dat = list(list(path = path_exp)), + var = 'tas', + sdate = '199212', + time = indices(4), + latitude = values(list(lats.min, lats.max)), + latitude_reorder = Sort(), + longitude_reorder = CircularSort(0, 360), + longitude = values(list(lons.min, lons.max)), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude')), + return_vars = list(latitude = NULL, + longitude = NULL, + time = 'sdate'), + retrieve = F) + + expect_equal( + length(attributes(attr(res_null, 'Variables')$common$longitude)), + 2 + ) + expect_equal( + is.list(attr(attr(res_null, 'Variables')$common$latitude, 'variables')), + TRUE + ) + expect_equal( + length(attr(attr(res_null, 'Variables')$common$latitude, 'variables')$latitude), + 7 + ) + expect_equal( + length(attr(attr(res_null, 'Variables')$common$longitude, 'variables')$longitude), + 7 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$latitude)[1], + 10.25761, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$latitude)[35], + 19.81264, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_null, 'Variables')$common$latitude)), + 35 + ) + + expect_equal( + as.vector(attr(res_null, 'Variables')$common$longitude)[1], + 0.00000, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$longitude)[71], + 359.71875, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_null, 'Variables')$common$longitude)), + 71 + ) + +# return_vars is dat +res_dat <- Start(dat = list(list(path = path_exp)), + var = 'tas', + sdate = '199212', + time = indices(4), + latitude = values(list(lats.min, lats.max)), + latitude_reorder = Sort(), + longitude_reorder = CircularSort(0, 360), + longitude = values(list(lons.min, lons.max)), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude')), + return_vars = list(latitude = 'dat', + longitude = 'dat', + time = 'sdate'), + retrieve = F) + + expect_equal( + length(attributes(attr(res_dat, 'Variables')$dat1$longitude)), + 2 + ) + expect_equal( + is.list(attr(attr(res_dat, 'Variables')$dat1$latitude, 'variables')), + TRUE + ) + expect_equal( + length(attr(attr(res_dat, 'Variables')$dat1$latitude, 'variables')$latitude), + 7 + ) + expect_equal( + length(attr(attr(res_dat, 'Variables')$dat1$longitude, 'variables')$longitude), + 7 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$latitude)[1], + 10.25761, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$latitude)[35], + 19.81264, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_dat, 'Variables')$dat1$latitude)), + 35 + ) + + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$longitude)[1], + 0.00000, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$longitude)[71], + 359.71875, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_dat, 'Variables')$dat1$longitude)), + 71 + ) + +}) + +test_that("2. Sort(decreasing = TRUE) and CircularSort(-180, 180)", { + +# Original lon is [0, 360] +path_exp <- '/esarchive/exp/ecmwf/system5_m1/daily_mean/$var$_f6h/$var$_$sdate$.nc' +lons.min <- 190 +lons.max <- 200 +lats.min <- 10 +lats.max <- 20 + +# return_vars is NULL +res_null <- Start(dat = list(list(path = path_exp)), + var = 'psl', + member = 'all', + sdate = '19821201', + time = indices(4), + latitude = values(list(lats.min, lats.max)), + latitude_reorder = Sort(decreasing = T), + longitude_reorder = CircularSort(-180, 180), + longitude = values(list(lons.min, lons.max)), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude'), + member = c('ensemble', 'realization')), + return_vars = list(latitude = NULL, + longitude = NULL, + time = 'sdate'), + retrieve = F) + + expect_equal( + length(attributes(attr(res_null, 'Variables')$common$longitude)), + 2 + ) + expect_equal( + is.list(attr(attr(res_null, 'Variables')$common$latitude, 'variables')), + TRUE + ) + expect_equal( + length(attr(attr(res_null, 'Variables')$common$latitude, 'variables')$latitude), + 7 + ) + expect_equal( + length(attr(attr(res_null, 'Variables')$common$longitude, 'variables')$longitude), + 7 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$latitude)[1], + 19.81264, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$latitude)[35], + 10.25761, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_null, 'Variables')$common$latitude)), + 35 + ) + + expect_equal( + as.vector(attr(res_null, 'Variables')$common$longitude)[1], + -170.0000, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$longitude)[37], + -160.0000, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_null, 'Variables')$common$longitude)), + 37 + ) + +# return_vars is 'dat' +res_dat <- Start(dat = list(list(path = path_exp)), + var = 'psl', + member = 'all', + sdate = '19821201', + time = indices(4), + latitude = values(list(lats.min, lats.max)), + latitude_reorder = Sort(decreasing = T), + longitude_reorder = CircularSort(-180, 180), + longitude = values(list(lons.min, lons.max)), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude'), + member = c('ensemble', 'realization')), + return_vars = list(latitude = 'dat', + longitude = 'dat', + time = 'sdate'), + retrieve = F) + + expect_equal( + length(attributes(attr(res_dat, 'Variables')$dat1$longitude)), + 2 + ) + expect_equal( + is.list(attr(attr(res_dat, 'Variables')$dat1$latitude, 'variables')), + TRUE + ) + expect_equal( + length(attr(attr(res_dat, 'Variables')$dat1$latitude, 'variables')$latitude), + 7 + ) + expect_equal( + length(attr(attr(res_dat, 'Variables')$dat1$longitude, 'variables')$longitude), + 7 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$latitude)[1], + 19.81264, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$latitude)[35], + 10.25761, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_dat, 'Variables')$dat1$latitude)), + 35 + ) + + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$longitude)[1], + -170.0000, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$longitude)[37], + -160.0000, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_dat, 'Variables')$dat1$longitude)), + 37 + ) + +}) diff --git a/tests/testthat/test-Start-transform-metadata.R b/tests/testthat/test-Start-transform-metadata.R new file mode 100644 index 0000000..f19a02a --- /dev/null +++ b/tests/testthat/test-Start-transform-metadata.R @@ -0,0 +1,272 @@ +context("Start() transform metadata check") +# Ensure returns_vars = NULL or 'dat' have the same metadata + +test_that("1. Sort() and CircularSort(0, 360)", { + +# Original lon is [-180, 180] +path_exp <- '/esarchive/recon/ecmwf/era5/original_files/reorder/daily_mean/$var$/$var$_$sdate$.nc' +lons.min <- -10 +lons.max <- 10 +lats.min <- 10 +lats.max <- 20 + +# return_vars is NULL +res_null <- Start(dat = list(list(path = path_exp)), + var = 'tas', + sdate = '199212', + time = indices(4), + latitude = values(list(lats.min, lats.max)), + latitude_reorder = Sort(), + longitude_reorder = CircularSort(0, 360), + longitude = values(list(lons.min, lons.max)), + transform = CDORemapper, + transform_extra_cells = 2, + transform_params = list(grid = 'r360x181', + method = 'conservative', + crop = c(lons.min, lons.max, + lats.min, lats.max)), + transform_vars = c('latitude', 'longitude'), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude')), + return_vars = list(latitude = NULL, + longitude = NULL, + time = 'sdate'), + retrieve = F) + + expect_equal( + length(attributes(attr(res_null, 'Variables')$common$latitude)), + 1 + ) + expect_equal( + length(attributes(attr(res_null, 'Variables')$common$longitude)), + 1 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$latitude)[1], + 10, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$latitude)[11], + 20, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_null, 'Variables')$common$latitude)), + 11 + ) + + expect_equal( + as.vector(attr(res_null, 'Variables')$common$longitude)[1], + 0, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$longitude)[21], + 359, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_null, 'Variables')$common$longitude)), + 21 + ) + +# return_vars is dat +res_dat <- Start(dat = list(list(path = path_exp)), + var = 'tas', + sdate = '199212', + time = indices(4), + latitude = values(list(lats.min, lats.max)), + latitude_reorder = Sort(), + longitude_reorder = CircularSort(0, 360), + longitude = values(list(lons.min, lons.max)), + transform = CDORemapper, + transform_extra_cells = 2, + transform_params = list(grid = 'r360x181', + method = 'conservative', + crop = c(lons.min, lons.max, + lats.min, lats.max)), + transform_vars = c('latitude', 'longitude'), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude')), + return_vars = list(latitude = 'dat', + longitude = 'dat', + time = 'sdate'), + retrieve = F) + + expect_equal( + length(attributes(attr(res_dat, 'Variables')$dat1$latitude)), + 1 + ) + expect_equal( + length(attributes(attr(res_dat, 'Variables')$dat1$longitude)), + 1 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$latitude)[1], + 10, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$latitude)[11], + 20, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_dat, 'Variables')$dat1$latitude)), + 11 + ) + + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$longitude)[1], + 0, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$longitude)[21], + 359, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_dat, 'Variables')$dat1$longitude)), + 21 + ) + +}) + +test_that("2. Sort(decreasing = TRUE) and CircularSort(-180, 180)", { + +# Original lon is [0, 360] +path_exp <- '/esarchive/exp/ecmwf/system5_m1/daily_mean/$var$_f6h/$var$_$sdate$.nc' +lons.min <- 190 +lons.max <- 200 +lats.min <- 10 +lats.max <- 20 + +# return_vars is NULL +res_null <- Start(dat = list(list(path = path_exp)), + var = 'psl', + member = 'all', + sdate = '19821201', + time = indices(4), + latitude = values(list(lats.min, lats.max)), + latitude_reorder = Sort(decreasing = T), + longitude_reorder = CircularSort(-180, 180), + longitude = values(list(lons.min, lons.max)), + transform = CDORemapper, + transform_extra_cells = 2, + transform_params = list(grid = 'r360x181', + method = 'conservative', + crop = c(lons.min, lons.max, + lats.min, lats.max)), + transform_vars = c('latitude', 'longitude'), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude'), + member = c('ensemble', 'realization')), + return_vars = list(latitude = NULL, + longitude = NULL, + time = 'sdate'), + retrieve = F) + + expect_equal( + length(attributes(attr(res_null, 'Variables')$common$latitude)), + 1 + ) + expect_equal( + length(attributes(attr(res_null, 'Variables')$common$longitude)), + 1 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$latitude)[1], + 20, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$latitude)[11], + 10, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_null, 'Variables')$common$latitude)), + 11 + ) + + expect_equal( + as.vector(attr(res_null, 'Variables')$common$longitude)[1], + -170, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_null, 'Variables')$common$longitude)[11], + -160, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_null, 'Variables')$common$longitude)), + 11 + ) + +# return_vars is 'dat' +res_dat <- Start(dat = list(list(path = path_exp)), + var = 'psl', + member = 'all', + sdate = '19821201', + time = indices(4), + latitude = values(list(lats.min, lats.max)), + latitude_reorder = Sort(decreasing = T), + longitude_reorder = CircularSort(-180, 180), + longitude = values(list(lons.min, lons.max)), + transform = CDORemapper, + transform_extra_cells = 2, + transform_params = list(grid = 'r360x181', + method = 'conservative', + crop = c(lons.min, lons.max, + lats.min, lats.max)), + transform_vars = c('latitude', 'longitude'), + synonims = list(latitude = c('lat', 'latitude'), + longitude = c('lon', 'longitude'), + member = c('ensemble', 'realization')), + return_vars = list(latitude = 'dat', + longitude = 'dat', + time = 'sdate'), + retrieve = F) + + expect_equal( + length(attributes(attr(res_dat, 'Variables')$dat1$latitude)), + 1 + ) + expect_equal( + length(attributes(attr(res_dat, 'Variables')$dat1$longitude)), + 1 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$latitude)[1], + 20, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$latitude)[11], + 10, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_dat, 'Variables')$dat1$latitude)), + 11 + ) + + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$longitude)[1], + -170, + tolerance = 0.0001 + ) + expect_equal( + as.vector(attr(res_dat, 'Variables')$dat1$longitude)[11], + -160, + tolerance = 0.0001 + ) + expect_equal( + length(as.vector(attr(res_dat, 'Variables')$dat1$longitude)), + 11 + ) + +}) -- GitLab From 2bc4a848b6b0219e008020d5b2ebbfb18f1520cf Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 13 Aug 2020 03:31:21 +0200 Subject: [PATCH 10/30] Update NEWS.md for bugfix of metadata --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index e38cd18..4ebe2d6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# startR v2.0.1 (Release date: 2020-08-) +- Bugfix for metadata in the condition that reorder or transform is applied and 'return_vars' is NULL. +- Bugfix for the missing first file case. It showed an error before when the first file is not found but now it works. + # startR v2.0.0 (Release date: 2020-08-06) - Adopt Roxygen2 documentation format - Remove Subset() to avoid duplicated function. Use ClimProjDiags::Subset instead. -- GitLab From b618bd26e247bae026b2d73f146a4f40a4c007c1 Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 13 Aug 2020 17:08:03 +0200 Subject: [PATCH 11/30] Bugfix for metadata_dims when more than 1 dat. Unit test is created. --- R/Start.R | 15 ++++ tests/testthat/test-Start-metadata_dims.R | 100 ++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 tests/testthat/test-Start-metadata_dims.R diff --git a/R/Start.R b/R/Start.R index 62d7e8c..7a9e27a 100644 --- a/R/Start.R +++ b/R/Start.R @@ -4109,7 +4109,22 @@ Start <- function(..., # dim = indices/selectors, if (!silent) { .message("Successfully retrieved data.") } + +# NOTE: The original var_backup saves only the first of the list (i.e., 1st dat). +# If there is more than one dat, it should be put under each dat rather than $common. +# Question: If there is only one dat, should it be under $common or $dat1? +# It is under $common now. + if (length(attr(data_array, 'Variables')) > 1) { # more than 1 dat. Put under each dat + var_backup <- attr(data_array, 'Variables') + for (kk in 1:length(var_backup)) { + picked_vars[[kk]][[names(var_backup[[kk]])]] <- var_backup[[kk]][[1]] + } + var_backup <- NULL + + } else { #old code var_backup <- attr(data_array, 'Variables')[[1]] + } + attr(data_array, 'Variables') <- NULL attributes(data_array) <- c(attributes(data_array), list(Variables = c(list(common = c(picked_common_vars, var_backup)), diff --git a/tests/testthat/test-Start-metadata_dims.R b/tests/testthat/test-Start-metadata_dims.R new file mode 100644 index 0000000..a771f98 --- /dev/null +++ b/tests/testthat/test-Start-metadata_dims.R @@ -0,0 +1,100 @@ +context("Start() metadata_dims check") + +test_that("1. One data set", { + repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + data <- Start(dat = list(list(name = 'system5_m1', path = repos)), + var = 'tas', + sdate = '20170101', + ensemble = indices(1), + time = indices(1), + lat = indices(1:10), + lon = indices(1:10), + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(time = 'sdate', + longitude = 'dat', + latitude = 'dat'), + metadata_dims = 'dat', # it can be omitted since it is automatically specified as 'dat' + retrieve = T + ) + + expect_equal( + length(attr(data, 'Variables')), + 2 + ) + expect_equal( + names(attr(data, 'Variables')), + c("common", "system5_m1") + ) + expect_equal( + names(attr(data, 'Variables')$common), + c('time', 'tas') + ) + expect_equal( + names(attr(data, 'Variables')$system5_m1), + c("longitude", "latitude") + ) + expect_equal( + length(attr(data, 'Variables')$common$tas), + 12 + ) + +} + + +test_that("2. Two data sets", { + repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + repos2 <- "/esarchive/exp/ecmwf/system4_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + + data <- Start(dat = list(list(name = 'system4_m1', path = repos2), + list(name = 'system5_m1', path = repos)), + var = 'tas', + sdate = '20170101', + ensemble = indices(1), + time = indices(1), + lat = indices(1:10), + lon = indices(1:10), + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(time = 'sdate', + longitude = 'dat', + latitude = 'dat'), + metadata_dims = 'dat', # it can be omitted since it is automatically specified as 'dat' + retrieve = T + ) + + expect_equal( + length(attr(data, 'Variables')), + 3 + ) + expect_equal( + names(attr(data, 'Variables')), + c("common", "system4_m1", "system5_m1") + ) + expect_equal( + names(attr(data, 'Variables')$common), + 'time' + ) + expect_equal( + names(attr(data, 'Variables')$system4_m1), + c("longitude", "latitude", "tas") + ) + expect_equal( + names(attr(data, 'Variables')$system5_m1), + c("longitude", "latitude", "tas") + ) + expect_equal( + length(attr(data, 'Variables')$system5_m1$tas), + 12 + ) + expect_equal( + length(attr(data, 'Variables')$system4_m1$tas), + 11 + ) + +} + +test_that("3. Specify metadata_dims with another file dimension", { + + +} -- GitLab From 995ec112c0f9f29fb67c3188bbc1801f699d718a Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 17 Aug 2020 17:51:25 +0200 Subject: [PATCH 12/30] Create unit test and use case for path_glob_permissive --- NEWS.md | 1 + inst/doc/faq.md | 2 +- inst/doc/usecase.md | 4 + inst/doc/usecase/ex1_9_path_glob_permissive.R | 114 ++++++++++++++++++ .../test-Start-path_glob_permissive.R | 90 ++++++++++++++ 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 inst/doc/usecase/ex1_9_path_glob_permissive.R create mode 100644 tests/testthat/test-Start-path_glob_permissive.R diff --git a/NEWS.md b/NEWS.md index 4ebe2d6..3577fbb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # startR v2.0.1 (Release date: 2020-08-) - Bugfix for metadata in the condition that reorder or transform is applied and 'return_vars' is NULL. - Bugfix for the missing first file case. It showed an error before when the first file is not found but now it works. +- Bugfix for the parameter 'path_glob_permissive' of Start(). # startR v2.0.0 (Release date: 2020-08-06) - Adopt Roxygen2 documentation format diff --git a/inst/doc/faq.md b/inst/doc/faq.md index 0cc5256..d7f10bf 100644 --- a/inst/doc/faq.md +++ b/inst/doc/faq.md @@ -695,7 +695,7 @@ functionality of '*'. It can be FALSE/TRUE or an integer indicating how many fol in the path pattern, beginning from the end, the shell glob expressions to be preserved. The default value is FALSE (equal to 0), which means no '\*' is preserved. If set it to TRUE (equal to 1), the '\*' in the filename will remain and represent different possiblities of the file path pattern. See more details in Start() parameter -'path\_glob\_permissive'. +'path\_glob\_permissive' and the use case [ex1_9](inst/doc/usecase/ex1_9_path_glob_permissive.R). # Something goes wrong... diff --git a/inst/doc/usecase.md b/inst/doc/usecase.md index 65dbd2d..e2ffdc0 100644 --- a/inst/doc/usecase.md +++ b/inst/doc/usecase.md @@ -38,6 +38,10 @@ The problem may occur when the dimension number of the splitted selector is more 8. [Loading tas and tos from Decadal Predictions performed with the EC-Earth model](inst/doc/usecase/ex1_8_tasandtos.R) Some climate indices needs to be computed loading 'tas' (air temperature at 2m) over land and 'tos' (ocean surface temperature) over sea. Using **startR**, you can load these data in a unique **Start** call or with multiple calls separately for each variable. + 9. [Use glob expression * to define the path](inst/doc/usecase/ex1_9_path_glob_permissive.R) + This script shows you how to use glob expression '*' and the parameter 'path_glob_permissive' of Start(). +You can also find information in [FAQ How-to-18](inst/doc/faq.md#18-use-glob-expression-to-define-the-file-path). + 2. **Execute computation (use `Compute()`)** 1. [Function working on time dimension](inst/doc/usecase/ex2_1_timedim.R) diff --git a/inst/doc/usecase/ex1_9_path_glob_permissive.R b/inst/doc/usecase/ex1_9_path_glob_permissive.R new file mode 100644 index 0000000..f52f7e0 --- /dev/null +++ b/inst/doc/usecase/ex1_9_path_glob_permissive.R @@ -0,0 +1,114 @@ +#--------------------------------------------------------------------- +# This script shows you how to use glob expression '*' and the parameter 'path_glob_permissive' of Start(). +# The regular way to define the path for Start() is using the tags, i.e., '$$'. +# However, we may want to use '*' to define the path under some conditions. +# Start() allows this usage but with some limitation. You can find more details in Start() documentation, the parameter 'path_glob_permissive'. +#--------------------------------------------------------------------- +library(startR) + +#----------------------------------------------------------------- +# Case 1: Use * to substitute a string which is common among files +#----------------------------------------------------------------- +## This is a lazy way to define the path. When there is a common string among all +## the files, you can use * instead of the string. +## However, it is not recommended to use because you may not notice when the file +## path is changed and Start() reads the unwanted files. The more clear-defined the +## path, the safer it is. + +## We want to read the two files, 1960 and 1961, from the repository. The full path +## definition is below. +repo_original <- paste0('/esarchive/exp/ecearth/a1st/diags/CMIP/EC-Earth-Consortium/', + 'EC-Earth3/historical/r7i1p1f1/Omon/$var$/gn/v20190302/', + '$var$_Omon_EC-Earth3_historical_r7i1p1f1_gn_$year$.nc') +years <- paste0(c(1960:1961), '01-', c(1960:1961), '12') + +## We know that there are some layers of the path are unique and identical between +## the two files. We can change those layers to *. +## Please note that if the string is different between files, * must be used with the +## parameter 'path_glob_permissive' (See Case 2 below). +repos <- paste0('/esarchive/exp/ecearth/a1st/diags/CMIP/*/', + '*/*/r7i1p1f1/Omon/$var$/*/v20190302/', + '$var$_Omon_*_*_r7i1p1f1_*_$year$.nc') + +data <- Start(dat = repos, + var = 'tosmean', + year = years, + time = indices(1), + region = indices(1), + return_vars = list(time = NULL, region = NULL), + retrieve = T) + + +#------------------------------------------------------------- +# Case 2: Use * to substitute a name which differs from files +#------------------------------------------------------------- +## We want to read two experiments together, while their member and version name are +## different. The data structure is like this: +## -- expid -- -- member -- -- version -- +## a1st r7i1p1f1 v20190302 +## a1sx r10i1p1f1 v20190308 +## +## We cannot simply substitue 'member' and 'version' with *, because Start() will only detect +## the first file path and use the string in the first file to represent the rest files. +## Therefore, the rest files cannot be found. That is, Start() will regard a1st and a1sx +## both have member 'r7i1p1f1' and version 'v20190302'. +## Fortunately, the expid only has one member and one version each. We can use * combined +## with the parameter 'path_glob_permissive' to make Start() work. + +## The * from the end in order represents: 1. member 2. version 3. member +repos <- paste0('/esarchive/exp/ecearth/$expid$/diags/CMIP/EC-Earth-Consortium/', + 'EC-Earth3/historical/*/Omon/$var$/gn/v*/', + '$var$_Omon_EC-Earth3_historical_*_gn_$year$.nc') +years <- paste0(c(1960:1961), '01-', c(1960:1961), '12') + +## The parameter 'path_glob_permissive' can be assigned with TRUE/FALSE or an integer. +## TRUE equals to 1, and FALSE equals to 0. The number means that how many layers from +## the end to preserve * for all files. That is, Start() won't replace * with the string +## found in the first file. Start() will use * to look for the pattern for each file. +## So, since the three * in above path are all different between a1st and a1sx, we need +## to preserve all of them. The furthest layer from the end is 6, so 'path_glob_permissive' +## should be 6. +data <- Start(dat = repos, + var = 'tosmean', + expid = c('a1st', 'a1sx'), + year = years, + time = indices(1), + region = indices(1), + path_glob_permissive = 6, + return_vars = list(time = NULL, region = NULL), + retrieve = T) + +## What if certain expid has more than one 'member' or 'version'? For example, +## -- expid -- -- member -- -- version -- +## a1st r7i1p1f1 v20190302 +## v20200302 +## a1sx r10i1p1f1 v20190308 + +## In this case, Start() will only catch 'v20190302' for a1st. This is the main difference +## between * and tag. Tag is the dimension of the output array, so it can save as many +## value as you want. On the other hand, * is not a dimension, so it can only represent one +## possibility for one file path. + + +## You may think of the usage of '_depends', which also tells Start() that one tag (i.e., +## dimension) is dependent on another one. However, '_depends' can only be used when the +## dependency is between two. In this case, we can define the dependency between 'expid' +## and 'member', and use * for 'version'. +repos <- paste0('/esarchive/exp/ecearth/$expid$/diags/CMIP/EC-Earth-Consortium/', + 'EC-Earth3/historical/$member$/Omon/$var$/gn/v*/', + '$var$_Omon_EC-Earth3_historical_*_gn_$year$.nc') + +## You can see that the layers contain * are the last two. Therefore, 'path_glob_permissive' +## is 2 here. +data <- Start(dat = repos, + var = 'tosmean', + expid = c('a1st', 'a1sx'), + year = years, + member = indices(1), + member_depends = 'expid', + time = indices(1), + region = indices(1), + path_glob_permissive = 2, + return_vars = list(time = NULL, region = NULL), + retrieve = T) + diff --git a/tests/testthat/test-Start-path_glob_permissive.R b/tests/testthat/test-Start-path_glob_permissive.R new file mode 100644 index 0000000..9e14c02 --- /dev/null +++ b/tests/testthat/test-Start-path_glob_permissive.R @@ -0,0 +1,90 @@ +context("Start() path_glob_permissive check") + +test_that("1. expid/member/version", { + +years <- paste0(c(1960:1961), '01-', c(1960:1961), '12') + +# from the end, each *: 1. member 2. version 3. member +repos <- paste0('/esarchive/exp/ecearth/$expid$/diags/CMIP/EC-Earth-Consortium/', + 'EC-Earth3/historical/*/Omon/$var$/gn/v*/', + '$var$_Omon_EC-Earth3_historical_*_gn_$year$.nc') + +data <- Start(dat = repos, + var = 'tosmean', + expid = c('a1st', 'a1sx'), + year = years, + time = indices(1), + region = indices(1), + path_glob_permissive = 6, #TRUE, + return_vars = list(time = NULL, region = NULL), + retrieve = T) + + + expect_equal( + dim(data), + c(dat = 1, var = 1, expid = 2, year = 2, time = 1, region = 1) + ) + expect_equal( + dim(attr(data, 'Files')), + c(dat = 1, var = 1, expid = 2, year = 2) + ) + expect_equal( + attr(data, 'Files'), + array(c("/esarchive/exp/ecearth/a1st/diags/CMIP/EC-Earth-Consortium/EC-Earth3/historical/r7i1p1f1/Omon/tosmean/gn/v20190302/tosmean_Omon_EC-Earth3_historical_r7i1p1f1_gn_196001-196012.nc", + "/esarchive/exp/ecearth/a1sx/diags/CMIP/EC-Earth-Consortium/EC-Earth3/historical/r10i1p1f1/Omon/tosmean/gn/v20190308/tosmean_Omon_EC-Earth3_historical_r10i1p1f1_gn_196001-196012.nc", + "/esarchive/exp/ecearth/a1st/diags/CMIP/EC-Earth-Consortium/EC-Earth3/historical/r7i1p1f1/Omon/tosmean/gn/v20190302/tosmean_Omon_EC-Earth3_historical_r7i1p1f1_gn_196101-196112.nc", + "/esarchive/exp/ecearth/a1sx/diags/CMIP/EC-Earth-Consortium/EC-Earth3/historical/r10i1p1f1/Omon/tosmean/gn/v20190308/tosmean_Omon_EC-Earth3_historical_r10i1p1f1_gn_196101-196112.nc"), + dim = c(dat = 1, var = 1, expid = 2, year = 2)) + ) + expect_equal( + data[1, 1, , , 1, 1], + matrix(c(18.60422, 17.13862, 18.52348, 17.21780), 2, 2), + tolerance = 0.0001 + ) + + +# from the end, each *: 1. member 2. version +repos <- paste0('/esarchive/exp/ecearth/$expid$/diags/CMIP/EC-Earth-Consortium/', + 'EC-Earth3/historical/$member$/Omon/$var$/gn/v*/', + '$var$_Omon_EC-Earth3_historical_*_gn_$year$.nc') + +data <- Start(dat = repos, + var = 'tosmean', + expid = c('a1st', 'a1sx'), + year = years, + member = indices(1), + member_depends = 'expid', + time = indices(1), + region = indices(1), + path_glob_permissive = 2, #TRUE, + return_vars = list(time = NULL, region = NULL), + retrieve = T) + + + expect_equal( + dim(data), + c(dat = 1, var = 1, expid = 2, year = 2, member = 1, time = 1, region = 1) + ) + expect_equal( + dim(attr(data, 'Files')), + c(dat = 1, var = 1, expid = 2, year = 2, member = 1) + ) + expect_equal( + attr(data, 'Files'), + array(c("/esarchive/exp/ecearth/a1st/diags/CMIP/EC-Earth-Consortium/EC-Earth3/historical/r7i1p1f1/Omon/tosmean/gn/v20190302/tosmean_Omon_EC-Earth3_historical_r7i1p1f1_gn_196001-196012.nc", + "/esarchive/exp/ecearth/a1sx/diags/CMIP/EC-Earth-Consortium/EC-Earth3/historical/r10i1p1f1/Omon/tosmean/gn/v20190308/tosmean_Omon_EC-Earth3_historical_r10i1p1f1_gn_196001-196012.nc", + "/esarchive/exp/ecearth/a1st/diags/CMIP/EC-Earth-Consortium/EC-Earth3/historical/r7i1p1f1/Omon/tosmean/gn/v20190302/tosmean_Omon_EC-Earth3_historical_r7i1p1f1_gn_196101-196112.nc", + "/esarchive/exp/ecearth/a1sx/diags/CMIP/EC-Earth-Consortium/EC-Earth3/historical/r10i1p1f1/Omon/tosmean/gn/v20190308/tosmean_Omon_EC-Earth3_historical_r10i1p1f1_gn_196101-196112.nc"), + dim = c(dat = 1, var = 1, expid = 2, year = 2, member = 1)) + ) + expect_equal( + data[1, 1, , , 1, 1, 1], + matrix(c(18.60422, 17.13862, 18.52348, 17.21780), 2, 2), + tolerance = 0.0001 + ) + expect_equal( + attr(data, 'FileSelectors')$dat1$member, + list(a1st = 'r7i1p1f1', a1sx = 'r10i1p1f1') + ) + +}) -- GitLab From 6096b98acd4c9ddfa7db6a74495407dbb98a0a12 Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 17 Aug 2020 17:53:41 +0200 Subject: [PATCH 13/30] Format fix --- inst/doc/usecase.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/doc/usecase.md b/inst/doc/usecase.md index e2ffdc0..a25f2a9 100644 --- a/inst/doc/usecase.md +++ b/inst/doc/usecase.md @@ -38,7 +38,7 @@ The problem may occur when the dimension number of the splitted selector is more 8. [Loading tas and tos from Decadal Predictions performed with the EC-Earth model](inst/doc/usecase/ex1_8_tasandtos.R) Some climate indices needs to be computed loading 'tas' (air temperature at 2m) over land and 'tos' (ocean surface temperature) over sea. Using **startR**, you can load these data in a unique **Start** call or with multiple calls separately for each variable. - 9. [Use glob expression * to define the path](inst/doc/usecase/ex1_9_path_glob_permissive.R) + 9. [Use glob expression * to define the path](inst/doc/usecase/ex1_9_path_glob_permissive.R) This script shows you how to use glob expression '*' and the parameter 'path_glob_permissive' of Start(). You can also find information in [FAQ How-to-18](inst/doc/faq.md#18-use-glob-expression-to-define-the-file-path). -- GitLab From 009a83327c20e4bf00a527e0e0b1bb2e63b8ee2b Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 18 Aug 2020 19:32:51 +0200 Subject: [PATCH 14/30] Consider the case that metadata_dims = 'var' and var is more than one --- R/Start.R | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/R/Start.R b/R/Start.R index 899d6ba..e9540a9 100644 --- a/R/Start.R +++ b/R/Start.R @@ -4116,14 +4116,33 @@ Start <- function(..., # dim = indices/selectors, .message("Successfully retrieved data.") } -# NOTE: The original var_backup saves only the first of the list (i.e., 1st dat). -# If there is more than one dat, it should be put under each dat rather than $common. -# Question: If there is only one dat, should it be under $common or $dat1? -# It is under $common now. - if (length(attr(data_array, 'Variables')) > 1) { # more than 1 dat. Put under each dat +#NOTE: The metadata of variables can be saved in one of the three different structures. +# (1) matadata_dims = 'xxx', which the length of 'xxx' is 1: the metadata is saved +# under $common. +# If the length of 'xxx' > 1, +# (2) metadata_dims = 'dat' (i.e., pattern_dims): the metadata is saved under +# each dat, and only the first variable can be saved. +# (3) metadata_dims != 'dat' (e.g., 'var'): the metadata is saved only under dat1, +# and all the variables can be saved. +#TODO: Enable metadata_dims to have more than one item. For example, there are 2 dats +# and 2 vars. The metadata of the vars should be saved under each dat. That is, +# each data has two vars. + + if (length(attr(data_array, 'Variables')) > 1) { # metadata_dims length is more than 1. (2) or (3) var_backup <- attr(data_array, 'Variables') - for (kk in 1:length(var_backup)) { - picked_vars[[kk]][[names(var_backup[[kk]])]] <- var_backup[[kk]][[1]] + + if (metadata_dims == pattern_dims) { # 'dat'. (2) + for (kk in 1:length(var_backup)) { + if (!is.null(var_backup[[kk]])) { # if file does not exist + picked_vars[[kk]][[names(var_backup[[kk]])]] <- var_backup[[kk]][[1]] + } + } + } else { # metadata_dims = 'var' or other file dim. (3) + for (kk in 1:length(var_backup)) { + if (!is.null(var_backup[[kk]])) { # if file does not exist + picked_vars[[1]][[metadata_dims]][[names(var_backup[[kk]])]] <- var_backup[[kk]][[1]] + } + } } var_backup <- NULL -- GitLab From 32dca61cc330ecbb3d58d2400638bf48d30d5fda Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 20 Aug 2020 11:17:46 +0200 Subject: [PATCH 15/30] Bugfix for metadata_dims when multiple dats and vars are required --- NEWS.md | 3 ++ R/Start.R | 97 ++++++++++++++++++++++++++++++++++------------------ man/Start.Rd | 4 +-- 3 files changed, 69 insertions(+), 35 deletions(-) diff --git a/NEWS.md b/NEWS.md index 4ebe2d6..2a122b2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # startR v2.0.1 (Release date: 2020-08-) - Bugfix for metadata in the condition that reorder or transform is applied and 'return_vars' is NULL. +- Bugfix for the parameter 'metadata_dims'. It did not work correctly for the cases other than +'1 data set, 1 variable'. For 1 data set case, all the variables should be listed under $common in +the attributes; for more than 1 data set case, the variables should be listed under each $dat. - Bugfix for the missing first file case. It showed an error before when the first file is not found but now it works. # startR v2.0.0 (Release date: 2020-08-06) diff --git a/R/Start.R b/R/Start.R index e9540a9..990d8e7 100644 --- a/R/Start.R +++ b/R/Start.R @@ -611,8 +611,8 @@ #' auxiliary data read for only the first file of each source (or data set) in #' the pattern dimension (see \code{\dots} for info on what the pattern #' dimension is). However it can be configured to return the metadata for all -#' the files along any set of file dimensions. The parameter 'metadata_dims' -#' allows to configure this level of granularity of the returned metadata. +#' the files along any set of file dimensions. The default value is NULL, and +#' it will be assigned automatically as parameter 'pattern_dims'. #'@param selector_checker A function used internaly by Start() to #' translate a set of selectors (values for a dimension associated to a #' coordinate variable) into a set of numeric indices. It takes by default @@ -1080,7 +1080,7 @@ Start <- function(..., # dim = indices/selectors, # Check metadata_dims if (!is.null(metadata_dims)) { - if (is.na(metadata_dims)) { + if (any(is.na(metadata_dims))) { metadata_dims <- NULL } else if (!is.character(metadata_dims) || (length(metadata_dims) < 1)) { stop("Parameter 'metadata' dims must be a vector of at least one character string.") @@ -1089,6 +1089,21 @@ Start <- function(..., # dim = indices/selectors, metadata_dims <- pattern_dims } + # Check if pattern_dims is the first item in metadata_dims + if ((pattern_dims %in% metadata_dims) & metadata_dims[1] != pattern_dims) { + metadata_dims <- c(metadata_dims[-1], metadata_dims[1]) + } + # Check if metadata_dims has more than 2 elements + if ((metadata_dims[1] == pattern_dims & length(metadata_dims) > 2)) { + .warning(paste0("Parameter 'metadata_dims' has too many elements which serve repetitive ", + "function. Keep '", metadata_dims[1], "' and '", metadata_dims[2], "' only.")) + metadata_dims <- metadata_dims[1:2] + } else if (!(pattern_dims %in% metadata_dims) & length(metadata_dims) > 1) { + .warning(paste0("Parameter 'metadata_dims' has too many elements which serve repetitive ", + "function. Keep '", metadata_dims[1], "' only.")) + metadata_dims <- metadata_dims[1] + } + # Once the pattern dimension with dataset specifications is found, # the variable 'dat' is mounted with the information of each # dataset. @@ -4049,9 +4064,35 @@ Start <- function(..., # dim = indices/selectors, loaded_metadata_files <- list.files(metadata_folder) loaded_metadata <- lapply(paste0(metadata_folder, '/', loaded_metadata_files), readRDS) unlink(metadata_folder, recursive = TRUE) - return_metadata <- vector('list', length = prod(dim(array_of_metadata_flags)[metadata_dims])) - return_metadata[as.numeric(loaded_metadata_files)] <- loaded_metadata - dim(return_metadata) <- dim(array_of_metadata_flags[metadata_dims]) + +#NOTE: Here, metadata can be saved in one of two ways: one for $common and the other for $dat +# for $common, it is a list of metadata length. For $dat, it is a list of dat length, +# and each sublist has the metadata for each dat. + dim_of_metadata <- dim(array_of_metadata_flags)[metadata_dims] + if (!any(names(dim_of_metadata) == pattern_dims) | + (any(names(dim_of_metadata) == pattern_dims) & + dim_of_metadata[pattern_dims] == 1)) { # put under $common; old code + return_metadata <- vector('list', + length = prod(dim(array_of_metadata_flags)[metadata_dims])) + return_metadata[as.numeric(loaded_metadata_files)] <- loaded_metadata + dim(return_metadata) <- dim(array_of_metadata_flags[metadata_dims]) + + } else { # put under $dat. metadata_dims has 'dat' and dat length > 1 + return_metadata <- vector('list', + length = dim_of_metadata[pattern_dims]) + names(return_metadata) <- dat_names + for (kk in 1:length(return_metadata)) { + return_metadata[[kk]] <- vector('list', length = prod(dim_of_metadata[-1])) # 1 is dat + } + loaded_metadata_count <- 1 + for (kk in 1:length(return_metadata)) { + for (jj in 1:length(return_metadata[[kk]])) { + return_metadata[[kk]][jj] <- loaded_metadata[[loaded_metadata_count]] + names(return_metadata[[kk]])[jj] <- names(loaded_metadata[[loaded_metadata_count]]) + loaded_metadata_count <- loaded_metadata_count + 1 + } + } + } attr(data_array, 'Variables') <- return_metadata # TODO: Try to infer data type from loaded_metadata # as.integer(data_array) @@ -4116,38 +4157,28 @@ Start <- function(..., # dim = indices/selectors, .message("Successfully retrieved data.") } -#NOTE: The metadata of variables can be saved in one of the three different structures. -# (1) matadata_dims = 'xxx', which the length of 'xxx' is 1: the metadata is saved -# under $common. -# If the length of 'xxx' > 1, -# (2) metadata_dims = 'dat' (i.e., pattern_dims): the metadata is saved under -# each dat, and only the first variable can be saved. -# (3) metadata_dims != 'dat' (e.g., 'var'): the metadata is saved only under dat1, -# and all the variables can be saved. -#TODO: Enable metadata_dims to have more than one item. For example, there are 2 dats -# and 2 vars. The metadata of the vars should be saved under each dat. That is, -# each data has two vars. - - if (length(attr(data_array, 'Variables')) > 1) { # metadata_dims length is more than 1. (2) or (3) +#NOTE: The metadata of variables can be saved in one of the two different structures. +# (1) metadata_dims != 'dat', or (metadata_dims == 'dat' & length(dat) == 1): +# put under $common +# (2) (metadata_dims == 'dat' & length(dat) > 1): +# put under $dat1, $dat2, .... Put it in picked_vars list +#TODO: The current (2) uses the inefficient method. Should define the list structure first +# then fill the list, rather than expand it in the for loop. + if (any(metadata_dims == pattern_dims) & length(dat) > 1) { # (2) var_backup <- attr(data_array, 'Variables') - - if (metadata_dims == pattern_dims) { # 'dat'. (2) - for (kk in 1:length(var_backup)) { - if (!is.null(var_backup[[kk]])) { # if file does not exist - picked_vars[[kk]][[names(var_backup[[kk]])]] <- var_backup[[kk]][[1]] - } - } - } else { # metadata_dims = 'var' or other file dim. (3) - for (kk in 1:length(var_backup)) { - if (!is.null(var_backup[[kk]])) { # if file does not exist - picked_vars[[1]][[metadata_dims]][[names(var_backup[[kk]])]] <- var_backup[[kk]][[1]] - } + for (kk in 1:length(var_backup)) { + sublist_names <- lapply(var_backup, names)[[kk]] + for (jj in 1:length(sublist_names)) { + picked_vars[[kk]][[sublist_names[jj]]] <- var_backup[[kk]][[jj]] } } var_backup <- NULL - } else { #old code - var_backup <- attr(data_array, 'Variables')[[1]] + } else { #(1) + var_backup <- attr(data_array, 'Variables') + var_backup_name <- lapply(var_backup, names) + var_backup <- lapply(var_backup, '[[', 1) + names(var_backup) <- unlist(var_backup_name) } attr(data_array, 'Variables') <- NULL diff --git a/man/Start.Rd b/man/Start.Rd index d69562c..f80f3bb 100644 --- a/man/Start.Rd +++ b/man/Start.Rd @@ -295,8 +295,8 @@ the data reader can optionally return auxiliary data via the attribute auxiliary data read for only the first file of each source (or data set) in the pattern dimension (see \code{\dots} for info on what the pattern dimension is). However it can be configured to return the metadata for all -the files along any set of file dimensions. The parameter 'metadata_dims' - allows to configure this level of granularity of the returned metadata.} +the files along any set of file dimensions. The default value is NULL, and +it will be assigned automatically as parameter 'pattern_dims'.} \item{selector_checker}{A function used internaly by Start() to translate a set of selectors (values for a dimension associated to a -- GitLab From fd11d85486b50034fa463f7cb9fcc1e232c66822 Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 20 Aug 2020 14:51:39 +0200 Subject: [PATCH 16/30] Add unit test, faq, and use case for metadata_dims --- inst/doc/faq.md | 28 +++ inst/doc/usecase.md | 4 + inst/doc/usecase/ex1_10_metadata_dims.R | 180 +++++++++++++++++++ tests/testthat/test-Start-metadata_dims.R | 207 +++++++++++++++++++++- 4 files changed, 413 insertions(+), 6 deletions(-) create mode 100644 inst/doc/usecase/ex1_10_metadata_dims.R diff --git a/inst/doc/faq.md b/inst/doc/faq.md index 4ad94a0..c5be8aa 100644 --- a/inst/doc/faq.md +++ b/inst/doc/faq.md @@ -22,6 +22,7 @@ This document intends to be the first reference for any doubts that you may have 16. [Use parameter 'return_vars' in Start()](#16-use-parameter-return_vars-in-start) 17. [Use parameter 'split_multiselected_dims' in Start()](#17-use-parameter-split_multiselected_dims-in-start) 18. [Use glob expression '*' to define the file path](#18-use-glob-expression-to-define-the-file-path) + 19. [Use 'metadata_dims' to retrieve variable metadata](#19-use-metadata_dims-to-retrieve-variable-metadata) 2. **Something goes wrong...** @@ -692,6 +693,33 @@ This is different from the common definition of glob expression that tries to ex There is a parameter 'path_glob_permissive' in Start(). If set it to TRUE, the '*' in the filename itself will remain (i.e., as the common definition), while the ones in the path to the filename will still be replaced by the pattern in the first found file. +### 19. Use 'metadata_dims' to retrieve variable metadata +In addition to retrieve the data value, Start() can retrieve the auxiliary data as well. +The parameter 'metadata_dims' is for the variable which you want to get the value (e.g., 'tas'), +and the parameter 'return_vars' is for other variables in the netCDF file (e.g., 'lat', 'lon', 'time'). + +The definition of 'metadata_dims' is: +> A vector of character strings with the names of the file dimensions which to return metadata for. +Start() by default returns the auxiliary data read for only the first file of each source (or data set) in the pattern dimension. + However, it can be configured to return the metadata for all the files along any set of file dimensions. + +By default, 'metadata_dims' is equal to 'pattern_dims', which we usually assign as 'dat'. +By this means, the variable auxiliary data will be collected from the first file of each data set. +If you only have one variable to be retrieved, you have no problem with the default. +However, what if the data set number and/or the variable number is more than 1? You need to adjust this parameter to get the complete metadata. + +Here are some common cases and the corresponding 'metadata_dims' to be used: +- One dat, one var: 'dat' (or default) +- One dat, two vars: 'var' +- Two dats, one var: 'dat' (or default) +- Two dats, two vars: c('dat', 'var') + +If there are two variables to be retrieved but metadata_dims does'nt have "var", only the first +variable's metadata will be retrieved. If there are two data sets but metadata_dims doesn't have "dat", +only the first data set will have the variable's metadata. + +Please find the relevant use cases in [ex1_10](inst/doc/usecase/ex1_10_metadta_dims.R). + # Something goes wrong... diff --git a/inst/doc/usecase.md b/inst/doc/usecase.md index 65dbd2d..00eae6f 100644 --- a/inst/doc/usecase.md +++ b/inst/doc/usecase.md @@ -38,6 +38,10 @@ The problem may occur when the dimension number of the splitted selector is more 8. [Loading tas and tos from Decadal Predictions performed with the EC-Earth model](inst/doc/usecase/ex1_8_tasandtos.R) Some climate indices needs to be computed loading 'tas' (air temperature at 2m) over land and 'tos' (ocean surface temperature) over sea. Using **startR**, you can load these data in a unique **Start** call or with multiple calls separately for each variable. + 10. [Use 'metadata_dims' to retrieve complete variable metadata](inst/doc/usecase/ex1_10_metadta_dims.R) + This script tells you how to use the parameter 'metadata_dims' in Start() to get the complete variable metadata. +You will see four difference cases and learn the rules. +You can find more explanation in FAQ [How-to-19](inst/doc/faq.md#19-use-metadata_dims-to-retrieve-variable-metadata). 2. **Execute computation (use `Compute()`)** 1. [Function working on time dimension](inst/doc/usecase/ex2_1_timedim.R) diff --git a/inst/doc/usecase/ex1_10_metadata_dims.R b/inst/doc/usecase/ex1_10_metadata_dims.R new file mode 100644 index 0000000..d49e314 --- /dev/null +++ b/inst/doc/usecase/ex1_10_metadata_dims.R @@ -0,0 +1,180 @@ +#--------------------------------------------------------------------- +# This script tells you how to use the parameter 'metadata_dims' in Start() +# to get the complete variable metadata. You will see four difference cases +# and there are some rules can be followed: +# (1) If the length of 'dat'/'var' is more than 1, you need to assign that +# file dimension in 'metadata_dims' +# (2) If there is more than one 'dat', the metadata will be stored under +# $ in the attributes. +# (3) If there is only one 'dat', or 'dat' is not in 'metadata_dims', the +# metadata will be stored under $common in the attributes. +# You can find more explanation in FAQ How-to-19. + +#--------------------------------------------------------------------- +library(startR) + +# Case 1: One dat, one var + + repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + data <- Start(dat = list(list(name = 'system5_m1', path = repos)), + var = 'tas', + sdate = '20170101', + ensemble = indices(1), + time = indices(1), + lat = indices(1:10), + lon = indices(1:10), + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(time = 'sdate', + longitude = 'dat', + latitude = 'dat'), + metadata_dims = 'dat', # it can be omitted since it is automatically specified as 'dat' + retrieve = T + ) + +str(attr(data, 'Variables')) +# 'tas' is under $common +List of 2 + $ common :List of 2 + ..$ time: POSIXct[1:1], format: "2017-02-01" + ..$ tas :List of 12 + .. .. + .. .. + .. .. + $ system5_m1:List of 2 + ..$ longitude: num [1:10(1d)] 0 0.278 0.556 0.833 1.111 ... + .. .. + .. .. + .. .. + ..$ latitude : num [1:10(1d)] 89.8 89.5 89.2 88.9 88.7 ... + .. .. + .. .. + + +# Case 2: One dat, two vars + repos <- paste0('/esarchive/exp/ecearth/a1tr/cmorfiles/CMIP/EC-Earth-Consortium/', + 'EC-Earth3/historical/r24i1p1f1/Amon/$var$/gr/v20190312/', + '$var$_Amon_EC-Earth3_historical_r24i1p1f1_gr_185001-185012.nc') + var <- c('tas', 'clt') + sdate <- '20170101' + + data <- Start(dat = repos, + var = var, + time = indices(1), + lat = indices(1:10), + lon = indices(10:19), + return_vars = list(lat = NULL, lon = NULL), + metadata_dims = 'var', + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + retrieve = TRUE + ) + +str(attr(data, 'Variables')) +# 'tas' and 'clt' are under $common +List of 2 + $ common:List of 4 + ..$ lat: num [1:10(1d)] -89.5 -88.8 -88.1 -87.4 -86.7 ... + .. .. + ..$ lon: num [1:10(1d)] 6.33 7.03 7.73 8.44 9.14 ... + .. .. + ..$ tas:List of 17 + .. .. + ..$ clt:List of 16 + .. .. + $ dat1 : NULL + +# NOTE: If the above script is changed to metadata_dims = 'dat', you can only find +# 'tas' under $common + + +# Case 3: Two dats, one var + repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + repos2 <- "/esarchive/exp/ecmwf/system4_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + + data <- Start(dat = list(list(name = 'system4_m1', path = repos2), + list(name = 'system5_m1', path = repos)), + var = 'tas', + sdate = '20170101', + ensemble = indices(1), + time = indices(1), + lat = indices(1:10), + lon = indices(1:10), + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(time = 'sdate', + longitude = 'dat', + latitude = 'dat'), + metadata_dims = 'dat', # it can be omitted since it is automatically specified as 'dat' + retrieve = T + ) + +str(attr(data, 'Variables')) +# 'tas' is under both $system4_m1 and $system5_m1 +List of 3 + $ common :List of 1 + ..$ time: POSIXct[1:1], format: "2017-02-01" + $ system4_m1:List of 3 + ..$ longitude: num [1:10(1d)] 0 0.703 1.406 2.109 2.812 ... + .. .. + ..$ latitude : num [1:10(1d)] 89.5 88.8 88.1 87.4 86.7 ... + .. .. + ..$ tas :List of 11 + .. .. + $ system5_m1:List of 3 + ..$ longitude: num [1:10(1d)] 0 0.278 0.556 0.833 1.111 ... + .. .. + ..$ latitude : num [1:10(1d)] 89.8 89.5 89.2 88.9 88.7 ... + .. .. + ..$ tas :List of 12 + .. .. + + +# Case 4: Two dats, two vars + repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + repos2 <- "/esarchive/exp/ecmwf/system4_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + + data <- Start(dat = list(list(name = 'system4_m1', path = repos2), + list(name = 'system5_m1', path = repos)), + var = c('tas', 'sfcWind'), + sdate = '20170101', + ensemble = indices(1), + time = indices(1), + lat = indices(1:10), + lon = indices(1:10), + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(time = 'sdate', + longitude = 'dat', + latitude = 'dat'), + metadata_dims = c('dat', 'var'), + retrieve = T + ) + +str(attr(data, 'Variables')) +# 'tas' and 'sfcWind' are under both $system4_m1 and $system5_m1 +List of 3 + $ common :List of 1 + ..$ time: POSIXct[1:1], format: "2017-02-01" + $ system4_m1:List of 3 + ..$ longitude: num [1:10(1d)] 0 0.703 1.406 2.109 2.812 ... + .. .. + ..$ latitude : num [1:10(1d)] 89.5 88.8 88.1 87.4 86.7 ... + .. .. + ..$ tas :List of 11 + .. .. + ..$ sfcWind :List of 11 + .. .. + $ system5_m1:List of 4 + ..$ longitude: num [1:10(1d)] 0 0.278 0.556 0.833 1.111 ... + .. .. + ..$ latitude : num [1:10(1d)] 89.8 89.5 89.2 88.9 88.7 ... + .. .. + ..$ tas :List of 12 + .. .. + ..$ sfcWind :List of 12 + .. .. + +#NOTE: If metadata_dims = 'dat', only 'tas' is under each dat. +# If metadata_dims = 'var', 'tas' and 'sfcWind' will be under $common. + diff --git a/tests/testthat/test-Start-metadata_dims.R b/tests/testthat/test-Start-metadata_dims.R index a771f98..00edd5d 100644 --- a/tests/testthat/test-Start-metadata_dims.R +++ b/tests/testthat/test-Start-metadata_dims.R @@ -1,6 +1,6 @@ context("Start() metadata_dims check") -test_that("1. One data set", { +test_that("1. One data set, one var", { repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" data <- Start(dat = list(list(name = 'system5_m1', path = repos)), var = 'tas', @@ -39,10 +39,10 @@ test_that("1. One data set", { 12 ) -} +}) -test_that("2. Two data sets", { +test_that("2. Two data sets, one var", { repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" repos2 <- "/esarchive/exp/ecmwf/system4_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" @@ -92,9 +92,204 @@ test_that("2. Two data sets", { 11 ) -} +}) -test_that("3. Specify metadata_dims with another file dimension", { +test_that("3. One data set, two vars", { + repos <- paste0('/esarchive/exp/ecearth/a1tr/cmorfiles/CMIP/EC-Earth-Consortium/', + 'EC-Earth3/historical/r24i1p1f1/Amon/$var$/gr/v20190312/', + '$var$_Amon_EC-Earth3_historical_r24i1p1f1_gr_185001-185012.nc') + var <- c('tas', 'clt') + sdate <- '20170101' + + data <- Start(dat = repos, + var = var, + time = indices(1), + lat = indices(1:10), + lon = indices(10:19), + return_vars = list(lat = NULL, lon = NULL), + metadata_dims = 'var', + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + retrieve = TRUE + ) + + expect_equal( + length(attr(data, 'Variables')), + 2 + ) + expect_equal( + names(attr(data, 'Variables')), + c("common", "dat1") + ) + expect_equal( + names(attr(data, 'Variables')$common), + c('lat', 'lon', 'tas', 'clt') + ) + expect_equal( + is.null(attr(data, 'Variables')$dat1), + TRUE + ) + expect_equal( + length(attr(data, 'Variables')$common$tas), + 17 + ) + expect_equal( + length(attr(data, 'Variables')$common$clt), + 16 + ) + +}) + +test_that("4. Two data sets, two vars", { + repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + repos2 <- "/esarchive/exp/ecmwf/system4_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + + data <- Start(dat = list(list(name = 'system4_m1', path = repos2), + list(name = 'system5_m1', path = repos)), + var = c('tas', 'sfcWind'), + sdate = '20170101', + ensemble = indices(1), + time = indices(1), + lat = indices(1:10), + lon = indices(1:10), + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(time = 'sdate', + longitude = 'dat', + latitude = 'dat'), + metadata_dims = 'dat', + retrieve = T + ) + + expect_equal( + length(attr(data, 'Variables')), + 3 + ) + expect_equal( + names(attr(data, 'Variables')), + c("common", "system4_m1", "system5_m1") + ) + expect_equal( + names(attr(data, 'Variables')$common), + 'time' + ) + expect_equal( + names(attr(data, 'Variables')$system4_m1), + c("longitude", "latitude", "tas") + ) + expect_equal( + names(attr(data, 'Variables')$system5_m1), + c("longitude", "latitude", "tas") + ) + expect_equal( + length(attr(data, 'Variables')$system5_m1$tas), + 12 + ) + expect_equal( + length(attr(data, 'Variables')$system4_m1$tas), + 11 + ) + + + data <- Start(dat = list(list(name = 'system4_m1', path = repos2), + list(name = 'system5_m1', path = repos)), + var = c('tas', 'sfcWind'), + sdate = '20170101', + ensemble = indices(1), + time = indices(1), + lat = indices(1:10), + lon = indices(1:10), + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(time = 'sdate', + longitude = 'dat', + latitude = 'dat'), + metadata_dims = c('dat', 'var'), + retrieve = T + ) + expect_equal( + length(attr(data, 'Variables')), + 3 + ) + expect_equal( + names(attr(data, 'Variables')), + c("common", "system4_m1", "system5_m1") + ) + expect_equal( + names(attr(data, 'Variables')$common), + 'time' + ) + expect_equal( + names(attr(data, 'Variables')$system4_m1), + c("longitude", "latitude", "tas", "sfcWind") + ) + expect_equal( + names(attr(data, 'Variables')$system5_m1), + c("longitude", "latitude", "tas", "sfcWind") + ) + expect_equal( + length(attr(data, 'Variables')$system5_m1$tas), + 12 + ) + expect_equal( + length(attr(data, 'Variables')$system5_m1$sfcWind), + 12 + ) + expect_equal( + length(attr(data, 'Variables')$system4_m1$tas), + 11 + ) + expect_equal( + length(attr(data, 'Variables')$system4_m1$sfcWind), + 11 + ) + +}) + +test_that("5. Specify metadata_dims with another file dimension", { + repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + repos2 <- "/esarchive/exp/ecmwf/system4_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc" + + data <- Start(dat = list(list(name = 'system4_m1', path = repos2), + list(name = 'system5_m1', path = repos)), + var = c('tas', 'sfcWind'), + sdate = c('20150101', '20160101', '20170101'), + ensemble = indices(1), + time = indices(1), + lat = indices(1:10), + lon = indices(1:10), + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(time = 'sdate', + longitude = 'dat', + latitude = 'dat'), + metadata_dims = 'sdate', + retrieve = T + ) + expect_equal( + length(attr(data, 'Variables')), + 3 + ) + expect_equal( + names(attr(data, 'Variables')), + c("common", "system4_m1", "system5_m1") + ) + expect_equal( + names(attr(data, 'Variables')$common), + c('time', 'tas', 'tas', 'tas') + ) + expect_equal( + names(attr(data, 'Variables')$system4_m1), + c("longitude", "latitude") + ) + expect_equal( + names(attr(data, 'Variables')$system5_m1), + c("longitude", "latitude") + ) + expect_equal( + length(attr(data, 'Variables')$common$tas), + 12 + ) -} +}) -- GitLab From 20d85683f5473f4b3e2aba0802de933eeec199de Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 20 Aug 2020 14:55:37 +0200 Subject: [PATCH 17/30] Typo fix for how-to-19 --- inst/doc/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/doc/faq.md b/inst/doc/faq.md index c5be8aa..7121ca1 100644 --- a/inst/doc/faq.md +++ b/inst/doc/faq.md @@ -718,7 +718,7 @@ If there are two variables to be retrieved but metadata_dims does'nt have "var", variable's metadata will be retrieved. If there are two data sets but metadata_dims doesn't have "dat", only the first data set will have the variable's metadata. -Please find the relevant use cases in [ex1_10](inst/doc/usecase/ex1_10_metadta_dims.R). +Please find the relevant use cases in [ex1_10](inst/doc/usecase/ex1_10_metadata_dims.R). # Something goes wrong... -- GitLab From d286d76480322b5f3aa4f928a64b8aa6aade6a6e Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 20 Aug 2020 14:57:29 +0200 Subject: [PATCH 18/30] typo fix for ex1_10 --- inst/doc/usecase.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/doc/usecase.md b/inst/doc/usecase.md index 00eae6f..1d3e877 100644 --- a/inst/doc/usecase.md +++ b/inst/doc/usecase.md @@ -38,7 +38,7 @@ The problem may occur when the dimension number of the splitted selector is more 8. [Loading tas and tos from Decadal Predictions performed with the EC-Earth model](inst/doc/usecase/ex1_8_tasandtos.R) Some climate indices needs to be computed loading 'tas' (air temperature at 2m) over land and 'tos' (ocean surface temperature) over sea. Using **startR**, you can load these data in a unique **Start** call or with multiple calls separately for each variable. - 10. [Use 'metadata_dims' to retrieve complete variable metadata](inst/doc/usecase/ex1_10_metadta_dims.R) + 10. [Use 'metadata_dims' to retrieve complete variable metadata](inst/doc/usecase/ex1_10_metadata_dims.R) This script tells you how to use the parameter 'metadata_dims' in Start() to get the complete variable metadata. You will see four difference cases and learn the rules. You can find more explanation in FAQ [How-to-19](inst/doc/faq.md#19-use-metadata_dims-to-retrieve-variable-metadata). -- GitLab From e423258a448f3b0c2d3381040cbe58423029e7ab Mon Sep 17 00:00:00 2001 From: nperez Date: Thu, 20 Aug 2020 18:18:42 +0200 Subject: [PATCH 19/30] change name chunk by .chunk in inst/chunking folder --- inst/chunking/load_process_save_chunk.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inst/chunking/load_process_save_chunk.R b/inst/chunking/load_process_save_chunk.R index a8a31a8..c50c79b 100644 --- a/inst/chunking/load_process_save_chunk.R +++ b/inst/chunking/load_process_save_chunk.R @@ -52,7 +52,7 @@ for (input in 1:length(data)) { split_dims_to_alter <- which(names(split_dims[[k]]) %in% names_dims_to_alter) chunks_split_dims[split_dims_to_alter] <- unlist(chunks[names(split_dims[[k]])[split_dims_to_alter]]) chunks_indices_split_dims[split_dims_to_alter] <- chunk_indices[names(split_dims[[k]])[split_dims_to_alter]] - start_call[[names(split_dims)[k]]] <- chunk(chunks_indices_split_dims, chunks_split_dims, + start_call[[names(split_dims)[k]]] <- .chunk(chunks_indices_split_dims, chunks_split_dims, eval(start_call[[names(split_dims)[k]]])) dims_to_alter_to_remove <- which(names_dims_to_alter %in% names(split_dims[[k]])) if (length(dims_to_alter_to_remove) > 0) { @@ -63,7 +63,7 @@ for (input in 1:length(data)) { } if (length(dims_to_alter) > 0) { for (call_dim in names_dims_to_alter) { - start_call[[call_dim]] <- chunk(chunk_indices[call_dim], chunks[[call_dim]], + start_call[[call_dim]] <- .chunk(chunk_indices[call_dim], chunks[[call_dim]], eval(start_call[[call_dim]])) } } -- GitLab From 2e52084c632d7fface3b326a1803e42f9ff6beea Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 20 Aug 2020 19:44:16 +0200 Subject: [PATCH 20/30] Remove trash file --- R/.nfs0000000000216b150000002c | Bin 16384 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 R/.nfs0000000000216b150000002c diff --git a/R/.nfs0000000000216b150000002c b/R/.nfs0000000000216b150000002c deleted file mode 100644 index 279efb3cd9209d7600c28d21cf0410000c31bc30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 Yl~evA8k*wz>%}UA7ldii6vrF?0e|(b%7 -- GitLab From cb292b984238ea0abf6f899db79dde81b37bead6 Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 20 Aug 2020 20:35:35 +0200 Subject: [PATCH 21/30] Recover the development --- R/Start.R | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/R/Start.R b/R/Start.R index 8efea29..6bf9e9e 100644 --- a/R/Start.R +++ b/R/Start.R @@ -644,8 +644,8 @@ #'When specifying a path pattern for a dataset, it might contain shell glob #'experissions. For each dataset, the first file matching the path pattern is #'found, and the found file is used to work out fixed values for the glob -#'expressions that will be used for all the files of the dataset. However in -#'some cases the values of the shell glob expressions may not be constant for +#'expressions that will be used for all the files of the dataset. However, in +#'some cases, the values of the shell glob expressions may not be constant for #'all files in a dataset, and they need to be worked out for each file #'involved.\cr\cr #'For example, a path pattern could be as follows: \cr @@ -667,7 +667,16 @@ #' pattern with the original glob expressions in the 1st and 2nd levels (in the #' example, both asterisks would be preserved, thus would allow Start() #' to recognize files such as \cr -#' \code{'/path/to/dataset/precipitation_zzz/19901101_yyy_foo.nc'}). +#' \code{'/path/to/dataset/precipitation_zzz/19901101_yyy_foo.nc'}).\cr\cr +#'Note that each glob expression can only represent one possibility (Start() +#'chooses the first). Because /code{*} is not the tag, which means it cannot +#'be a dimension of the output array. Therefore, only one possibility can be +#'adopted. For example, if \cr +#'\code{'/path/to/dataset/precipitation_*/19901101_*_foo.nc'}\cr +#'has two matches:\cr +#'\code{'/path/to/dataset/precipitation_xxx/19901101_yyy_foo.nc'} and\cr +#'\code{'/path/to/dataset/precipitation_zzz/19901101_yyy_foo.nc'},\cr +#'only the first found file will be used. #'@param retrieve A logical value indicating whether to retrieve the data #' defined in the Start() call or to explore only its dimension lengths #' and names, and the values for the file and inner dimensions. The default @@ -1686,6 +1695,8 @@ Start <- function(..., # dim = indices/selectors, replace_values[[u_file_dim]] <- '*' depended_dim <- NULL depended_dim_values <- NA + +#NOTE: Here 'selectors' is always 1. Is it supposed to be like this? selectors <- dat_selectors[[u_file_dim]][[1]] if (u_file_dim %in% names(depending_file_dims)) { depended_dim <- depending_file_dims[[u_file_dim]] @@ -1787,6 +1798,20 @@ Start <- function(..., # dim = indices/selectors, sub_array_of_not_found_files[j] <- TRUE } else { file_path <- .ReplaceVariablesInString(dat[[i]][['path']], replace_values) + +#NOTE: After replacing tags, there is still * if path_glob_permissive is not FALSE. + if (grepl('\\*', file_path)) { + found_files <- Sys.glob(file_path) + file_path <- found_files[1] # choose only the first file. +#NOTE: Above line chooses only the first found file. Because * is not tags, which means +# it is not a dimension. So it cannot store more than one item. If use * to define +# the path, that * should only represent one possibility. + if (length(found_files) > 1) { + .warning("Using glob expression * to define the path, but more ", + "than one match is found. Choose the first match only.") + } + } + if (!(length(grep("^http", file_path)) > 0)) { if (grepl(file_path, '*', fixed = TRUE)) { file_path_full <- Sys.glob(file_path)[1] -- GitLab From d780bd2153e429202a64129290b4feb2b56e06bf Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 20 Aug 2020 21:05:00 +0200 Subject: [PATCH 22/30] Modify unit test for new development --- tests/testthat/test-Start-first_file_missing.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-Start-first_file_missing.R b/tests/testthat/test-Start-first_file_missing.R index 5f7a5a6..95319ae 100644 --- a/tests/testthat/test-Start-first_file_missing.R +++ b/tests/testthat/test-Start-first_file_missing.R @@ -69,7 +69,7 @@ data <- Start(dat = file, return_vars = list(latitude = 'dat', longitude = 'dat', time = 'file_date'), - metadata_dims = c('file_date'), +# metadata_dims = c('file_date'), retrieve = T) expect_equal( @@ -87,7 +87,7 @@ data <- Start(dat = file, ) expect_equal( names(attr(data, 'Variables')$common), - c('time', 'tas') + c('time') ) }) @@ -112,7 +112,7 @@ data <- Start(dat = file, expect_equal( names(attr(data, 'Variables')$common), - c('latitude', 'longitude', 'time', 'tas') + c('latitude', 'longitude', 'time', 'tas', NA) ) expect_equal( as.vector(attr(data, 'NotFoundFiles')), -- GitLab From cff5eaf62259da794bc16afa7b596524ed6f996d Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 20 Aug 2020 21:17:47 +0200 Subject: [PATCH 23/30] Upgrade version number --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index b1b9425..a75b2cf 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: startR Title: Automatically Retrieve Multidimensional Distributed Data Sets -Version: 2.0.0 +Version: 2.0.1 Authors@R: c( person("BSC-CNS", role = c("aut", "cph")), person("Nicolau", "Manubens", , "nicolau.manubens@bsc.es", role = c("aut")), -- GitLab From 7813d21ad8569ee39e60f69edfcc56c34676cd5d Mon Sep 17 00:00:00 2001 From: nperez Date: Fri, 21 Aug 2020 11:43:20 +0200 Subject: [PATCH 24/30] This change has worked --- inst/chunking/load_process_save_chunk.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inst/chunking/load_process_save_chunk.R b/inst/chunking/load_process_save_chunk.R index c50c79b..e68b869 100644 --- a/inst/chunking/load_process_save_chunk.R +++ b/inst/chunking/load_process_save_chunk.R @@ -52,7 +52,7 @@ for (input in 1:length(data)) { split_dims_to_alter <- which(names(split_dims[[k]]) %in% names_dims_to_alter) chunks_split_dims[split_dims_to_alter] <- unlist(chunks[names(split_dims[[k]])[split_dims_to_alter]]) chunks_indices_split_dims[split_dims_to_alter] <- chunk_indices[names(split_dims[[k]])[split_dims_to_alter]] - start_call[[names(split_dims)[k]]] <- .chunk(chunks_indices_split_dims, chunks_split_dims, + start_call[[names(split_dims)[k]]] <- startR:::.chunk(chunks_indices_split_dims, chunks_split_dims, eval(start_call[[names(split_dims)[k]]])) dims_to_alter_to_remove <- which(names_dims_to_alter %in% names(split_dims[[k]])) if (length(dims_to_alter_to_remove) > 0) { @@ -63,7 +63,7 @@ for (input in 1:length(data)) { } if (length(dims_to_alter) > 0) { for (call_dim in names_dims_to_alter) { - start_call[[call_dim]] <- .chunk(chunk_indices[call_dim], chunks[[call_dim]], + start_call[[call_dim]] <- startR:::.chunk(chunk_indices[call_dim], chunks[[call_dim]], eval(start_call[[call_dim]])) } } -- GitLab From aa55f4069624b575c1a3da2032dd9a8a2fcd8929 Mon Sep 17 00:00:00 2001 From: aho Date: Fri, 21 Aug 2020 20:35:18 +0200 Subject: [PATCH 25/30] Create use case for using existing masks to do analysis --- inst/doc/usecase/ex2_10_existing_masks.R | 140 +++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 inst/doc/usecase/ex2_10_existing_masks.R diff --git a/inst/doc/usecase/ex2_10_existing_masks.R b/inst/doc/usecase/ex2_10_existing_masks.R new file mode 100644 index 0000000..d8757ca --- /dev/null +++ b/inst/doc/usecase/ex2_10_existing_masks.R @@ -0,0 +1,140 @@ +# Apply an existing mask file on data +# Author: An-Chi Ho +# ------------------------------------------------------------------ + + + +# A) Load mask file +mask_path <- '/esarchive/autosubmit/con_files/land_sea_mask_1x1_c3s.nc' + +mask <- Start(dat = mask_path, + var = 'LSM', + lat = 'all', + lon = 'all', + return_vars = list(var_names = NULL, + lat = NULL, lon = NULL), + var_var = 'var_names', + retrieve = F) + + +# B) Load data +data_path <- '/esarchive/exp/ecmwf/system5c3s/monthly_mean/$var$_f6h/$var$_$sdate$.nc' + +data <- Start(dat = data_path, + var = 'tos', + sdate = paste0(1991:2010, '0101'), + ensemble = 'all', + time = indices(1), + lat = 'all', + lon = 'all', + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(lat = NULL, + lon = NULL, + time = 'sdate'), + retrieve = FALSE) + +# C) Build the workflow +reg_mask <- function(data, mask) { + # data: [sdate = 20, ensemble = 25] + # mask: [dat = 1] + if (mask == 1) { + trend <- s2dv::Trend(data, time_dim = 'sdate')$trend[2, , , ] + ind <- mean(data) + } else { + ind <- NA + } + return(ind) + +} + +step_mask <- Step(fun = reg_mask, + target_dims = list(data = c('dat', 'sdate', 'ensemble', 'time'), + mask = c('dat')), + output_dim = NULL) + +wf_mask <- AddStep(list(data, mask), step_mask) + +res <- Compute(workflow = wf_mask, + chunks = list(lat = 4, + lon = 4)) + + + +#================= Case 2 ================== +# A) Load mask file +mask_path <- '/esarchive/autosubmit/con_files/mask.regions.HadISST.nc' + +mask1 <- Start(dat = mask_path, + var = 'Baffin_Bay', # c('Grnland', 'Baffin_Bay'), + lat = 'all', + lon = 'all', + synonims = list(lat = c('lat', 'y'), + lon = c('lon', 'x')), + return_vars = list(var_names = NULL, + lat = NULL, lon = NULL), + var_var = 'var_names', + retrieve = F) + +mask2 <- Start(dat = mask_path, + var = 'Grnland', + lat = 'all', + lon = 'all', + synonims = list(lat = c('lat', 'y'), + lon = c('lon', 'x')), + return_vars = list(var_names = NULL, + lat = NULL, lon = NULL), + var_var = 'var_names', + retrieve = F) + + +# B) Load data +data_path <- '/esarchive/exp/gfdl-cm4/cmip6-piControl/monthly_mean/sic-lonlat/sic_$sdate$.nc' + +data <- Start(dat = data_path, + var = 'siconc', + sdate = paste0('0', 521:540, '0101'), + ensemble = 'all', + time = indices(1), + lat = 'all', + lon = 'all', + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(lat = NULL, + lon = NULL, + time = 'sdate'), + retrieve = FALSE) + + +# C) Build the workflow +reg_mask <- function(data, mask1, mask2) { + # data: [sdate = 20, ensemble = 25] + # mask: [var = 2] +#--------Remove when s2dv::Trend is updated ------- + source('/esarchive/scratch/aho/Trend_tmp.R') +#----------------------------------------------- + + if (mask == 1 & mask2 == 1) { +#------------- Change when s2dv::Trend is updated ---------------- + trend <- Trend(data, time_dim = 'sdate')$trend[2, , , ] +# trend <- s2dv::Trend(data, time_dim = 'sdate')$trend[2, , , ] +#----------------------------------------------------------------- + ind <- mean(data) + } else { + ind <- NA + } + return(ind) + +} + +step_mask <- Step(fun = reg_mask, + target_dims = list(data = c('dat', 'sdate', 'ensemble', 'time'), + mask1 = c('dat'), + mask2 = c('dat')), + output_dim = NULL) + +wf_mask <- AddStep(list(data, mask1, mask2), step_mask) + +res <- Compute(workflow = wf_mask, + chunks = list(lat = 2, + lon = 2)) -- GitLab From cb13e04b4c18c57cd059281a74f60b2c40ea28b7 Mon Sep 17 00:00:00 2001 From: aho Date: Fri, 21 Aug 2020 20:35:52 +0200 Subject: [PATCH 26/30] Bugfix for metadata when retrieving two vars from one file --- R/Start.R | 14 +++++++-- tests/testthat/test-Start-metadata_dims.R | 36 +++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/R/Start.R b/R/Start.R index 6bf9e9e..8243fda 100644 --- a/R/Start.R +++ b/R/Start.R @@ -4218,9 +4218,17 @@ Start <- function(..., # dim = indices/selectors, } else { #(1) var_backup <- attr(data_array, 'Variables') - var_backup_name <- lapply(var_backup, names) - var_backup <- lapply(var_backup, '[[', 1) - names(var_backup) <- unlist(var_backup_name) + var_backup_names <- unlist(lapply(var_backup, names)) + new_list <- vector('list', length = length(var_backup_names)) + count <- 1 + for (kk in 1:length(var_backup)) { + for (jj in 1:length(var_backup[[kk]])) { + new_list[[count]] <- var_backup[[kk]][[jj]] + count <- count + 1 + } + } + names(new_list) <- var_backup_names + var_backup <- new_list } } attr(data_array, 'Variables') <- NULL diff --git a/tests/testthat/test-Start-metadata_dims.R b/tests/testthat/test-Start-metadata_dims.R index 00edd5d..b4ef3cf 100644 --- a/tests/testthat/test-Start-metadata_dims.R +++ b/tests/testthat/test-Start-metadata_dims.R @@ -291,5 +291,41 @@ test_that("5. Specify metadata_dims with another file dimension", { 12 ) +}) + + +test_that("6. One data set, two vars from one file", { +mask_path <- '/esarchive/autosubmit/con_files/mask.regions.Ec3.0_O1L46.nc' + +data <- Start(repos = mask_path, + var = c('nav_lon', 'nav_lat'), + t = 'first', + z = 'first', + x = 'all', + y = 'all', + return_vars = list(var_names = NULL), + var_var = 'var_names', + retrieve = T) + + expect_equal( + length(attr(data, 'Variables')), + 2 + ) + expect_equal( + names(attr(data, 'Variables')), + c("common", "dat1") + ) + expect_equal( + names(attr(data, 'Variables')$common), + c("var_names", "nav_lon", "nav_lat") + ) + expect_equal( + is.null(attr(data, 'Variables')$dat1), + TRUE + ) + expect_equal( + length(attr(data, 'Variables')$common$nav_lat), + 8 + ) }) -- GitLab From 4e12ffe0f88610c25fc521ed3058bb509133cda4 Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 24 Aug 2020 12:22:29 +0200 Subject: [PATCH 27/30] Create use case for existing mask file --- inst/doc/usecase.md | 7 +- inst/doc/usecase/ex2_10_existing_mask.R | 171 +++++++++++++++++++++++ inst/doc/usecase/ex2_10_existing_masks.R | 140 ------------------- 3 files changed, 176 insertions(+), 142 deletions(-) create mode 100644 inst/doc/usecase/ex2_10_existing_mask.R delete mode 100644 inst/doc/usecase/ex2_10_existing_masks.R diff --git a/inst/doc/usecase.md b/inst/doc/usecase.md index e049eb7..4e44631 100644 --- a/inst/doc/usecase.md +++ b/inst/doc/usecase.md @@ -61,8 +61,11 @@ You can find more explanation in FAQ [How-to-20](inst/doc/faq.md#20-use-metadata Use `SpecsVerification::EnsCrps` to calculate the ensemble-adjusted Continuous Ranked Probability Score (CRPS) for ECWMF experimental data, and do ensemble mean. Use `s2dverification::PlotEquiMap` to plot the CRPS map. 8. [Use CSTools Calibration function](inst/doc/usecase/ex2_8_calibration.R) Use `CSTools:::.cal`, the interior function of `CSTools::CST_Calibration`, to do the bias adjustment for ECMWF experimental monthly mean data. - 9. [Use a mask to apply different methods to different gridpoints](inst/doc/usecase/ex2_9_mask.R) If you need to apply your analysis in a few gridpoints, you may want to consider use case 1.6, but if you need to load a lot of grid points, maybe this a better solution. - + 9. [Use a mask to apply different methods to different gridpoints](inst/doc/usecase/ex2_9_mask.R) + If you need to apply your analysis in a few gridpoints, you may want to consider use case 1.6, but if you need to load a lot of grid points, maybe this a better solution. + 10. [Apply an existing mask on data](inst/doc/usecase/ex2_10_existing_mask.R) + This use case shows you how to apply the existing mask file on your data. +If you need to create the mask file on your own, go to ex2_9_mask.R. diff --git a/inst/doc/usecase/ex2_10_existing_mask.R b/inst/doc/usecase/ex2_10_existing_mask.R new file mode 100644 index 0000000..fb41e17 --- /dev/null +++ b/inst/doc/usecase/ex2_10_existing_mask.R @@ -0,0 +1,171 @@ +# Author: An-Chi Ho +# Date: 24th Aug. 2020 +# ------------------------------------------------------------------ +# This use case shows you how to apply the existing mask file on your data. +# Case 1 is a land-sea mask, and case 2 is a mask file containing several +# region's mask. +# If you need to create the mask file on your own, go to ex2_9_mask.R + + +#================= Case 1 ================== +# Goal: Apply a land-sea mask on tas data. Because the mask is tailored for +# system5c3s data, the latitude and longitude of the mask and data +# have matched already. + +# A) Load mask file +mask_path <- '/esarchive/autosubmit/con_files/land_sea_mask_1x1_c3s.nc' + +mask <- Start(dat = mask_path, + var = 'LSM', + lat = 'all', + lon = 'all', + return_vars = list(var_names = NULL, + lat = NULL, lon = NULL), + var_var = 'var_names', + retrieve = F) + + +# B) Load data +data_path <- '/esarchive/exp/ecmwf/system5c3s/monthly_mean/$var$_f6h/$var$_$sdate$.nc' + +data <- Start(dat = data_path, + var = 'tas', + sdate = paste0(1991:2010, '0101'), + ensemble = 'all', + time = indices(1), + lat = 'all', + lon = 'all', + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(lat = NULL, + lon = NULL, + time = 'sdate'), + retrieve = FALSE) + +# C) Build the workflow +reg_mask <- function(data, mask) { + # data: [dat = 1, sdate = 20, ensemble = 25, time = 1] + # mask: [dat = 1] + if (mask == 1) { + ind <- s2dv::MeanDims(data, c('dat', 'ensemble', 'time')) + } else { + ind <- array(rep(NA, dim(data)[2]), dim = c(sdate = dim(data)[2])) + } + return(ind) + +} + +step_mask <- Step(fun = reg_mask, + target_dims = list(data = c('dat', 'sdate', 'ensemble', 'time'), + mask = c('dat')), + output_dim = 'sdate') + +wf_mask <- AddStep(list(data, mask), step_mask) + +res <- Compute(workflow = wf_mask, + chunks = list(lat = 2, + lon = 2)) + +# Check with plotting +library(s2dv) +s2dv::PlotLayout(PlotEquiMap, c('lat', 'lon'), res$output1[ , 1, , ], + lon = seq(0, 359, 1), lat = seq(90, -90, -1)) + + +#================= Case 2 ================== +# Goal: Apply analysis only on Baffin Bay and Greenland region. +# The mask of the two regions is from the same file, while we have to read them +# seperately because the dimensions have to be in line with the data. That is, +# the length of 'var' can only be 1. +# Another way is read data with repetitive "var = c('siconc', 'siconc')" and read mask +# as one object with "var = c('Baffin_Bay', 'Grnland')". The following workflow need +# to adjust accordingly. + +# A) Load mask file +mask_path <- '/esarchive/autosubmit/con_files/mask.regions.HadISST.nc' + +mask1 <- Start(dat = mask_path, + var = 'Baffin_Bay', + lat = 'all', + lon = 'all', + synonims = list(lat = c('lat', 'y'), + lon = c('lon', 'x')), + return_vars = list(var_names = NULL, + lat = NULL, lon = NULL), + var_var = 'var_names', + retrieve = F) + +mask2 <- Start(dat = mask_path, + var = 'Grnland', + lat = 'all', + lon = 'all', + synonims = list(lat = c('lat', 'y'), + lon = c('lon', 'x')), + return_vars = list(var_names = NULL, + lat = NULL, lon = NULL), + var_var = 'var_names', + retrieve = F) + + +# B) Load data +# The original longitude range is [0, 360]. Reorder to [-180, 180] to be in line with masks. +data_path <- '/esarchive/exp/gfdl-cm4/cmip6-piControl/monthly_mean/sic-lonlat/sic_$sdate$.nc' +lons.min <- -179.5 +lons.max <- 179.5 +lats.min <- -90 +lats.max <- 90 + +data <- Start(dat = data_path, + var = 'siconc', + sdate = paste0('0', 521:540, '0101'), + ensemble = 'all', + time = indices(1), + lat = values(list(lats.min, lats.max)), + lat_reorder = Sort(), + lon = values(list(lons.min, lons.max)), + lon_reorder = CircularSort(-180, 180), + synonims = list(lat = c('lat', 'latitude'), + lon = c('lon', 'longitude')), + return_vars = list(lat = NULL, + lon = NULL, + time = 'sdate'), + retrieve = FALSE) + + +# C) Build the workflow +reg_mask <- function(data, mask1, mask2) { + # data: [var = 1, sdate = 20, ensemble = 1, time = 1] + # mask1 and mask2: [var = 1] +#--------Remove when s2dv::Trend is updated ------- + source('/esarchive/scratch/aho/Trend_tmp.R') +#----------------------------------------------- + + if (mask1 == 1 | mask2 == 1) { +#------------- Change when s2dv::Trend is updated ---------------- + trend <- Trend(data, time_dim = 'sdate')$trend[2, , , ] +# trend <- s2dv::Trend(data, time_dim = 'sdate')$trend[2, , , ] +#----------------------------------------------------------------- + ind <- mean(data) + } else { + ind <- NA + } + return(ind) +} + +# The necessary target dim of data for the function is 'sdate' only, but those not +# in mask dimensions are needed to be included here to make chunking work. +step_mask <- Step(fun = reg_mask, + target_dims = list(data = c('var', 'sdate', 'ensemble', 'time'), + mask1 = c('var'), + mask2 = c('var')), + output_dim = NULL) + +wf_mask <- AddStep(list(data, mask1, mask2), step_mask) + +res <- Compute(workflow = wf_mask, + chunks = list(lat = 2, + lon = 2)) + +# Check with plotting. Only the two regions have values +s2dv::PlotEquiMap(res$output1[1, , ], lon = seq(-179.5, 179.5, 1), lat = seq(-89.5, 89.5, 1)) + diff --git a/inst/doc/usecase/ex2_10_existing_masks.R b/inst/doc/usecase/ex2_10_existing_masks.R deleted file mode 100644 index d8757ca..0000000 --- a/inst/doc/usecase/ex2_10_existing_masks.R +++ /dev/null @@ -1,140 +0,0 @@ -# Apply an existing mask file on data -# Author: An-Chi Ho -# ------------------------------------------------------------------ - - - -# A) Load mask file -mask_path <- '/esarchive/autosubmit/con_files/land_sea_mask_1x1_c3s.nc' - -mask <- Start(dat = mask_path, - var = 'LSM', - lat = 'all', - lon = 'all', - return_vars = list(var_names = NULL, - lat = NULL, lon = NULL), - var_var = 'var_names', - retrieve = F) - - -# B) Load data -data_path <- '/esarchive/exp/ecmwf/system5c3s/monthly_mean/$var$_f6h/$var$_$sdate$.nc' - -data <- Start(dat = data_path, - var = 'tos', - sdate = paste0(1991:2010, '0101'), - ensemble = 'all', - time = indices(1), - lat = 'all', - lon = 'all', - synonims = list(lat = c('lat', 'latitude'), - lon = c('lon', 'longitude')), - return_vars = list(lat = NULL, - lon = NULL, - time = 'sdate'), - retrieve = FALSE) - -# C) Build the workflow -reg_mask <- function(data, mask) { - # data: [sdate = 20, ensemble = 25] - # mask: [dat = 1] - if (mask == 1) { - trend <- s2dv::Trend(data, time_dim = 'sdate')$trend[2, , , ] - ind <- mean(data) - } else { - ind <- NA - } - return(ind) - -} - -step_mask <- Step(fun = reg_mask, - target_dims = list(data = c('dat', 'sdate', 'ensemble', 'time'), - mask = c('dat')), - output_dim = NULL) - -wf_mask <- AddStep(list(data, mask), step_mask) - -res <- Compute(workflow = wf_mask, - chunks = list(lat = 4, - lon = 4)) - - - -#================= Case 2 ================== -# A) Load mask file -mask_path <- '/esarchive/autosubmit/con_files/mask.regions.HadISST.nc' - -mask1 <- Start(dat = mask_path, - var = 'Baffin_Bay', # c('Grnland', 'Baffin_Bay'), - lat = 'all', - lon = 'all', - synonims = list(lat = c('lat', 'y'), - lon = c('lon', 'x')), - return_vars = list(var_names = NULL, - lat = NULL, lon = NULL), - var_var = 'var_names', - retrieve = F) - -mask2 <- Start(dat = mask_path, - var = 'Grnland', - lat = 'all', - lon = 'all', - synonims = list(lat = c('lat', 'y'), - lon = c('lon', 'x')), - return_vars = list(var_names = NULL, - lat = NULL, lon = NULL), - var_var = 'var_names', - retrieve = F) - - -# B) Load data -data_path <- '/esarchive/exp/gfdl-cm4/cmip6-piControl/monthly_mean/sic-lonlat/sic_$sdate$.nc' - -data <- Start(dat = data_path, - var = 'siconc', - sdate = paste0('0', 521:540, '0101'), - ensemble = 'all', - time = indices(1), - lat = 'all', - lon = 'all', - synonims = list(lat = c('lat', 'latitude'), - lon = c('lon', 'longitude')), - return_vars = list(lat = NULL, - lon = NULL, - time = 'sdate'), - retrieve = FALSE) - - -# C) Build the workflow -reg_mask <- function(data, mask1, mask2) { - # data: [sdate = 20, ensemble = 25] - # mask: [var = 2] -#--------Remove when s2dv::Trend is updated ------- - source('/esarchive/scratch/aho/Trend_tmp.R') -#----------------------------------------------- - - if (mask == 1 & mask2 == 1) { -#------------- Change when s2dv::Trend is updated ---------------- - trend <- Trend(data, time_dim = 'sdate')$trend[2, , , ] -# trend <- s2dv::Trend(data, time_dim = 'sdate')$trend[2, , , ] -#----------------------------------------------------------------- - ind <- mean(data) - } else { - ind <- NA - } - return(ind) - -} - -step_mask <- Step(fun = reg_mask, - target_dims = list(data = c('dat', 'sdate', 'ensemble', 'time'), - mask1 = c('dat'), - mask2 = c('dat')), - output_dim = NULL) - -wf_mask <- AddStep(list(data, mask1, mask2), step_mask) - -res <- Compute(workflow = wf_mask, - chunks = list(lat = 2, - lon = 2)) -- GitLab From d55ed34fbd28de91ce7fce06132517eaeb682c58 Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 24 Aug 2020 12:22:43 +0200 Subject: [PATCH 28/30] Add author and date --- inst/doc/usecase/ex1_10_metadata_dims.R | 2 ++ inst/doc/usecase/ex1_9_path_glob_permissive.R | 2 ++ 2 files changed, 4 insertions(+) diff --git a/inst/doc/usecase/ex1_10_metadata_dims.R b/inst/doc/usecase/ex1_10_metadata_dims.R index cba3022..b5909d7 100644 --- a/inst/doc/usecase/ex1_10_metadata_dims.R +++ b/inst/doc/usecase/ex1_10_metadata_dims.R @@ -1,3 +1,5 @@ +# Author: An-Chi Ho +# Date: 20th Aug. 2020 #--------------------------------------------------------------------- # This script tells you how to use the parameter 'metadata_dims' in Start() # to get the complete variable metadata. You will see four difference cases diff --git a/inst/doc/usecase/ex1_9_path_glob_permissive.R b/inst/doc/usecase/ex1_9_path_glob_permissive.R index f52f7e0..e2f25d1 100644 --- a/inst/doc/usecase/ex1_9_path_glob_permissive.R +++ b/inst/doc/usecase/ex1_9_path_glob_permissive.R @@ -1,3 +1,5 @@ +# Author: An-Chi Ho +# Date: 17th Aug. 2020 #--------------------------------------------------------------------- # This script shows you how to use glob expression '*' and the parameter 'path_glob_permissive' of Start(). # The regular way to define the path for Start() is using the tags, i.e., '$$'. -- GitLab From e5eb4a1e26e964952d6f750d03b378b0e37e6780 Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 24 Aug 2020 20:59:55 +0200 Subject: [PATCH 29/30] Add Compute() on Nord3, result checking --- inst/doc/usecase/ex2_10_existing_mask.R | 71 ++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/inst/doc/usecase/ex2_10_existing_mask.R b/inst/doc/usecase/ex2_10_existing_mask.R index fb41e17..20d2db7 100644 --- a/inst/doc/usecase/ex2_10_existing_mask.R +++ b/inst/doc/usecase/ex2_10_existing_mask.R @@ -62,16 +62,50 @@ step_mask <- Step(fun = reg_mask, wf_mask <- AddStep(list(data, mask), step_mask) +# run locally res <- Compute(workflow = wf_mask, chunks = list(lat = 2, lon = 2)) +# Submit to Nord3 +#-------------------user-defined--------------------- + queue_host <- 'nord1' + temp_dir <- '/gpfs/scratch/bsc32/bsc32734/startR_hpc/' + ecflow_suite_dir <- '/home/Earth/aho/startR_local/' +#---------------------------------------------------- + res <- Compute(wf_mask, + chunks = list(lat = 2, + lon = 2),#$output1 + threads_load = 2, + threads_compute = 4, + cluster = list(queue_host = queue_host, + queue_type = 'lsf', + temp_dir = temp_dir, + cores_per_job = 2, + job_wallclock = '05:00', + max_jobs = 4, + extra_queue_params = list('#BSUB -q bsc_es'), + bidirectional = FALSE, + polling_period = 10 + ), + ecflow_suite_dir = ecflow_suite_dir, + wait = TRUE + ) + +#-------- See the result ----------- +str(res$output1) +# num [1:20, 1, 1:181, 1:360] 249 245 247 245 247 ... +summary(res$output1) +# Min. 1st Qu. Median Mean 3rd Qu. Max. NA's +# 236.8 273.9 286.5 282.4 297.1 304.4 441960 + # Check with plotting library(s2dv) s2dv::PlotLayout(PlotEquiMap, c('lat', 'lon'), res$output1[ , 1, , ], lon = seq(0, 359, 1), lat = seq(90, -90, -1)) + #================= Case 2 ================== # Goal: Apply analysis only on Baffin Bay and Greenland region. # The mask of the two regions is from the same file, while we have to read them @@ -162,9 +196,42 @@ step_mask <- Step(fun = reg_mask, wf_mask <- AddStep(list(data, mask1, mask2), step_mask) +# Run locally res <- Compute(workflow = wf_mask, - chunks = list(lat = 2, - lon = 2)) + chunks = list(lat = 2, + lon = 2)) + +# Submit to Nord3 +#-------------------user-defined--------------------- + queue_host <- 'nord1' + temp_dir <- '/gpfs/scratch/bsc32/bsc32734/startR_hpc/' + ecflow_suite_dir <- '/home/Earth/aho/startR_local/' +#---------------------------------------------------- + res <- Compute(wf_mask, + chunks = list(lat = 2, + lon = 2),#$output1 + threads_load = 2, + threads_compute = 4, + cluster = list(queue_host = queue_host, + queue_type = 'lsf', + temp_dir = temp_dir, + cores_per_job = 2, + job_wallclock = '05:00', + max_jobs = 4, + extra_queue_params = list('#BSUB -q bsc_es'), + bidirectional = FALSE, + polling_period = 10 + ), + ecflow_suite_dir = ecflow_suite_dir, + wait = TRUE + ) + +#--------Check the result ------------ +str(res$output1) +# num [1, 1:180, 1:360] NA NA NA NA NA NA NA NA NA NA ... +summary(res$output1) +# Min. 1st Qu. Median Mean 3rd Qu. Max. NA's +# 0.00 78.83 95.44 80.00 97.60 99.91 64093 # Check with plotting. Only the two regions have values s2dv::PlotEquiMap(res$output1[1, , ], lon = seq(-179.5, 179.5, 1), lat = seq(-89.5, 89.5, 1)) -- GitLab From c2242a1070be6f2e9288ebf1dea7a4f9b9458006 Mon Sep 17 00:00:00 2001 From: aho Date: Wed, 26 Aug 2020 10:50:11 +0200 Subject: [PATCH 30/30] Update pdf and NEWS for v2.0.1 --- NEWS.md | 2 +- startR-manual.pdf | Bin 151587 -> 152686 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 8002e90..c348dda 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# startR v2.0.1 (Release date: 2020-08-21) +# startR v2.0.1 (Release date: 2020-08-25) - Bugfix for the function .chunk(). Its name was chunk() before v2.0.0, and there are two parts were not renamed to .chunk() in v2.0.0. - Bugfix for metadata in the condition that reorder or transform is applied and 'return_vars' is NULL. diff --git a/startR-manual.pdf b/startR-manual.pdf index 3417b13eaf55bc8c3e82ee68bf29c1c3900d2704..d8749b9c70344724b637231f2c63e0dcc6e034ec 100644 GIT binary patch delta 82467 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

DguqP&#=JM$&D%5@=Vw*|e?zcCi;^`|KBW@FR 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 delta 81529 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