From d4f4a873a48fe087518e84954c61001eaf49e107 Mon Sep 17 00:00:00 2001
From: Delaigue Olivier <olivier.delaigue@irstea.priv>
Date: Wed, 17 Apr 2019 18:32:01 +0200
Subject: [PATCH] v1.2.14.14 NEW: box-cox transformation allowed in
 CreateInputsCrit and computed in .ErrorCrit

---
 DESCRIPTION             |  2 +-
 NEWS.rmd                |  6 +++---
 R/CreateInputsCrit.R    |  2 +-
 R/Utils.R               |  6 +++++-
 man/CreateInputsCrit.Rd | 10 ++++++----
 5 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
index f90d79b5..67dd2c65 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,7 +1,7 @@
 Package: airGR
 Type: Package
 Title: Suite of GR Hydrological Models for Precipitation-Runoff Modelling
-Version: 1.2.14.12
+Version: 1.2.14.14
 Date: 2019-04-17
 Authors@R: c(
   person("Laurent", "Coron", role = c("aut", "trl"), comment = c(ORCID = "0000-0002-1503-6204")),
diff --git a/NEWS.rmd b/NEWS.rmd
index a977e3be..af184484 100644
--- a/NEWS.rmd
+++ b/NEWS.rmd
@@ -14,17 +14,17 @@ output:
 
 
 
-### 1.2.14.12 Release Notes (2019-04-17)
+### 1.2.14.14 Release Notes (2019-04-17)
 
 
 #### New features
 
-- <code>CreateInputsCrit()</code> now allows power transformation (as numeric or character values) in the <code>transfo</code> argument.
+- <code>CreateInputsCrit()</code> now allows power (as numeric or character values) and the Box-Cox transformations in the <code>transfo</code> argument.
 
 
 #### Minor user-visible changes
 
-- <code>.ErrorCrit()</code> private function added to check inputs into <code>ErrorCrit_&#42;()</code> functions.
+- <code>.ErrorCrit()</code> private function added to check inputs into <code>ErrorCrit_&#42;()</code> functions. The <code>ErrorCrit_&#42;()</code> functions were simplified accordingly.
 
 ____________________________________________________________________________________
 
diff --git a/R/CreateInputsCrit.R b/R/CreateInputsCrit.R
index 33a20e1f..365679f9 100644
--- a/R/CreateInputsCrit.R
+++ b/R/CreateInputsCrit.R
@@ -157,7 +157,7 @@ CreateInputsCrit <- function(FUN_CRIT,
   inVarObs  <- c("Q", "SCA", "SWE")
   msgVarObs <- "'VarObs' must be a (list of) character vector(s) and one of %s"
   msgVarObs <- sprintf(msgVarObs, paste(sapply(inVarObs, shQuote), collapse = ", "))
-  inTransfo  <- c("", "sqrt", "log", "inv", "sort") # pow is not checked by inTransfo, but appears in the warning message and checkef after (see ## check 'transfo')
+  inTransfo  <- c("", "sqrt", "log", "inv", "sort", "boxcox") # pow is not checked by inTransfo, but appears in the warning message and checkef after (see ## check 'transfo')
   msgTransfo <- "'transfo' must be a (list of) character vector(s) and one of %s, or numeric value for power transformation"
   msgTransfo <- sprintf(msgTransfo, paste(sapply(inTransfo, shQuote), collapse = ", "))
   
diff --git a/R/Utils.R b/R/Utils.R
index 268074a5..bce34322 100644
--- a/R/Utils.R
+++ b/R/Utils.R
@@ -102,7 +102,7 @@
   if (InputsCrit$transfo == "") {
     CritName <- paste0(Crit, "[CritVar]")
   }
-  if (InputsCrit$transfo %in% c("sqrt", "log", "sort")) {
+  if (InputsCrit$transfo %in% c("sqrt", "log", "sort", "boxcox")) {
     CritName <- paste0(Crit, "[", InputsCrit$transfo, "(CritVar)]")
   }
   if (InputsCrit$transfo == "inv") {
@@ -172,6 +172,10 @@
     VarObs <- sort(VarObs, na.last = TRUE)
     InputsCrit$BoolCrit <-  sort(InputsCrit$BoolCrit, decreasing = TRUE)
   }
+  if (InputsCrit$transfo == "boxcox") {
+    VarSim <- (VarSim^0.25 - 0.01 * mean(VarSim, na.rm = TRUE)) / 0.25
+    VarObs <- (VarObs^0.25 - 0.01 * mean(VarObs, na.rm = TRUE)) / 0.25
+  }
   if (grepl("\\^", InputsCrit$transfo)) {
     VarObs <- VarObs^transfoPow
     VarSim <- VarSim^transfoPow
diff --git a/man/CreateInputsCrit.Rd b/man/CreateInputsCrit.Rd
index ac1f8498..cbfb7e09 100644
--- a/man/CreateInputsCrit.Rd
+++ b/man/CreateInputsCrit.Rd
@@ -32,7 +32,7 @@ CreateInputsCrit(FUN_CRIT, InputsModel, RunOptions,
 
 \item{BoolCrit}{(optional) [boolean (atomic or list)] boolean (the same length as \code{Obs}) giving the time steps to consider in the computation (all time steps are considered by default)}
 
-\item{transfo}{(optional) [character (atomic or list)] name of the transformation (e.g. \code{""}, \code{"sqrt"}, \code{"log"}, \code{"inv"}, \code{"sort"} or numeric value for power transformation (see details))}
+\item{transfo}{(optional) [character (atomic or list)] name of the transformation (e.g. \code{""}, \code{"sqrt"}, \code{"log"}, \code{"inv"}, \code{"sort"}, \code{"boxcox"} or a numeric value for power transformation (see details))}
 
 \item{Weights}{(optional) [numeric (atomic or list)] vector of weights necessary to calculate a composite criterion (the same length as \code{FUN_CRIT}) giving the weights to use for elements of \code{FUN_CRIT} [-]. See details}
 
@@ -53,7 +53,7 @@ CreateInputsCrit(FUN_CRIT, InputsModel, RunOptions,
     \emph{$Obs       } \tab [numeric] series of observed variable(s) ([mm/time step] for discharge or SWE, [-] for SCA) \cr
     \emph{$VarObs    } \tab [character] names of the observed variable(s) \cr
     \emph{$BoolCrit  } \tab [boolean] boolean giving the time steps considered in the computation \cr
-    \emph{$transfo   } \tab [character] name of the transformation (e.g. \code{""}, \code{"sqrt"}, \code{"log"}, \code{"inv"}, \code{"sort"}) \cr
+    \emph{$transfo   } \tab [character] name of the transformation (e.g. \code{""}, \code{"sqrt"}, \code{"log"}, \code{"inv"}, \code{"sort"}, \code{"boxcox"} or a number for power transformation) \cr
     \emph{$epsilon   } \tab [numeric] small value to add to all observations and simulations when \code{"log"} or \code{"inv"} transformations are used [same unit as \code{Obs}] \cr
     \emph{$Weights   } \tab [numeric] vector (same length as \code{VarObs}) giving the weights to use for elements of \code{FUN_CRIT} [-] \cr
   }
@@ -72,14 +72,16 @@ Creation of the \code{InputsCrit} object required to the \code{ErrorCrit_*} func
 
 \details{
 Users wanting to use \code{FUN_CRIT} functions that are not included in the package must create their own InputsCrit object accordingly. \cr \cr
-The syntax of the power transformation can be written in numerical form or as a string of characters, for example for a square: \code{transfo = 2}, \code{"2"} or \code{"^2"}.
+The syntax of the power transformation allows a numeric or a string of characters. For example for a squared transformation, the following can be used: \code{transfo = 2}, \code{transfo = "2"} or \code{transfo = "^2"}. Negative values are allowed. Fraction values are not allowed (e.g., \code{"-1/2"} must instead be written \code{"-0.5"}).
+\cr \cr
+In order to make sure that KGE and KGE2 remain dimensionless and not impacted by zero values, the Box-Cox transformation (\code{transfo = "boxcox"}) uses the formulation given in Equation 10 of Santos et al. (2018). Lambda is set to 0.25 accordingly. 
 \cr \cr
 The epsilon value is useful when \code{"log"} or \code{"inv"} transformations are used (to avoid calculation of the inverse or of the logarithm of zero). The impact of this value and a recommendation about the epsilon value to use (usually one hundredth of average observation) are discussed in Pushpalatha et al. (2012) for NSE and in Santos et al. (2018) for KGE and KGE'. \cr \cr
 We do not advise computing KGE or KGE' with log-transformation as it might be wrongly influenced by discharge values close to 0 or 1 and the criterion value is dependent on the discharge unit. See Santos et al. (2018) for more details and alternative solutions (see the references list below). \cr \cr
 Users can set the following arguments as atomic or list: \code{FUN_CRIT}, \code{Obs}, \code{VarObs}, \code{BoolCrit}, \code{transfo}, \code{Weights}. If the list format is chosen, all the lists must have the same length. \cr
 Calculation of a single criterion (e.g. NSE computed on discharge) is prepared by providing to \code{CreateInputsCrit} arguments atomics only. \cr
 Calculation of multiple criteria (e.g. NSE computed on discharge and RMSE computed on discharge) is prepared by providing to \code{CreateInputsCrit} arguments lists except for \code{Weights} that must be set as \code{NULL}. \cr
-Calculation of a composite criterion (e.g. the average between NSE computed on dscharge and NSE computed on log of discharge) is prepared by providing to \code{CreateInputsCrit} arguments lists including \code{Weights}. \cr
+Calculation of a composite criterion (e.g. the average between NSE computed on discharge and NSE computed on log of discharge) is prepared by providing to \code{CreateInputsCrit} arguments lists including \code{Weights}. \cr
 \code{\link{ErrorCrit_RMSE}} cannot be used in a composite criterion since it is not a unitless value.
 }
 
-- 
GitLab