ProbBins <- function(ano, fcyr = 'all', thr, quantile = TRUE, posdates = 3,
                     posdim = 2, compPeriod = "Full period", format = "category") {
  # define dimensions
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ano <- aperm(ano, c(posdates, posdim, c(1:length(dim(ano)))[-c(posdates,posdim)]))
  if (length(dim(ano)) <= 2) {
    margins <- NULL
  } else {
    margins <- 3 : length(dim(ano))
  }
  PBF <- Apply(list(ano), margins = margins, AtomicFun = ".ProbBins", fcyr,
        thr, quantile, compPeriod, format)
  return(PBF)
}

.ProbBins <- function(ano, fcyr = 'all', thr, quantile = TRUE, compPeriod = "Full period", format = "category") {
  # define dimensions
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (c(format %in% c("members", "category", "probability")) == FALSE) {
    stop("format must be one of members, category or probability")
  }
  if (!is.matrix(ano) && !is.vector(ano)) {
    stop("ano must be a matrix or a vector")
  }
  if (is.vector(ano)) {
    ano <- as.matrix(ano)
  }
  
  # nbdim <- length(dim(ano))   # this will always be 2
  dimano <- dim(ano)
  nsdates <- dimano[1]
  nmemb <- dimano[2]
  nbthr <- length(thr)
  #calculate the number of elements on posdim dimension in ano
  
  if (length(fcyr) == 1) {
    if (fcyr == 'all') {
      fcyr <- 1:nsdates
    }
  }
  nfcyr <- length(fcyr)
  if (compPeriod == "Cross-validation") {
    result <- NULL
    for (iyr in fcyr) {
      if (is.null(result)) {
        result <- .ProbBins(ano, iyr, thr, quantile, 
                           "Without fcyr")
      } else {
        dimnames_backup <- names(dim(result))
        result <- abind(result, .ProbBins(ano, iyr, thr, quantile, 
                                           "Without fcyr"), 
                        along = 2)
        names(dim(result)) <- dimnames_backup
      }
    }
    return(result)
  } else if (compPeriod %in% c("Full period", "Without fcyr")) {
    # separate forecast and hindcast
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    fore <- ano[fcyr, ]
    if (is.vector(fore)) {
      fore <- as.matrix(fore)
    }
    if(compPeriod == "Full period") {
      sample <-  c(ano)
    } else if (compPeriod == "Without fcyr") {
      sample <- c(ano[-fcyr, ])
    }
    
    #quantiles for each grid point and experiment
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    if (quantile == TRUE) {
      qum <- quantile(sample, thr, na.rm = TRUE, names = FALSE, type = 8)
    } else {
      qum <- thr
    }
    
    # PBF:Probabilistic bins of a forecast.
    
    if (format == "category") {
      PBF <- ProbBinsCpp1(fore, qum)
      dim(PBF) <- c(nbthr + 1, nfcyr, nmemb)
    } else if (format == "members") {
      PBF <- ProbBinsCpp2(fore, qum)
    } else {
      PBF <- ProbBinsCpp3(fore, qum)
    }
  } else {
    stop("Parameter 'compPeriod' must be one of 'Full period', 'Without fcyr' or 'Cross-validation'.")
  }
  return(PBF)
}