diff --git a/.Rbuildignore b/.Rbuildignore index f6430a4587524c56d276b040b1318e3561853bcf..2814b11b1187b7963ea8c1cf6a04e019ebe4392b 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -10,4 +10,7 @@ README\.md$ vignettes .gitlab-ci.yml # unit tests should be ignored when building the package for CRAN -#^tests$ +^tests$ +# CDO is not in windbuilder, so we can test the unit tests by winbuilder +# but test-CDORemap.R needs to be hidden +#tests/testthat/test-CDORemap.R diff --git a/DESCRIPTION b/DESCRIPTION index 0b45aff93c7ea89ce8ad247c16d478727ddc7013..f2577bfeebb720f2d76e89bde01f267e54ade2ae 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: s2dv Title: A Set of Common Tools for Seasonal to Decadal Verification -Version: 1.0.0 +Version: 1.1.0 Authors@R: c( person("BSC-CNS", role = c("aut", "cph")), person("An-Chi", "Ho", , "an.ho@bsc.es", role = c("aut", "cre")), diff --git a/NAMESPACE b/NAMESPACE index 7cbec955260f4cd54997046277a3d9c886e599db..ca5d500368ca97734ff3b1c4bbc51b3b547e948c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -84,6 +84,7 @@ import(multiApply) import(ncdf4) import(parallel) import(plyr) +import(stats) importFrom(ClimProjDiags,CombineIndices) importFrom(ClimProjDiags,Subset) importFrom(ClimProjDiags,WeightedMean) @@ -130,5 +131,6 @@ importFrom(stats,sd) importFrom(stats,setNames) importFrom(stats,spectrum) importFrom(stats,ts) +importFrom(stats,var) importFrom(stats,varimax) importFrom(stats,window) diff --git a/NEWS.md b/NEWS.md index e537e95964bc8453030f091399a1a66bc81cd3f0..71993f0e554bb260e19b2678f9c455d5e0923f2f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,13 @@ +# s2dv 1.1.0 (Release date: 2021-12-14) +- New functions: RatioPredictableComponents, SignalNoiseRatio +- CDORemap(): Able to interpolate irregular grid to regular grid; include new cdo methods 'con2', 'laf' and 'nn' +- PlotEquiMap(): Discard the dependency on 'GEOmap' and 'geomapdata' and only use package 'map' now; +new parameters 'country.borders', 'shapefile', 'shapefile_color', and 'shapefile_lwd' for plotting the national borders and shapefile +- PlotLayout(): new parameter 'layout_by_rows' for changing the layout order +- MeanDims(): new parameter 'drop' to choose whether to drop the averaged dimension or not; +Bugfix for making the result as array even if the result is only a number +- Season(): Add dimension name even if the result is only a number + # s2dv 1.0.0 (Release date: 2021-06-16) - New functions: ACC, Ano_CrossValid, BrierScore, CDORemap, Cluster, Consistent_Trend, EOF, EuroAtlanticTC, Filter, Histo2Hindcast, diff --git a/R/BrierScore.R b/R/BrierScore.R index 1363f6155ff53a7c73cb8afd3d630f05fceb343a..c3673ad4273089059f13debc91d244554c2f90cd 100644 --- a/R/BrierScore.R +++ b/R/BrierScore.R @@ -174,7 +174,7 @@ BrierScore <- function(exp, obs, thresholds = seq(0.1, 0.9, 0.1), time_dim = 'sd name_exp <- name_exp[-which(name_exp == dat_dim)] name_obs <- name_obs[-which(name_obs == dat_dim)] } - if (any(name_exp != name_obs)) { + if (any(!name_exp %in% name_obs) | any(!name_obs %in% name_exp)) { stop(paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", "of all the dimensions expect 'dat_dim' and 'memb_dim'.")) } diff --git a/R/Cluster.R b/R/Cluster.R index 33527aea9b0e8f43bcce78be874cd07d5a02629a..8f401182b93a1d1b62a1041de9779910cbcc8d2d 100644 --- a/R/Cluster.R +++ b/R/Cluster.R @@ -181,7 +181,7 @@ Cluster <- function(data, weights = NULL, time_dim = 'sdate', space_dim = NULL, if (!(length(space_dim) == length(dim(weights)) & all(space_dim %in% names(dim(weights))))) { stop("Parameter 'weights' must have dimension names the same as 'space_dim'.") } - if (space_dim != names(dim(weights))) { + if (any(space_dim != names(dim(weights)))) { space_dim <- names(dim(weights)) } } diff --git a/R/Histo2Hindcast.R b/R/Histo2Hindcast.R index 860f56b96bae59a9b06e0eff937a24d5df79668d..5657457d7a47933153496ada5062cb8a94bc95fa 100644 --- a/R/Histo2Hindcast.R +++ b/R/Histo2Hindcast.R @@ -66,7 +66,7 @@ Histo2Hindcast <- function(data, sdatesin, sdatesout, nleadtimesout, if (is.null(sdatesin)) { stop("Parameter 'sdatesin' cannot be NULL.") } - if (!is.character(sdatesin) | length(sdatesin) > 1) { + if (!is.character(sdatesin) || length(sdatesin) > 1) { stop(paste0("Parameter 'sdatesin' must be a character string in the format", " 'YYYYMMDD' or 'YYYYMM'.")) } else if (!nchar(sdatesin) %in% c(6, 8) | is.na(as.numeric(sdatesin))) { @@ -88,12 +88,12 @@ Histo2Hindcast <- function(data, sdatesin, sdatesout, nleadtimesout, if (is.null(nleadtimesout)) { stop("Parameter 'nleadtimesout' cannot be NULL.") } - if (!is.numeric(nleadtimesout) | nleadtimesout %% 1 != 0 | - nleadtimesout < 0 | length(nleadtimesout) > 1) { + if (!is.numeric(nleadtimesout) | any(nleadtimesout %% 1 != 0) | + any(nleadtimesout < 0) | length(nleadtimesout) > 1) { stop("Parameter 'nleadtimesout' must be a positive integer.") } # sdate_dim - if (!is.character(sdate_dim) | length(sdate_dim) > 1) { + if (!is.character(sdate_dim) || length(sdate_dim) > 1) { stop("Parameter 'sdate_dim' must be a character string.") } if (!sdate_dim %in% names(dim(data))) { @@ -103,7 +103,7 @@ Histo2Hindcast <- function(data, sdatesin, sdatesout, nleadtimesout, stop("The dimension length of sdate_dim of 'data' must be 1.") } # ftime_dim - if (!is.character(ftime_dim) | length(ftime_dim) > 1) { + if (!is.character(ftime_dim) || length(ftime_dim) > 1) { stop("Parameter 'ftime_dim' must be a character string.") } if (!ftime_dim %in% names(dim(data))) { @@ -111,7 +111,7 @@ Histo2Hindcast <- function(data, sdatesin, sdatesout, nleadtimesout, } # ncores if (!is.null(ncores)) { - if (!is.numeric(ncores) | ncores %% 1 != 0 | ncores <= 0 | + if (!is.numeric(ncores) || ncores %% 1 != 0 || ncores <= 0 | length(ncores) > 1) { stop("Parameter 'ncores' must be a positive integer.") } diff --git a/R/ProbBins.R b/R/ProbBins.R index 327ceb34fafb48b6425373536e2b1bf7d70041dc..ef293d94710fa7d70bbb3a8984a25898ddc68f72 100644 --- a/R/ProbBins.R +++ b/R/ProbBins.R @@ -100,7 +100,7 @@ ProbBins <- function(data, thr, fcyr = 'all', time_dim = 'sdate', memb_dim = 'me stop("Parameter 'memb_dim' is not found in 'data' dimension.") } ## fcyr - if (fcyr != 'all') { + if (!identical(fcyr, 'all')) { if (!is.numeric(fcyr) | !is.vector(fcyr)) { stop("Parameter 'fcyr' must be a numeric vector or 'all'.") } else if (any(fcyr %% 1 != 0) | min(fcyr) < 1 | max(fcyr) > dim(data)[time_dim]) { diff --git a/R/REOF.R b/R/REOF.R index c9c82cf94e1091f88ea7a8c71dd2957e5079de80..2def222614b84ff7f15a772eb5092ff22691b6ce 100644 --- a/R/REOF.R +++ b/R/REOF.R @@ -146,9 +146,9 @@ REOF <- function(ano, lat, lon, ntrunc = 15, time_dim = 'sdate', # ntrunc is bounded if (ntrunc != min(dim(ano)[time_dim], prod(dim(ano)[space_dim]), ntrunc)) { ntrunc <- min(dim(ano)[time_dim], prod(dim(ano)[space_dim]), ntrunc) - .warning(paste0("Parameter 'ntrunc' is changed to ", ntrunc, ", the minimum among ", - "the length of time_dim, the production of the length of space_dim, ", - "and ntrunc.")) + warning(paste0("Parameter 'ntrunc' is changed to ", ntrunc, ", the minimum among ", + "the length of time_dim, the production of the length of space_dim, ", + "and ntrunc.")) } # Area weighting is needed to compute the fraction of variance explained by diff --git a/R/RatioPredictableComponents.R b/R/RatioPredictableComponents.R index 270420ab272bc392caff74494c46f244844e2db2..163d18fcdbd10524d24b6111a7b759527e5f611f 100644 --- a/R/RatioPredictableComponents.R +++ b/R/RatioPredictableComponents.R @@ -23,13 +23,10 @@ #'obs <- array(data = runif(60), dim = c(year = 15, lat = 2, lon = 2)) #'RatioPredictableComponents(exp, obs) #' -#'@import multiApply +#'@import multiApply stats #'@export RatioPredictableComponents <- function(exp, obs, time_dim = 'year', member_dim = 'member', na.rm = FALSE, ncores = NULL) { - C_cor <- stats:::C_cor - C_cov <- stats:::C_cov - ## Checkings if (is.null(exp)) { stop("Parameter 'exp' cannot be NULL.") diff --git a/R/RatioSDRMS.R b/R/RatioSDRMS.R index 85313030dfd0bedaeb7b78c44423dbfb559c45dc..544ca6f8db3b6f85c73788fdecd5caa9c8557586 100644 --- a/R/RatioSDRMS.R +++ b/R/RatioSDRMS.R @@ -182,7 +182,7 @@ RatioSDRMS <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', if (pval) { F <- (enosd[jexp] * std[jexp]^2 / (enosd[jexp] - 1)) / (enorms * rms^2 / (enorms - 1)) - if (!is.na(F) & !is.na(enosd[jexp]) & !is.na(enorms) & enosd > 2 & enorms > 2) { + if (!is.na(F) & !is.na(enosd[jexp]) & !is.na(enorms) & any(enosd > 2) & enorms > 2) { p.val[jexp, jobs] <- 1 - pf(F, enosd[jexp] - 1, enorms - 1) } else { ratiosdrms[jexp, jobs] <- NA diff --git a/R/SignalNoiseRatio.R b/R/SignalNoiseRatio.R index a8f235637fd074990f0c573def1ee686ededc99b..18dccf407a52c7eb3c7d6e193edf0fe2d1e470b5 100644 --- a/R/SignalNoiseRatio.R +++ b/R/SignalNoiseRatio.R @@ -23,6 +23,7 @@ #' SignalNoiseRatio(exp) #' #'@import multiApply +#'@importFrom stats var #'@export SignalNoiseRatio <- function(data, time_dim = 'year', member_dim = 'member', na.rm = FALSE, ncores = NULL) { @@ -71,9 +72,9 @@ SignalNoiseRatio <- function(data, time_dim = 'year', member_dim = 'member', na. ens_spread <- apply(data, 2, "-", ens_mean) ## Ensemble mean variance -> signal - var_signal <- var(ens_mean, na.rm = na.rm) + var_signal <- stats::var(ens_mean, na.rm = na.rm) ## Variance of ensemble members about ensemble mean (= spread) -> noise - var_noise <- var(as.vector(ens_spread), na.rm = na.rm) + var_noise <- stats::var(as.vector(ens_spread), na.rm = na.rm) ## Signal to noise ratio SNR <- var_signal / var_noise diff --git a/R/Spread.R b/R/Spread.R index 9f1624a3f34934b4de61e1523044c20ab7db28af..d1d8f6d159bceab7781f9d131ad47589381ed708 100644 --- a/R/Spread.R +++ b/R/Spread.R @@ -114,12 +114,12 @@ Spread <- function(data, compute_dim = 'member', na.rm = TRUE, stop("Parameter 'conf' must be one logical value.") } ## conf.lev - if (!is.numeric(conf.lev) | conf.lev < 0 | conf.lev > 1 | length(conf.lev) > 1) { + if (!is.numeric(conf.lev) | any(conf.lev < 0) | any(conf.lev > 1) | length(conf.lev) > 1) { stop("Parameter 'conf.lev' must be a numeric number between 0 and 1.") } ## ncores if (!is.null(ncores)) { - if (!is.numeric(ncores) | ncores %% 1 != 0 | ncores <= 0 | + if (!is.numeric(ncores) | any(ncores %% 1 != 0) | any(ncores <= 0) | length(ncores) > 1) { stop("Parameter 'ncores' must be a positive integer.") } diff --git a/s2dv-manual.pdf b/s2dv-manual.pdf index de5dc4cb860f84e21a44781861245233d13c7fdf..b6faa89fbc92c8735e85d4fa7bc4d0f68d47030b 100644 Binary files a/s2dv-manual.pdf and b/s2dv-manual.pdf differ diff --git a/tests/testthat/test-Cluster.R b/tests/testthat/test-Cluster.R index 9071cd8e5e479e0ef2ccee2b6b74208815e604c8..4e0a7b171d25ec559afbef8b97dafb45e87cff6e 100644 --- a/tests/testthat/test-Cluster.R +++ b/tests/testthat/test-Cluster.R @@ -61,17 +61,17 @@ test_that("1. Input checks", { ) # nclusters expect_error( - Cluster(dat1, weights1, ncluster = 1), + Cluster(dat1, weights1, ncluster = 1, space_dim = 'space'), "Parameter 'nclusters' must be an integer bigger than 1." ) # index expect_error( - Cluster(dat1, weights1, index = 1), + Cluster(dat1, weights1, index = 1, space_dim = 'space'), "Parameter 'index' should be a character strings accepted as 'index' by the function NbClust::NbClust." ) # ncores expect_error( - Cluster(dat1, weights1, ncore = 0), + Cluster(dat1, weights1, ncore = 0, space_dim = 'space'), "Parameter 'ncores' must be a positive integer." ) }) @@ -80,7 +80,7 @@ test_that("1. Input checks", { test_that("2. Output checks: dat1", { # The output is random. Only check dimensions. expect_equal( - length(Cluster(dat1, weights1)$cluster), + length(Cluster(dat1, weights1, space_dim = 'space')$cluster), 50 ) expect_equal( @@ -88,11 +88,11 @@ test_that("2. Output checks: dat1", { 100 ) expect_equal( - dim(Cluster(dat1, weights1)$centers), + dim(Cluster(dat1, weights1, space_dim = 'space')$centers), c(8, 2) ) expect_equal( - dim(Cluster(dat1, weights1, nclusters = 3)$centers), + dim(Cluster(dat1, weights1, nclusters = 3, space_dim = 'space')$centers), c(3, 2) ) @@ -103,7 +103,7 @@ test_that("2. Output checks: dat1", { test_that("3. Output checks: dat2", { expect_equal( - length(Cluster(dat2, weights2)$cluster), + length(Cluster(dat2, weights2, space_dim = c('lat', 'lon'))$cluster), 50 ) expect_equal( @@ -115,11 +115,11 @@ test_that("3. Output checks: dat2", { 50 ) expect_equal( - dim(Cluster(dat2, weights2)$centers), + dim(Cluster(dat2, weights2, space_dim = c('lat', 'lon'))$centers), c(7, 6) ) expect_equal( - dim(Cluster(dat2, weights2, nclusters = 5)$centers), + dim(Cluster(dat2, weights2, nclusters = 5, space_dim = c('lat', 'lon'))$centers), c(5, 6) ) diff --git a/tests/testthat/test-Consist_Trend.R b/tests/testthat/test-Consist_Trend.R index 2dd2214a8ea31e851fae8564921c66266d54342c..aa66f45761c6aa6b8bca1f02d7fbf8649882b038 100644 --- a/tests/testthat/test-Consist_Trend.R +++ b/tests/testthat/test-Consist_Trend.R @@ -151,8 +151,10 @@ c(NA, -0.4826962, 1.2716524, -1.0952163, 0.3062600), tolerance = 0.0001 ) expect_equal( -mean(Consist_Trend(exp2, obs2)$detrended_obs, na.rm = TRUE)*10^18, -2.118364, +as.vector(Consist_Trend(exp2, obs2)$detrended_obs), +c(NA, -0.4826962, 1.2716524, -1.0952163, 0.3062600, -0.2100316, 0.2920924, + -0.7289708, 1.4217907, -0.7748807, 0.6108713, NA, -0.5417854, -1.3599143, + 1.2908284), tolerance = 0.0001 ) expect_equal( diff --git a/tests/testthat/test-EOF.R b/tests/testthat/test-EOF.R index 7966518dec3472f37d267f36c9a9589ac089c43d..01428e6eb73bd736c9ca7b7b6c5da83fa6c4f678 100644 --- a/tests/testthat/test-EOF.R +++ b/tests/testthat/test-EOF.R @@ -205,20 +205,20 @@ test_that("2. dat1", { ############################################## test_that("3. dat2", { expect_equal( - dim(EOF(dat2, lon = lon2, lat = lat2)$EOFs), + dim(EOF(dat2, lon = lon2, lat = lat2, neofs = 12)$EOFs), c(mode = 12, lat = 6, lon = 2) ) expect_equal( - dim(EOF(dat2, lon = lon2, lat = lat2)$PCs), + dim(EOF(dat2, lon = lon2, lat = lat2, neofs = 12)$PCs), c(sdate = 20, mode = 12) ) expect_equal( - EOF(dat2, lon = lon2, lat = lat2)$EOFs[1:5], + EOF(dat2, lon = lon2, lat = lat2, neofs = 12)$EOFs[1:5], c(0.33197201, 0.18837900, -0.19697143, 0.08305805, -0.51297585), tolerance = 0.0001 ) expect_equal( - mean(EOF(dat2, lon = lon2, lat = lat2)$EOFs), + mean(EOF(dat2, lon = lon2, lat = lat2, neofs = 12)$EOFs), 0.02720393, tolerance = 0.0001 ) @@ -228,37 +228,37 @@ test_that("3. dat2", { ############################################## test_that("4. dat3", { expect_equal( - dim(EOF(dat3, lon = lon3, lat = lat3)$EOFs), + dim(EOF(dat3, lon = lon3, lat = lat3, neofs = 12)$EOFs), c(mode = 12, lat = 6, lon = 2, dat = 2) ) expect_equal( - dim(EOF(dat3, lon = lon3, lat = lat3)$PCs), + dim(EOF(dat3, lon = lon3, lat = lat3, neofs = 12)$PCs), c(sdate = 20, mode = 12, dat = 2) ) expect_equal( - dim(EOF(dat3, lon = lon3, lat = lat3)$var), + dim(EOF(dat3, lon = lon3, lat = lat3, neofs = 12)$var), c(mode = 12, dat = 2) ) expect_equal( - dim(EOF(dat3, lon = lon3, lat = lat3)$mask), + dim(EOF(dat3, lon = lon3, lat = lat3, neofs = 12)$mask), c(lat = 6, lon = 2, dat = 2) ) expect_equal( - dim(EOF(dat3, lon = lon3, lat = lat3)$wght), + dim(EOF(dat3, lon = lon3, lat = lat3, neofs = 12)$wght), c(lat = 6, lon = 2) ) expect_equal( - mean(EOF(dat3, lon = lon3, lat = lat3)$EOFs), + mean(EOF(dat3, lon = lon3, lat = lat3, neofs = 12)$EOFs), 0.01214845, tolerance = 0.0001 ) expect_equal( - EOF(dat3, lon = lon3, lat = lat3)$EOFs[1:5], + EOF(dat3, lon = lon3, lat = lat3, neofs = 12)$EOFs[1:5], c(0.3292733, 0.1787016, -0.3801986, 0.1957160, -0.4377031), tolerance = 0.0001 ) expect_equal( - EOF(dat3, lon = lon3, lat = lat3)$tot_var, + EOF(dat3, lon = lon3, lat = lat3, neofs = 12)$tot_var, array(c(213.2422, 224.4203), dim = c(dat = 2)), tolerance = 0.0001 ) diff --git a/tests/testthat/test-InsertDim.R b/tests/testthat/test-InsertDim.R index f3cfab801f33fd29e44e805ae65d6f8c52d9dad7..876e7e36c2e0c74f0a4a2017d35f4857e2109816 100644 --- a/tests/testthat/test-InsertDim.R +++ b/tests/testthat/test-InsertDim.R @@ -56,20 +56,24 @@ test_that("1. Input checks", { ############################################## test_that("2. Output checks: dat1", { + expect_warning( + InsertDim(dat1, posdim = 1, lendim = 2), + "The name of new dimension is not given. Set the name as 'new'." + ) expect_equal( - dim(InsertDim(dat1, posdim = 1, lendim = 2)), + dim(InsertDim(dat1, posdim = 1, lendim = 2, name = 'new')), dim(array(dim = c(new = 2, dat = 1, sdate = 13, ftime = 2))) ) expect_equal( - dim(InsertDim(dat1, posdim = 3, lendim = c(d = 2))), + dim(InsertDim(dat1, posdim = 3, lendim = 2, name = 'd')), c(dat = 1, sdate = 13, d = 2, ftime = 2) ) expect_equal( - as.vector(InsertDim(dat1, posdim = 1, lendim = 2)[1,,,]), + as.vector(InsertDim(dat1, posdim = 1, lendim = 2, name = 'd')[1,,,]), as.vector(dat1) ) expect_equal( - as.vector(InsertDim(dat1, posdim = 1, lendim = 2)[2,,,]), + as.vector(InsertDim(dat1, posdim = 1, lendim = 2, name = 'd')[2,,,]), as.vector(dat1) ) @@ -84,13 +88,13 @@ test_that("3. Output checks: dat2", { ) expect_equal( - as.vector(InsertDim(dat2, posdim = 3, lendim = 1)[,,1,]), + as.vector(InsertDim(dat2, posdim = 3, lendim = 1, name = 'd')[,,1,]), as.vector(dat2) ) expect_equal( - dim(InsertDim(InsertDim(dat2, posdim = 4, lendim = 2), posdim = 1, lendim = 4)), - dim(array(dim = c(new = 4, 2, 3, c = 4, new = 2))) + dim(InsertDim(InsertDim(dat2, posdim = 4, lendim = 2, name = 'd'), posdim = 1, lendim = 4, name = 'e')), + dim(array(dim = c(e = 4, 2, 3, c = 4, d = 2))) ) }) diff --git a/tests/testthat/test-REOF.R b/tests/testthat/test-REOF.R index 9f4bb480a5dc5bb3de121041fa9f72afe1cea72c..e118e1eac8284161c18fabdeee51c4ccf827101a 100644 --- a/tests/testthat/test-REOF.R +++ b/tests/testthat/test-REOF.R @@ -92,13 +92,17 @@ test_that("1. Input checks", { ############################################## test_that("2. dat1", { - + expect_warning( + REOF(dat1, lon = lon1, lat = lat1), + "Parameter 'ntrunc' is changed to 10, the minimum among the length of time_dim, the production of the length of space_dim, and ntrunc.", + fixed = TRUE + ) expect_equal( - names(REOF(dat1, lon = lon1, lat = lat1, ntrunc = 5)), + names(REOF(dat1, lon = lon1, lat = lat1, ntrunc = 10)), c("REOFs", "RPCs", "var", "wght") ) expect_equal( - dim(REOF(dat1, lon = lon1, lat = lat1)$REOFs), + dim(REOF(dat1, lon = lon1, lat = lat1, ntrunc = 10)$REOFs), c(mode = 10, lat = 6, lon = 2) ) expect_equal( @@ -147,7 +151,7 @@ test_that("2. dat1", { ############################################## test_that("3. dat2", { expect_equal( - dim(REOF(dat2, lon = lon2, lat = lat2)$REOFs), + dim(REOF(dat2, lon = lon2, lat = lat2, ntrunc = 5)$REOFs), c(mode = 5, lat = 6, lon = 2, dat = 2) ) expect_equal( @@ -164,7 +168,7 @@ test_that("3. dat2", { tolerance = 0.0001 ) expect_equal( - mean(REOF(dat2, lon = lon2, lat = lat2)$REOFs), + mean(REOF(dat2, lon = lon2, lat = lat2, ntrunc = 5)$REOFs), 0.01120786, tolerance = 0.0001 )