From 8ef0f0def6387d405c8f581a1b2f1c5f6914966c Mon Sep 17 00:00:00 2001
From: Dorchies David <david.dorchies@irstea.fr>
Date: Sat, 9 Jan 2021 18:05:36 +0100
Subject: [PATCH] fix: Single ConvertFun argument for list

- ConvertFun for InputsModel and OutputsModel are entirely defined into SeriesAggreg.list
- otherwise SeriesAggreg.list only accept a single ConvertFun to apply to all elements and sub-elements of the list

Refs #82
---
 R/SeriesAggreg.InputsModel.R       |  2 +-
 R/SeriesAggreg.OutputsModel.R      |  2 +-
 R/SeriesAggreg.list.R              | 58 ++++++++++++++++++++----------
 man/SeriesAggreg.Rd                |  2 +-
 tests/testthat/test-SeriesAggreg.R |  5 ++-
 5 files changed, 47 insertions(+), 22 deletions(-)

diff --git a/R/SeriesAggreg.InputsModel.R b/R/SeriesAggreg.InputsModel.R
index 4a62b4ec..37513f46 100644
--- a/R/SeriesAggreg.InputsModel.R
+++ b/R/SeriesAggreg.InputsModel.R
@@ -1,7 +1,7 @@
 SeriesAggreg.InputsModel <- function(x, Format, ...) {
   SeriesAggreg.list(x,
                     Format,
-                    ConvertFun = .GetAggregConvertFun(names(x), Format),
+                    ConvertFun = NA,
                     except = c("ZLayers", "LengthHydro", "BasinAreas"),
                     ...)
 }
diff --git a/R/SeriesAggreg.OutputsModel.R b/R/SeriesAggreg.OutputsModel.R
index 27eb2ff3..3bf0d8ae 100644
--- a/R/SeriesAggreg.OutputsModel.R
+++ b/R/SeriesAggreg.OutputsModel.R
@@ -1,7 +1,7 @@
 SeriesAggreg.OutputsModel <- function(x, Format, ...) {
   SeriesAggreg.list(x,
                     Format,
-                    ConvertFun = .GetAggregConvertFun(names(x), Format),
+                    ConvertFun = NA,
                     except = "StateEnd",
                     ...)
 }
diff --git a/R/SeriesAggreg.list.R b/R/SeriesAggreg.list.R
index 299bce02..c9117e92 100644
--- a/R/SeriesAggreg.list.R
+++ b/R/SeriesAggreg.list.R
@@ -12,6 +12,16 @@ SeriesAggreg.list <- function(x,
     warning("deprecated 'NewTimeFormat' argument: 'Format' argument is used instead",
             call. = FALSE)
   }
+  # Check ConvertFun
+  if (any(class(x) %in% c("InputsModel", "OutputsModel"))) {
+    if (!all(is.na(ConvertFun))) {
+      warning("Argument 'ConvertFun' is ignored on 'InputsModel' and 'OutputsModel' objects")
+    }
+  } else if (length(ConvertFun)!=1) {
+    stop("Argument 'ConvertFun' must be of length 1 with 'list' object")
+  } else if (!is.character(ConvertFun)) {
+    stop("Argument 'ConvertFun' must be a character")
+  }
 
   # Determination of DatesR
   if (!is.null(x$DatesR)) {
@@ -59,13 +69,11 @@ SeriesAggreg.list <- function(x,
   }
   dfOut <- NULL
   if (length(cols)) {
-    ConvertFun2 <- .GetAggregConvertFun(names(cols), Format)
-    if (is.null(recursive)) {
-      if (missing(ConvertFun)) {
-        stop("'ConvertFun' argument should provided if 'recursive = NULL'")
-      } else if (!is.na(ConvertFun)) {
-        ConvertFun2 <- rep(ConvertFun, length(cols))
-      }
+    # Treating aggregation at root level
+    if (is.na(ConvertFun)) {
+      ConvertFun2 <- .GetAggregConvertFun(names(cols), Format)
+    } else {
+      ConvertFun2 <- rep(ConvertFun, length(cols))
     }
     dfOut <- SeriesAggreg(cbind(DatesR, as.data.frame(cols)),
                           Format,
@@ -93,17 +101,27 @@ SeriesAggreg.list <- function(x,
       dfCols <- c(dfCols, x[sapply(x, inherits, "matrix")])
       listCols <- listCols[setdiff(names(listCols), names(dfCols))]
       if (length(listCols) > 0) {
-        # Check for predefined ConvertFun for all sub-elements
-        ConvertFun <- .GetAggregConvertFun(names(listCols), Format)
+        if (is.na(ConvertFun)) {
+          # Check for predefined ConvertFun for all sub-elements
+          listConvertFun <- .GetAggregConvertFun(names(listCols), Format)
+        } else {
+          listConvert
+        }
         # Run SeriesAggreg for each embedded list
-        listRes <- lapply(names(listCols), function(x) {
-          listCols[[x]]$DatesR <- DatesR
-          SeriesAggreg(listCols[[x]],
+        listRes <- lapply(names(listCols), function(y) {
+          listCols[[y]]$DatesR <- DatesR
+          if (is.na(ConvertFun)) {
+            SeriesAggreg.list(listCols[[y]],
                        Format = Format,
-                       except = except,
-                       ConvertFun = ConvertFun[x],
                        recursive = NULL,
-                       ...)
+                       ...,
+                       ConvertFun = listConvertFun[y])
+          } else {
+            SeriesAggreg.list(listCols[[y]],
+                              Format = Format,
+                              recursive = NULL,
+                              ...)
+          }
         })
         names(listRes) <- names(listCols)
         if (is.null(res$DatesR)) {
@@ -129,10 +147,14 @@ SeriesAggreg.list <- function(x,
               "), it will be ignored in the aggregation"
             )
           } else {
-            ConvertFun <- rep(.GetAggregConvertFun(key, Format), ncol(m))
-            res[[key]] <- SeriesAggreg(data.frame(DatesR, m),
+            if (is.na(ConvertFun)) {
+              ConvertFun2 <- rep(.GetAggregConvertFun(key, Format), ncol(m))
+            } else {
+              ConvertFun2 <- rep(ConvertFun, ncol(m))
+            }
+            res[[key]] <- SeriesAggreg.data.frame(data.frame(DatesR, m),
                                        Format = Format,
-                                       ConvertFun = ConvertFun)
+                                       ConvertFun = ConvertFun2)
           }
         }
       }
diff --git a/man/SeriesAggreg.Rd b/man/SeriesAggreg.Rd
index aa7e67fd..c402a5eb 100644
--- a/man/SeriesAggreg.Rd
+++ b/man/SeriesAggreg.Rd
@@ -62,7 +62,7 @@ Warning: on the aggregated outputs, the dates correspond to the beginning of the
 
 \item{NewTimeFormat}{(deprecated) [character] output time step format (i.e. \code{"hourly"}, \code{"daily"}, \code{"monthly"} or \code{"yearly"}). Use the \code{Format} argument instead}
 
-\item{ConvertFun}{[character] names of aggregation functions (e.g. for P[mm], T[degC], Q[mm]: \code{ConvertFun = c("sum", "mean", "sum"})) (default: use the name of the column (see details) or \code{"mean"} for regime calculation)}
+\item{ConvertFun}{[character] names of aggregation functions (e.g. for P[mm], T[degC], Q[mm]: \code{ConvertFun = c("sum", "mean", "sum"})) or name of aggregation function to apply to all elements if the parameter 'x' is a [list]}
 
 \item{YearFirstMonth}{(optional) [numeric] integer used when \code{Format = "\%Y"} to set when the starting month of the year (e.g. 01 for calendar year or 09 for hydrological year starting in September)}
 
diff --git a/tests/testthat/test-SeriesAggreg.R b/tests/testthat/test-SeriesAggreg.R
index 7ec93199..4d4d4907 100644
--- a/tests/testthat/test-SeriesAggreg.R
+++ b/tests/testthat/test-SeriesAggreg.R
@@ -90,7 +90,10 @@ test_that("No DatesR should warning", {
     E = BasinObs$E,
     Qmm = BasinObs$Qmm
   )
-  expect_warning(SeriesAggreg(TabSeries, "%Y%m"), regexp = "has been automatically chosen")
+  expect_warning(
+    SeriesAggreg(TabSeries, "%Y%m", ConvertFun = "sum"),
+    regexp = "has been automatically chosen"
+  )
 })
 
 test_that("Check SeriesAggreg.list 'DatesR' argument", {
-- 
GitLab