Newer
Older
Delaigue Olivier
committed
CreateInputsCrit <- function(FUN_CRIT,
InputsModel,
RunOptions,
Qobs,
Delaigue Olivier
committed
obs,
varObs = "Qobs",
Delaigue Olivier
committed
BoolCrit = NULL,
transfo = "",
Delaigue Olivier
committed
# groupLayer,
weights = NULL,
Delaigue Olivier
committed
Ind_zeroes = NULL,
epsilon = NULL,
Delaigue Olivier
committed
warnings = TRUE,
Delaigue Olivier
committed
verbose = TRUE) {
ObjectClass <- NULL
Delaigue Olivier
committed
## ---------- check arguments
Delaigue Olivier
committed
Delaigue Olivier
committed
if (!missing(Qobs)) {
if (missing(obs)) {
if (warnings) {
warning("argument 'Qobs' is deprecated. Please use 'obs' and 'varObs' instead")
}
obs <- Qobs
# varObs <- "Qobs"
} else {
warning("argument 'Qobs' is deprecated. The values set in 'obs' will be used instead")
Delaigue Olivier
committed
}
if (!missing(Ind_zeroes) & warnings) {
warning("Deprecated 'Ind_zeroes' argument")
}
if (!missing(verbose)) {
warning("Deprecated 'verbose' argument. Use 'warnings', instead")
}
## create list of arguments
listArgs <- list(FUN_CRIT = FUN_CRIT,
obs = obs,
varObs = varObs,
BoolCrit = BoolCrit,
transfo = transfo,
# groupLayer = groupLayer,
weights = weights,
epsilon = epsilon)
## check lists lengths
for (iArgs in names(listArgs)) {
if (iArgs %in% c("weights", "BoolCrit", "epsilon")) {
if (any(is.null(listArgs[[iArgs]]))) {
listArgs[[iArgs]] <- lapply(seq_along(listArgs$FUN_CRIT), function(x) NULL)
}
Delaigue Olivier
committed
if (!is.list(listArgs[[iArgs]])) {
listArgs[[iArgs]] <- list(listArgs[[iArgs]])
Delaigue Olivier
committed
}
## check 'varObs'
if (missing(varObs)) {
listArgs$varObs <- as.list(rep("Qobs", times = length(listArgs$obs)))
if (warnings) {
warning("'varObs' automatically set to \"Qobs\"")
Delaigue Olivier
committed
}
## check 'transfo'
if (missing(transfo)) {
listArgs$transfo <- as.list(rep("", times = length(listArgs$obs)))
if (warnings) {
warning("'transfo' automatically set to \"\"")
Delaigue Olivier
committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
}
## check length of each args
if (length(unique(sapply(listArgs, FUN = length))) != 1) {
stopListArgs <- paste(sapply(names(listArgs), shQuote), collapse = ", ")
stop(sprintf("arguments %s must have the same length", stopListArgs))
}
## check "InputsModel"
if (!inherits(InputsModel, "InputsModel")) {
stop("'InputsModel' must be of class 'InputsModel' \n")
return(NULL)
}
## check 'RunOptions'
if (!inherits(RunOptions , "RunOptions")) {
stop("'RunOptions' must be of class 'RunOptions' \n")
return(NULL)
}
## check 'weights'
if (length(listArgs$weights) > 1 & sum(unlist(listArgs$weights)) == 0 & !any(sapply(listArgs$weights, is.null))) {
stop("sum of 'weights' cannot be equal to zero \n")
}
## reformat list of arguments
listArgs2 <- lapply(seq_along(listArgs$FUN_CRIT), function(i) lapply(listArgs, "[[", i))
## length of index of period to be used for the model run
LLL <- length(InputsModel$DatesR[RunOptions$IndPeriod_Run])
## preparation of warning messages
inVarObs <- c("Qobs") ##, "SCAobs")
msgVarObs <- "'varObs' must be a (list of) character vector(s) and one of %s \n"
msgVarObs <- sprintf(msgVarObs, paste(sapply(inVarObs, shQuote), collapse = ","))
inTransfo <- c("", "sqrt", "log", "inv", "sort")
msgTransfo <- "'transfo' must be a (list of) character vector(s) and one of %s \n"
msgTransfo <- sprintf(msgTransfo, paste(sapply(inTransfo, shQuote), collapse = ","))
## ---------- loop on the list of inputs
InputsCrit <- lapply(listArgs2, function(iListArgs2) {
## check 'FUN_CRIT'
if (!(identical(iListArgs2$FUN_CRIT, ErrorCrit_NSE ) | identical(iListArgs2$FUN_CRIT, ErrorCrit_KGE ) |
identical(iListArgs2$FUN_CRIT, ErrorCrit_KGE2) | identical(iListArgs2$FUN_CRIT, ErrorCrit_RMSE))) {
stop("incorrect 'FUN_CRIT' for use in 'CreateInputsCrit' \n", call. = FALSE)
Delaigue Olivier
committed
if (identical(iListArgs2$FUN_CRIT, ErrorCrit_RMSE) & length(listArgs$weights) > 1 & all(!is.null(unlist(listArgs$weights)))) {
stop("calculating a composite criterion with the RMSE is not allowed since RMSE is not an adimensional measure \n", call. = FALSE)
Delaigue Olivier
committed
## check 'BoolCrit'
if (is.null(iListArgs2$BoolCrit)) {
iListArgs2$BoolCrit <- rep(TRUE, length(iListArgs2$obs))
Delaigue Olivier
committed
if (!is.logical(iListArgs2$BoolCrit)) {
stop("'BoolCrit' must be a (list of) vector(s) of boolean \n", call. = FALSE)
Delaigue Olivier
committed
if (length(iListArgs2$BoolCrit) != LLL) {
stop("'BoolCrit' and 'InputsModel' series must have the same length \n", call. = FALSE)
Delaigue Olivier
committed
## check 'obs'
if (!is.vector(iListArgs2$obs) | length(iListArgs2$obs) != LLL | !is.numeric(iListArgs2$obs)) {
stop("'obs' must be a (list of) vector(s) of numeric values \n", call. = FALSE)
Delaigue Olivier
committed
## check 'varObs'
if (!is.vector(iListArgs2$varObs) | length(iListArgs2$varObs) != 1 | !is.character(iListArgs2$varObs) | !all(iListArgs2$varObs %in% inVarObs)) {
stop(msgVarObs, call. = FALSE)
Delaigue Olivier
committed
## check 'transfo'
if (is.null(iListArgs2$transfo) | !is.vector(iListArgs2$transfo) | length(iListArgs2$transfo) != 1 | !is.character(iListArgs2$transfo) | !all(iListArgs2$transfo %in% inTransfo)) {
stop(msgTransfo, call. = FALSE)
Delaigue Olivier
committed
## check 'weights'
if (!is.null(iListArgs2$weights)) {
if (!is.vector(iListArgs2$weights) | length(iListArgs2$weights) != 1 | !is.numeric(iListArgs2$weights) | any(iListArgs2$weights < 0)) {
stop("'weights' must be a single (list of) positive or equal to zero value(s) \n", call. = FALSE)
Delaigue Olivier
committed
## check 'epsilon'
if (!is.null(iListArgs2$epsilon)) {
if (!is.vector(iListArgs2$epsilon) | length(iListArgs2$epsilon) != 1 | !is.numeric(iListArgs2$epsilon) | any(iListArgs2$epsilon <= 0)) {
stop("'epsilon' must be a single (list of) positive value(s) \n", call. = FALSE)
return(NULL)
Delaigue Olivier
committed
}
Delaigue Olivier
committed
} else if (iListArgs2$transfo %in% c("log", "inv") & any(iListArgs2$obs %in% 0) & warnings) {
warning("zeroes detected in obs: the corresponding time-steps will be excluded by the 'ErrorCrit*' functions if the epsilon agrument = NULL", call. = FALSE)
Delaigue Olivier
committed
}
Delaigue Olivier
committed
## check 'transfo' + 'FUN_CRIT'
if (iListArgs2$transfo == "log" & warnings) {
warn_log_kge <- "we do not advise using the %s with a log transformation on obs (see the details part in the 'CreateInputsCrit' help)"
if (identical(iListArgs2$FUN_CRIT, ErrorCrit_KGE)) {
warning(sprintf(warn_log_kge, "KGE"), call. = FALSE)
}
if (identical(iListArgs2$FUN_CRIT, ErrorCrit_KGE2)) {
warning(sprintf(warn_log_kge, "KGE'"), call. = FALSE)
}
}
Delaigue Olivier
committed
## Create InputsCrit
iInputsCrit <- list(FUN_CRIT = iListArgs2$FUN_CRIT,
obs = iListArgs2$obs,
varObs = iListArgs2$varObs,
BoolCrit = iListArgs2$BoolCrit,
# groupLayer = iListArgs2$groupLayer,
transfo = iListArgs2$transfo,
epsilon = iListArgs2$epsilon,
weights = iListArgs2$weights)
class(iInputsCrit) <- c("Single", "InputsCrit", ObjectClass)
return(iInputsCrit)
Delaigue Olivier
committed
})
names(InputsCrit) <- paste0("IC", seq_along(InputsCrit))
# if only one criterion --> not a list of InputsCrit but directly an InputsCrit
if (length(InputsCrit) < 2) {
InputsCrit <- InputsCrit[[1L]]
InputsCrit["weights"] <- list(weights = NULL)
} else {
if (any(sapply(listArgs$weights, is.null))) {
for (iListArgs in InputsCrit) {
iListArgs$weights <- NULL
}
class(InputsCrit) <- c("Multi", "InputsCrit", ObjectClass)
} else {
class(InputsCrit) <- c("Compo", "InputsCrit", ObjectClass)
}
combInputsCrit <- combn(x = length(InputsCrit), m = 2)
apply(combInputsCrit, MARGIN = 2, function(i) {
equalInputsCrit <- identical(InputsCrit[[i[1]]], InputsCrit[[i[2]]])
if(equalInputsCrit) {
warning(sprintf("Elements %i and %i of the criteria list are identical. This might not be necessary", i[1], i[2]), call. = FALSE)
}
return(NULL)
})
Delaigue Olivier
committed
return(InputsCrit)
}