ProbBins <- function(ano, fcyr = 'all', thr, quantile = TRUE, posdates = NULL,
                     posdim = NULL, compPeriod = "Full period", format = "category") {
  # define dimensions
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (is.null(posdates)) {
    if ("sdate" %in% names(dim(ano))) {
      posdates <- which(names(dim(ano)) == "sdate") 
    } else {
      stop("posdates must be specified")
    }
  }
  if (is.null(posdim) & length(dim(ano)) == 0) {
    ano <- array(ano, c(length(ano),1))
    posdim <- 2
    posdates <- 1
  }
  if (length(dim(ano)) <= 2) {
    ano <- array(ano, dim = c(dim(ano), 1))
    extra_dim = TRUE
  } else {
    extra_dim = FALSE
  }
  dimano <- dim(ano)
  nbdim <- length(dim(ano))
  posdim <- setdiff(posdim, posdates)
  nbpos <- length(posdim)
  if (posdates != 1 || posdim != 2) {
    dimnames_backup <- names(dim(ano))
    perm <- c(posdates, posdim, (1:nbdim)[-c(posdates, posdim)])
    ano <- aperm(ano, perm)
    names(dim(ano)) <- dimnames_backup[perm]
    posdates <- 1
    posdim <- 2
  }
  dimano <- dim(ano)
  nsdates <- dimano[1]
  #calculate the number of elements on posdim dimension in ano
  nmemb <- 1
  if (nbpos > 0){
    for (idim in 2:(nbpos+1)){
      nmemb <- nmemb*dimano[idim]
    }
  }
  
  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, 
                           posdates, posdim, "Without fcyr")
      } else {
        dimnames_backup <- names(dim(result))
        result <- abind(result, ProbBins(ano, iyr, thr, quantile, 
                                         posdates, posdim, "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 <- array(Subset(ano, along = 1, indices = fcyr), dim = c(nfcyr,
                                                                  dimano[2:nbdim]))
    
    # the members and startdates are combined in one dimension
    sample_fore <- array(fore, dim=c(nfcyr*nmemb, dimano[(nbpos+2):nbdim]))
    
    if(compPeriod == "Full period") {
      hind <- ano
      sample <- array(hind, dim=c(nsdates*nmemb, dimano[(nbpos+2):nbdim]))
    } else if (compPeriod == "Without fcyr") {
      hind <- array(Subset(ano, along = 1, indices = -fcyr), dim = c(nsdates-nfcyr,
                                                                     dimano[2:nbdim]))
      sample <- array(hind, dim=c((nsdates-nfcyr)*nmemb, dimano[(nbpos+2):nbdim]))
    }
    
    #quantiles for each grid point and experiment
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    if (quantile == TRUE) {
      qum <- apply(sample, seq(2, nbdim - nbpos, 1), FUN = quantile, probs = thr, na.rm = TRUE, names = FALSE, type = 8)                                        
    } else {
      qum <- array(thr, dim = c(length(thr), dimano[(nbpos + 2) : nbdim]))
    }
    
    # This function assign the values to a category which is limited by the thresholds
    # It provides binary information
    
    counts <- function (dat, nbthr){
      thr <- dat[1 : nbthr]
      data <-  dat[nbthr + 1 : (length(dat) - nbthr)]
      prob <- array(NA, dim = c(nbthr + 1, length(dat) - nbthr))
      prob[1,] = 1 * (data <= thr[1])
      if(nbthr!=1){
        for (ithr in 2:(nbthr)){
          prob[ithr,]=1*((data > thr[ithr - 1]) & (data <= thr[ithr]))
        }
      }
      prob[nbthr+1,]=1*(data > thr[nbthr])
      return(prob) 
    }
    
    # The thresholds and anomalies are combined to use apply
    data <- abind(qum, sample_fore, along = 1)
    
    # PBF:Probabilistic bins of a forecast.
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # This array contains zeros and ones that indicate the category where your forecast is. 
    
    PBF <- array(apply(data, seq(2, nbdim - nbpos,1), FUN = counts, nbthr = length(thr)),
                 dim = c(length(thr)+1, nfcyr, nmemb, dimano[(nbpos + 2) : nbdim]))
    names(dim(PBF)) <- c('bin', 'sdate', 'member', names(dim(ano))[(nbpos+2):nbdim])
    if (extra_dim == TRUE) {
      PBF <- adrop(PBF, 4)
    }
    if (format == "members") {
      PBF <- t(apply(PBF, MARGIN = c(2), FUN = rowSums))
    } else if (format == "probability") {
      PBF <- t(apply(PBF, MARGIN = c(2), FUN = function(x) rowSums(x) / dim(x)[2]))
    }
    return(PBF)
  } else {
    stop("Parameter 'compPeriod' must be one of 'Full period', 'Without fcyr' or 'Cross-validation'.")
  }
}