CreateInputsCrit.R 13.13 KiB
CreateInputsCrit <- function(FUN_CRIT,
                             InputsModel,
                             RunOptions,
                             Qobs,              # deprecated
                             Obs,
                             VarObs = "Q",
                             BoolCrit = NULL,
                             transfo = "",
                             Weights = NULL,
                             Ind_zeroes = NULL, # deprecated
                             epsilon = NULL,
                             warnings = TRUE,
                             verbose = TRUE) {
  ObjectClass <- NULL
  ## ---------- check arguments
  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")
  if (!missing(Ind_zeroes) & warnings) {
    warning("deprecated 'Ind_zeroes' argument")
  if (!missing(verbose)) {
    warning("deprecated 'verbose' argument. Use 'warnings', instead")
  ## check 'InputsModel'
  if (!inherits(InputsModel, "InputsModel")) {
    stop("'InputsModel' must be of class 'InputsModel'")
  ## length of index of period to be used for the model run
  LLL <- length(InputsModel$DatesR[RunOptions$IndPeriod_Run])
  ## check 'Obs' and definition of idLayer
  vecObs <- unlist(Obs)
  if (length(vecObs) %% LLL != 0 | !is.numeric(vecObs)) {
    stop(sprintf("'Obs' must be a (list of) vector(s) of numeric values of length %i", LLL), call. = FALSE)
  if (!is.list(Obs)) {
    idLayer <- list(1L)
    Obs <- list(Obs)
  } else {
    idLayer <- lapply(Obs, function(i) {
      if (is.list(i)) {
        length(i)
      } else {
    Obs <- lapply(Obs, function(x) rowMeans(as.data.frame(x)))
  ## create list of arguments
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
listArgs <- list(FUN_CRIT = FUN_CRIT, Obs = Obs, VarObs = VarObs, BoolCrit = BoolCrit, idLayer = idLayer, transfo = as.character(transfo), 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) } } if (iArgs %in% c("FUN_CRIT", "VarObs", "transfo", "Weights") & length(listArgs[[iArgs]]) > 1L) { listArgs[[iArgs]] <- as.list(listArgs[[iArgs]]) } if (!is.list(listArgs[[iArgs]])) { listArgs[[iArgs]] <- list(listArgs[[iArgs]]) } } ## check 'FUN_CRIT' listArgs$FUN_CRIT <- lapply(listArgs$FUN_CRIT, FUN = match.fun) ## check 'VarObs' if (missing(VarObs)) { listArgs$VarObs <- as.list(rep("Q", times = length(listArgs$Obs))) # if (warnings) { # warning("'VarObs' automatically set to \"Q\"") # } } ## check 'VarObs' + 'RunOptions' if ("Q" %in% VarObs & !inherits(RunOptions, "GR")) { stop("'VarObs' cannot contain Q if a GR rainfall-runoff model is not used") } if (any(c("SCA", "SWE") %in% VarObs) & !inherits(RunOptions, "CemaNeige")) { stop("'VarObs' cannot contain SCA or SWE if CemaNeige is not used") } if ("SCA" %in% VarObs & inherits(RunOptions, "CemaNeige") & !"Gratio" %in% RunOptions$Outputs_Sim) { stop("'Gratio' is missing in 'Outputs_Sim' of 'RunOptions', which is necessary to output SCA with CemaNeige") } if ("SWE" %in% VarObs & inherits(RunOptions, "CemaNeige") & !"SnowPack" %in% RunOptions$Outputs_Sim) { stop("'SnowPack' is missing in 'Outputs_Sim' of 'RunOptions', which is necessary to output SWE with CemaNeige") } ## check 'transfo' if (missing(transfo)) { listArgs$transfo <- as.list(rep("", times = length(listArgs$Obs))) # if (warnings) { # warning("'transfo' automatically set to \"\"") # } } ## 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 'RunOptions' if (!inherits(RunOptions , "RunOptions")) {
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
stop("'RunOptions' must be of class 'RunOptions'") } ## 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") } ## ---------- reformat ## reformat list of arguments listArgs2 <- lapply(seq_along(listArgs$FUN_CRIT), function(i) lapply(listArgs, "[[", i)) ## preparation of warning messages 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", "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 = ", ")) ## ---------- 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'", call. = FALSE) } 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 a dimensionless metric", call. = FALSE) } ## check 'Obs' if (!is.vector(iListArgs2$Obs) | length(iListArgs2$Obs) != LLL | !is.numeric(iListArgs2$Obs)) { stop(sprintf("'Obs' must be a (list of) vector(s) of numeric values of length %i", LLL), call. = FALSE) } ## check 'BoolCrit' if (is.null(iListArgs2$BoolCrit)) { iListArgs2$BoolCrit <- rep(TRUE, length(iListArgs2$Obs)) } if (!is.logical(iListArgs2$BoolCrit)) { stop("'BoolCrit' must be a (list of) vector(s) of boolean", call. = FALSE) } if (length(iListArgs2$BoolCrit) != LLL) { stop("'BoolCrit' and 'InputsModel' series must have the same length", call. = FALSE) } ## check 'VarObs' if (!is.vector(iListArgs2$VarObs) | length(iListArgs2$VarObs) != 1 | !is.character(iListArgs2$VarObs) | !all(iListArgs2$VarObs %in% inVarObs)) { stop(msgVarObs, call. = FALSE) } ## check 'VarObs' + 'Obs' if (any(iListArgs2$VarObs %in% "SCA")) { idSCA <- which(iListArgs2$VarObs == "SCA") if (length(idSCA) == 1L) { vecSCA <- iListArgs2$Obs } else { vecSCA <- unlist(iListArgs2$Obs[idSCA]) } if (min(vecSCA, na.rm = TRUE) < 0 | max(vecSCA, na.rm = TRUE) > 1) { stop("'Obs' outside [0,1] for \"SCA\"", call. = FALSE) } }