
##################################################################################
#                                    Toy Model                                   #
##################################################################################

library(s2dverification)
library(SpecsVerification)
library(easyVerification)

my.prob=c(1/3,2/3)      # quantiles used for FairRPSS and the RelDiagr (usually they are the terciles)

N=80 # number of years
M=14 # number of members

for(M in c(2:10,20,51,100,200)){ 
  
  for(N in c(5,10,15,20,25,30,40,50,100,200,500,1000,2000,5000,10000,20000,50000,100000)){ 
    
    anom.rean<-rnorm(N)
    anom.hind<-array(rnorm(N*M),c(N,M))
    #quantile(anom.hind,prob=my.prob,type=8)
    
    obs<-convert2prob(anom.rean,prob<-my.prob) 
    #mean(obs[,1]) # check if it is equal to 0.333 for K=3
    
    ens<-convert2prob(anom.hind,prob<-my.prob)
    
    # climatological forecast:
    anom.hind.clim<-array(sample(anom.hind,N*M),c(N,M))   # extract a random sample with no replacement of the hindcast
    ens.clim<-convert2prob(anom.hind.clim,prob<-my.prob)
    #mean(ens.clim[,1]) # check if it is equal to M/3 (1.333 for M=4)
    
    # alternative definition of climatological forecast, based on observations instead (as applied by veriApply via convert2prob when option fcst.ref is missing):
    #anom.rean.clim<-ClimEns(anom.rean) # create a climatological ensemble from a vector of observations (anom.rean) with the leave-one-out cross validation
    anom.rean.clim<-t(array(anom.rean,c(N,N))) # function used by convert2prob when ref is not specified; it is ~ equal to the above function ClimEns, it only has a column more
    ens.clim.rean<-convert2prob(anom.rean.clim,prob<-c(1/3,2/3))  # create a new prob.table based on the climatological ensemble of observations
    
    p<-count2prob(ens)  # we should add the option type=4, in not the sum for each year is not 100%!!!
    y<-count2prob(obs)  # we should add the option type=4, in not the sum for each year is not 100%!!!
    ReliabilityDiagram(p[,1], y[,1], bins=10, nboot=0,  plot=TRUE, cons.prob=c(0.05, 0.85),plot.refin=F)
    
    ### computation of verification scores:
    
    Rps<-round(mean(EnsRps(ens,obs)),4)
    FairRps<-round(mean(FairRps(ens,obs)),4)
    #Rps.easy<-round(mean(veriApply("EnsRps", fcst=anom.hind, obs=anom.rean, prob=my.prob, tdim=1, ensdim=2)),4)  # check once to see if it is the same value of Rps
    #FairRps.easy<-round(mean(veriApply("FairRps", fcst=anom.hind, obs=anom.rean, prob=my.prob, tdim=1, ensdim=2)),4)  # check once to see if it is the same value of FairRps
    
    Rps.clim<-round(mean(EnsRps(ens.clim,obs)),4)
    FairRps.clim<-round(mean(FairRps(ens.clim,obs)),4)
    FairRps.clim.rean<-round(mean(FairRps(ens.clim.rean,obs)),4)
    
    #FairRps.clim.stable<-0.44444444
    #Rps.clim.easy<-round(mean(veriApply("EnsRps", fcst=anom.hind.clim, obs=anom.rean, prob=my.prob, tdim=1, ensdim=2)),4) # check once to see if it is the same value of Rps.clim
    #FairRps.clim.easy<-round(mean(veriApply("FairRps", fcst=anom.hind.clim, obs=anom.rean, prob=my.prob, tdim=1, ensdim=2)),4)  # check once to see if it is = to FairRps.clim
    
    Rpss<-round(1-(Rps/Rps.clim),4)
    #Rpss.specs<-round(EnsRpss(ens=ens, ens.ref=ens.clim, obs=obs)$rpss,4)  # check it once to see if it is the same as Rpss (yes)
    Rpss.easy<-veriApply("EnsRpss", fcst=anom.hind, fcst.ref=anom.hind.clim, obs=anom.rean, prob=my.prob, tdim=1, ensdim=2)$rpss # we provide the clim.forecast; = to Rpss.specs
    system.time(Rpss.easy.noclim<-round(veriApply("EnsRpss", fcst=anom.hind, obs=anom.rean, prob=my.prob, tdim=1, ensdim=2, parallel=FALSE, ncpus=5)$rpss,4))  # using their climatological forecast
    #cat(Rps.clim.noclim<-Rps/(1-Rpss.easy.noclim)) # sale igual a ~0.45 per ogni hindcast; é diverso sia da Rps.clim che da Rps.clim per N-> +oo (0.555)
    
    Rpss.easy<-veriApply("EnsRpss", fcst=anom.hind, fcst.ref=anom.rean.clim, obs=anom.rean, prob=my.prob, tdim=1, ensdim=2)$rpss # we provide the clim.forecast; = to Rpss.specs
    Rpss.easy.noclim<-veriApply("EnsRpss", fcst=anom.hind, obs=anom.rean, prob=my.prob, tdim=1, ensdim=2)$rpss # we provide the clim.forecast; = to Rpss.specs
    
    FairRpss<-round(1-(FairRps/FairRps.clim),4)
    #FairRpss.specs<-round(FairRpss(ens=ens,ens.ref=ens.clim,obs=obs)$rpss,4)  # check it once to see if it is the same as FairRpss (yes)
    #FairRpss.easy<-veriApply("FairRpss", fcst=anom.hind, fcst.ref=anom.hind.clim, obs=anom.rean, prob=c(1/3,2/3), tdim=1, ensdim=2)$rps
    #FairRpss.easy.noclim<-round(veriApply("FairRpss", fcst=anom.hind, obs=anom.rean, prob=c(1/3,2/3), tdim=1, ensdim=2)$rpss,4)  # using their climatological forecast
    #cat(FairRps.clim.noclim<-Rps/(1-FairRpss.easy.noclim)) # sale igual a ~0.55; é diverso sia da FairRps.clim che da FairRps.clim per N-> +oo (0.444)
    
    cat(paste0('n.memb: ' ,M,'  n.yrs: ',N,'  <FairRps>: ',FairRps,'  <FairRps(clim)>: ' ,FairRps.clim,'  FairRpss: ',FairRpss,'\n'))
    
    #cat(paste0('n.memb: ' ,M,'  n.yrs: ',N,'  <FairRps>: ',FairRps,'  <FairRps(clim)>: ' ,FairRps.clim,'  FairRpss: ',FairRpss,'\n'))
    
    #cat(paste0('n.memb: ' ,M,'  n.yrs: ',N,'  <Rps>:     ',Rps,'  <Rps(clim)>:     ' ,Rps.clim,'  Rpss: ',Rpss,'\n','n.memb: ' ,M,'  n.yrs: ',N,'  <FairRps>: ',FairRps,'  <FairRps(#clim)>: ' ,FairRps.clim,'  FairRpss: ',FairRpss,'\n'))
    
    #cat(paste0('n.memb: ' ,M,'  n.yrs: ',N,'  <Rps>:     ',Rps,'  <Rps(clim)>:     ' ,Rps.clim,'  Rpss: ',Rpss,'  Rpss.easy: ',Rpss.easy.noclim,'\n','n.memb: ' ,M,'  n.yrs: ',N,'  #<FairRps>: ',FairRps,'  <FairRps(clim)>: ' ,FairRps.clim,'  FairRpss: ',FairRpss,'  FairRpss.easy: ',FairRpss.easy.noclim))
    
  }
  
  # Crpss:
  
  #Crps<-round(mean(EnsCrps(ens,obs)),4)
  #FairCrps<-round(mean(FairCrps(ens,obs)),4)
  
  #cat(Crps.clim<-round(mean(EnsCrps(ens.clim,obs)),4))
  #FairCrps.clim<-round(mean(FairCrps(ens.clim,obs)),4)
  
  #Crpss<-round(1-(Crps/Crps.clim),4)
  #Crpss.specs<-round(EnsCrpss(ens=ens, ens.ref=ens.clim, obs=obs)$rpss,4)
  
  #FairCrpss<-round(1-(FairCrps/FairCrps.clim),4)
  #FairCrpss.specs<-round(FairCrpss(ens=ens,ens.ref=ens.clim,obs=obs)$rpss,4)
  
}


##################################################################################
#                                 Other analysis                                 #
##################################################################################

my.startdates=1 #c(1:9) # select the startdates (weeks) you want to merge together

#tm<-toyarray(dims=c(32,64),N=20,nens=4) # in the number of startdates in case of forecasts or the number of years in case of hindcasts
#str(tm) # tm$fcst: [32,64,20,4]  tm$obs: [32,64,20]
#
#f.corr <- veriApply("EnsCorr", fcst=tm$fcst, obs=tm$obs)
#f.me <- veriApply('EnsMe', tm$fcst, tm$obs)
#f.crps <- veriApply("FairCrps", fcst=tm$fcst, obs=tm$obs)
#str(f.crps) # [32,64,20]

#cst <- array(rnorm(prod(4:8)), 4:8)
#obs <- array(rnorm(prod(4:7)), 4:7)
#f.me <- veriApply('EnsMe', fcst=fcst, obs=obs)
#dim(f.me)
#fcst2 <- array(aperm(fcst, c(5,1,4,2,3)), c(8, 4, 7, 5*6))  # very interesting use of aperm not only to swap dimensions, but also to merge two dimensions in the same one!
#obs2 <- array(aperm(obs, c(1,4,2,3)), c(4,7,5*6))
#f.me2 <- veriApply('EnsMe', fcst=fcst2, obs=obs2, tdim=3, ensdim=1)
#dim(f.me2)

# when you have for each leadtime all the 52 weeks of year 2014 stored in a map,
# you can plot the time serie for a particular point and leadtime:
pos.lat<-which(round(la,3)==round(my.lat,3))
pos.lon<-which(round(lo,3)==round(my.lon,3))

x11()
plot(1:week,EnMeanCorr[,leadtime],type="b",
     main=paste0("Weekly time serie of point with lat=",round(my.lat,2),", lon=",round(my.lon,2)),
     xlab="week",ylab="Ensemble Mean Corr.",ylim=c(-1,1))



###   check if 4 time steps are better than one: 

yrs.hind<-yr2.hind-yr1.hind+1
my.point.obs<-array(NA,c(yrs.hind,28))

# load obs.data for the four time steps:
for(year in yr1.hind:yr2.hind){
  data_erai_6h <- Load(var=var.name, exp = 'ERAint6h',
                       obs = NULL, sdates=paste0(year,'01'), leadtimemin = 61, 
                       leadtimemax = 88, output = 'lonlat', configfile = file_path, grid=my.grid,method='distance-weighted')
  
  my.point.obs[year-yr1.hind+1,]<-data_erai_6h$mod[1,1,1,,65,633]
}

utm0<-c(1,5,9,13,17,21,25)
utm6<-utm0+1
utm12<-utm0+2
utm18<-utm0+3
my.points.obs.weekly.mean.utm0<-rowMeans(my.point.obs[,utm0])
my.points.obs.weekly.mean.utm6<-rowMeans(my.point.obs[,utm6])
my.points.obs.weekly.mean.utm12<-rowMeans(my.point.obs[,utm12])
my.points.obs.weekly.mean.utm18<-rowMeans(my.point.obs[,utm18])
my.points.obs.weekly.mean.all<-rowMeans(my.point.obs)

cor(my.points.exp.weekly.mean.all,my.points.obs.weekly.mean.all,use="complete.obs")

my.points.obs.weekly.mean.utm<-c(my.points.obs.weekly.mean.utm0,my.points.obs.weekly.mean.utm6,my.points.obs.weekly.mean.utm12,my.points.obs.weekly.mean.utm18)
my.points.exp.weekly.mean.utm<-c(my.points.exp.weekly.mean.utm0,my.points.exp.weekly.mean.utm6,my.points.exp.weekly.mean.utm12,my.points.exp.weekly.mean.utm18)
cor(my.points.exp.weekly.mean.utm,my.points.obs.weekly.mean.utm,use="complete.obs")


##### Calculate Reanalysis climatology loading only 1 file each 4 (it's quick but it needs to have all files beforehand):

ss<-c(seq(1,52,by=4),50,51,52) # take only 1 startdate each 4, more the last 3 startdates that must be computed individually because they are not a complete set of 4

for(startdate in ss){ # the startdate day of 2014 to load in the sdates weekly sequence along with the same startdates of the previous 20 years
  data.ERAI <- Load(var=var.name, exp = 'ERAintEnsWeek',
                    obs = NULL, sdates=paste0(yr1.hind:yr2.hind,substr(sdates.seq[startdate],5,6),substr(sdates.seq[startdate],7,8)),
                    nleadtime = 4, leadtimemin = 1, leadtimemax = 4, output = 'lonlat', configfile = file_path, grid=my.grid, method='distance-weighted')
  
  clim.ERAI[startdate,,,]<-apply(data.ERAI$mod,c(1,2,4,5,6),mean)[1,1,,,] # average for each leadtime and pixel
  
  # the intermediate startdate between startdate week i and startdate week i+4 are repeated:
  if(startdate <= 49){
    clim.ERAI[startdate+1,1,,]<- clim.ERAI[startdate,2,,] # startdate  leadtime (week)
    clim.ERAI[startdate+1,2,,]<- clim.ERAI[startdate,3,,] #   (week)   1 2 3 4 
    clim.ERAI[startdate+2,1,,]<- clim.ERAI[startdate,3,,] #     1      a b c d <- only startdate 1 and 5 are necessary to calculate all startdates between 1 and 5
    clim.ERAI[startdate+1,3,,]<- clim.ERAI[startdate,4,,] #     2      b c d e
    clim.ERAI[startdate+2,2,,]<- clim.ERAI[startdate,4,,] #     3      c d e f
    clim.ERAI[startdate+3,1,,]<- clim.ERAI[startdate,4,,] #     4      d e f g
  }                                                     #     5      e f g h 
  
  if(startdate > 1 && startdate <=49){  # fill the previous startdates:                                          
    clim.ERAI[startdate-1,4,,]<- clim.ERAI[startdate,3,,]
    clim.ERAI[startdate-1,3,,]<- clim.ERAI[startdate,2,,]
    clim.ERAI[startdate-2,4,,]<- clim.ERAI[startdate,2,,]
    clim.ERAI[startdate-1,2,,]<- clim.ERAI[startdate,1,,]
    clim.ERAI[startdate-2,3,,]<- clim.ERAI[startdate,1,,]
    clim.ERAI[startdate-3,4,,]<- clim.ERAI[startdate,1,,]
  }
  
}




# You can make cor much faster by stripping away all the error checking code and calling the internal c function directly:
# r <- apply(m1, 1, function(x) { apply(m2, 1, function(y) { cor(x,y) })}) 
# r2 <- apply(m1, 1, function(x) { apply(m2, 1, function(y) {.Internal(cor(x, y, 4L, FALSE)) })})
C_cor<-get("C_cor", asNamespace("stats"))
test<-.Call(C_cor, x=rnorm(100,1), y=rnorm(100,1), na.method=2, FALSE)
my.EnsCorr.chunk[i,j,k]<-.Call(C_cor, x=anom.hindcast.mean.chunk[,i,j,k], y=nom.rean.chunk[,i,j,k], na.method=2, FALSE)



#######################################################################################
#                              Raster Animations                                      #
#######################################################################################

library(png)
library(animation)


clustPNG <- function(pngobj, nclust = 3){
  
  j <- pngobj
  # If there is an alpha component remove it...
  # might be better to just adjust the mat matrix
  if(dim(j)[3] > 3){
    j <- j[,,1:3]
  }
  k <- apply(j, c(1,2), c)
  mat <- matrix(unlist(k), ncol = 3, byrow = TRUE)
  grd <- expand.grid(1:dim(j)[1], 1:dim(j)[2])
  clust <- kmeans(mat, nclust, iter.max = 20)
  new <- clust$centers[clust$cluster,]
  
  for(i in 1:3){
    tmp <- matrix(new[,i], nrow = dim(j)[1])
    j[,,i] <- tmp
  }
  
  plot.new()
  rasterImage(j, 0, 0, 1, 1, interpolate = FALSE)
}

makeAni <- function(file, n = 10){
  j <- readPNG(file)
  for(i in 1:n){
    clustPNG(j, i)
    mtext(paste("Number of clusters:", i))
  }
  
  j <- readPNG(file)
  plot.new()
  rasterImage(j, 0, 0, 1, 1, interpolate = FALSE)
  mtext("True Picture")
}

file <- "~/Dropbox/Photos/ClassyDogCropPng.png"
n <- 20
saveGIF(makeAni(file, n), movie.name = "tmp.gif", interval = c(rep(1,n), 5))




#######################################################################################
#                                    ProgressBar                                      #
#######################################################################################

for(i in 1:10) {
  Sys.sleep(0.2)
  # Dirk says using cat() like this is naughty ;-)
  #cat(i,"\r")
  # So you can use message() like this, thanks to Sharpie's
  # comment to use appendLF=FALSE.
  message(i,"\r",appendLF=FALSE)
  flush.console()
}


for(i in 1:10) {
  Sys.sleep(0.2)
  # Dirk says using cat() like this is naughty ;-)
  cat(i,"\r")
  
  
}



#######################################################################################
#                            Load large datasets with ff                              #
#######################################################################################

library(ff)
my.scratch<-"/scratch/Earth/ncortesi/myBigData"
anom.hind<-as.ff(anom.hind, vmode="double", file=my.scratch)
ffsave(anom.hind,file=my.scratch)
close(anom.hind);rm(anom.hind)

ffload(file=my.scratch, list=c(anom.hind))
open(anom.hind)
my.SkillScore <- veriApplyBig("FairRpss", fcst=anom.hind, obs=anom.rean, tdim=2, ensdim=1, prob=c(1/3,1/3))
close(anom.hind);rm(anom.hind)



BigDataPath <- "/scratch/Earth/ncortesi/myBigData"
source('/home/Earth/ncortesi/Downloads/RESILIENCE/veriApplyBig.R')

anom.hind.dim<-c(5,3,1,256,512)
anom.hind<-array(rnorm(prod(anom.hind.dim)),anom.hind.dim)  # doesn't fit in memory
save.big(array=anom.hind, path=BigDataPath)

veriApplyBig <- function(, obsmy.scratch){
  ffload(file=my.scratch)
  open(anom.hind)
  my.SkillScore <- veriApplyBig("FairRpss", fcst=anom.hind, obs=anom.rean, tdim=2, ensdim=1, prob=c(1/3,1/3))
  close(anom.hind)
}


anom.hind<-as.ff(anom.hind, vmode="double", file=my.scratch)
ffsave(anom.hind, file=my.scratch)

my.scratch<-"/scratch/Earth/ncortesi/myBigData"

anom.hind<-as.ff(anom.hind, vmode="double", file=my.scratch)
ffsave(anom.hind, file=my.scratch)
close(anom.hind); rm(anom.hind)

ffload(file=my.scratch, list=c(anom.hind))
open(anom.hind)
my.SkillScore <- veriApplyBig("FairRpss", fcst=anom.hind, obs=anom.rean, tdim=2, ensdim=1, prob=c(1/3,1/3))
close(anom.hind); rm(anom.hind)

anom.hind.dim<-c(51,30,1,256,51)
anom.hind<-ff(rnorm(prod(anom.hind.dim)), dim=anom.hind.dim, vmode="double", filename="/scratch/Earth/ncortesi/anomhind")
str(anom.hind)
dim(anom.hind)

anom.hind.dim<-c(51,30,1,256,51)
anom.hind<-array(rnorm(prod(anom.hind.dim)),anom.hind.dim)  # doesn't fit in memory
anom.hind<-as.ff(anom.hind, vmode="double", file="/scratch/Earth/ncortesi/myBigData")
str(anom.hind)
dim(anom.hind)

ffsave(anom.hind,file="/scratch/Earth/ncortesi/anomhind")
#ffinfo(file="/scratch/Earth/ncortesi/anomhind")
close(anom.hind)
#delete(anom.hind)
#rm(anom.hind)

ffload(file="/scratch/Earth/ncortesi/anomhind")

anom.rean<-array(rnorm(prod(anom.hind.dim[-1])), anom.hind.dim[-1])  # doesn't fit in memory

open(anom.hind)
my.SkillScore <- veriApplyBig("FairRpss", fcst=anom.hind, obs=anom.rean, tdim=2, ensdim=1, prob=c(1/3,1/3))
fcst<-anom.hind
obs<-anom.rean

close(anom.hind)
rm(anom.hind)

#ffdrop(file="/scratch/Earth/ncortesi/anomhind")

a<-ffapply(X=anom.hind.big, MARGIN=c(1,3,4,5), AFUN=mean, RETURN=TRUE)
a<-ffapply(X=anom.hind.big, MARGIN=c(1,3,4,5), AFUN=function(x) sample(x, replace=TRUE), CFUN="list", RETURN=TRUE)


pred_Cal_cross_ff <- as.ff(pred_Cal_cross, vmode='double', file=fileoutput_cross)
ffsave(pred_Cal_cross_ff, file=paste0(fileoutput_cross)) 
delete(pred_Cal_cross_ff)

assign("pred_Cal_cross_ff",  as.ff(pred_Cal_cross, vmode='double', file=fileoutput_cross))
ffsave(pred_Cal_cross_ff, file=paste0(fileoutput_cross)) 
delete(pred_Cal_cross_ff)
rm(pred_Cal_cross_ff)

assign("pred_Cal_cross_ff",  as.ff(pred_Cal_cross, vmode='double', file=fileoutput_cross))
a<-get("pred_Cal_cross_ff")           # get() works well in this case but not in the row below!  (you must use do.call, see WT_drivers_v2.R)
ffsave(get("pred_Cal_cross_ff"), file=paste0(fileoutput_cross)) 
delete(pred_Cal_cross_ff)
rm(pred_Cal_cross_ff)



#########################################################################################
#   Calculate and save the FairRpss and/or the FairCrpss for a chosen period using ff   #
#########################################################################################

bigdata=FALSE           # if TRUE, compute the Rpss and the Crpss using the package ff (storing arrays in the disk instead than in the RAM) to remove the memory limit

for(month in veri.month){
  month=1 # for debug
  my.startdates <- which(as.integer(substr(sdates.seq,5,6)) == month) #startdates.monthly[[month]] #c(1:5)    # select the startdates (weeks) you want to compute
  startdate.name=my.month[month]                        # name given to the period of the selected startdates, i.e:"January" 
  n.yrs <- length(my.startdates)*n.yrs.hind             # number of total years for the selected month
  print(paste0("Computing Skill Scores for ",startdate.name))
  
  if(!boot) anom.rean.big<-array(NA, dim=c(n.yrs, n.leadtimes, n.lat, n.lon)) # reanalysis data is not converted to ff because it is a small array
  
  if(boot) mod<-1 else mod=0  # in case of the boostrap, anom.hind.big includes also the reanalysis data as additional last member
  
  if(bigdata)  anom.hind.big <- ff(NA, dim=c(n.members + mod, n.yrs, n.leadtimes, n.lat, n.lon), vmode="double", filename=paste0(workdir,"/anomhindbig.ff"))
  if(!bigdata) anom.hind.big <- array(NA, dim=c(n.members + mod, n.yrs, n.leadtimes, n.lat, n.lon))
  
  for(startdate in my.startdates){
    
    pos.startdate<-which(startdate==my.startdates) # count of the number of stardates already loaded +1
    my.time.interv<-(1+(pos.startdate-1)*n.yrs.hind):(pos.startdate*n.yrs.hind)  # time interval where to load data
    
    load(paste0(workdir,'/Data_',var.name,'/anom_rean_startdate',startdate,'.RData'))
    if(!boot) {
      anom.rean<-drop(anom.rean)
      anom.rean.big[my.time.interv,,,] <- anom.rean
    }
    
    if(any(my.score.name=="FairRpss") || any(my.score.name=="FairCrpss")){
      load(paste0(workdir,'/Data_',var.name,'/anom_hindcast_startdate',startdate,'.RData'))  # load hindcast data
      anom.hindcast<-drop(anom.hindcast)
      
      if(!boot) anom.hind.big[,my.time.interv,,,] <- anom.hindcast
      if(boot) anom.hind.big[,my.time.interv,,,] <- abind(anom.hindcast, anom.rean, along=1)
      
      rm(anom.hindcast, anom.rean)
    }
    gc()
  }
  
  if(any(my.score.name=="FairRpss" || my.score.name=="FairCrpss")){
    if(!boot) {
      if(any(my.score.name=="FairRpss")) my.FairRpss <- veriApplyBig("FairRpss", fcst=anom.hind.big, obs=anom.rean.big,
                                                                     prob=my.prob, tdim=2, ensdim=1, parallel=TRUE, ncpus=n.cpus)
      if(any(my.score.name=="FairCrpss")) my.FairCrpss <- veriApplyBig("FairCrpss", fcst=anom.hind.big, obs=anom.rean.big, tdim=2, ensdim=1, parallel=TRUE, ncpus=n.cpus)
      
    } else {
      # bootstrapping: 
      my.FairRpssBoot<-my.FairCrpssBoot<-array(NA, c(n.boot, n.leadtimes, n.lat, n.lon))
      if(!bigdata) save(anom.hind.big, file=paste0(workdir,"/anom_hind_big.RData")) # save the anomalies to free memory
      
      for(b in 1:n.boot){
        print(paste0("resampling n. ",b,"/",n.boot))
        yrs.sampled <- sample(1:n.yrs, replace=TRUE)
        
        if(bigdata)  anom.hind.big.sampled <- ff(NA, dim=c(n.members+1, n.yrs, n.leadtimes, n.lat, n.lon), vmode="double", filename=paste0(workdir,"/anomhindbigsampled"))
        if(!bigdata) anom.hind.big.sampled <- array(NA, dim=c(n.members+1, n.yrs, n.leadtimes, n.lat, n.lon))
        
        if(!bigdata && b>1) load(paste0(workdir,"/anom_hind_big.RData")) # need to load the hindcasts if b>1
        
        for(y in 1:n.yrs) anom.hind.big.sampled[,y,,,] <-  anom.hind.big[,yrs.sampled[y],,,] # with ff takes 53s x 100 ~1h!!! (without, only 4s x 100 ~6m)
        
        if(!bigdata) rm(anom.hind.big); gc()  # free memory for the following commands
        
        # faster way that will be able to replace the above one when ffapply output parameters wll be improved:
        #a<-ffapply(X=anom.hind.big, MARGIN=c(3,4,5), AFUN=function(x) my.sample(x,n.members+1, replace=TRUE), CFUN="list", RETURN=TRUE, FF_RETURN=TRUE) # takes 3m only
        #aa<-abind(a[1:10], along=4) # it doesn't fit into memory!
        
        if(any(my.score.name=="FairRpss")) my.FairRpssBoot[b,,,]  <- veriApplyBig("FairRpss", fcst=anom.hind.big.sampled[1:n.members,,,,],
                                                                                  obs=anom.hind.big.sampled[n.members+1,,,,],
                                                                                  prob=my.prob, tdim=2, ensdim=1, parallel=TRUE, ncpus=n.cpus) #$rpss
        
        if(any(my.score.name=="FairCrpss")) my.FairCrpssBoot[b,,,] <- veriApplyBig("FairCrpss", fcst=anom.hind.big.sampled[1:n.members,,,,],
                                                                                   obs=anom.hind.big.sampled[n.members+1,,,,],
                                                                                   tdim=2, ensdim=1, parallel=TRUE, ncpus=n.cpus) #$crpss
        
        if(bigdata) delete(anom.hind.big.sampled)
        rm(anom.hind.big.sampled) # delete the sampled hindcast
        
      }
      
      # calculate 5 and 95 percentiles of skill scores:
      if(any(my.score.name=="FairRpss"))  my.FairRpssConf <- apply(my.FairRpssBoot, c(2,3,4), function(x) quantile(x, probs=c(0.05,0.95), type=8))
      if(any(my.score.name=="FairCrpss")) my.FairCrpssConf <- quantile(my.FairCrpssBoot, probs=c(0.05,0.95), type=8)
      
    } # close if on boot
    
  }
  
  if(bigdata) delete(anom.hind.big) # delete the file with the hindcasts
  rm(anom.hind.big) 
  rm(anom.rean.big)
  gc()
  
  if(!boot){
    if(any(my.score.name=="FairRpss")) save(my.FairRpss, file=paste0(workdir,'/Data_',var.name,'/FairRpss_',startdate.name,'.RData'))
    if(any(my.score.name=="FairCrpss")) save(my.FairCrpss, file=paste0(workdir,'/Data_',var.name,'/FairCrpss_',startdate.name,'.RData'))
  } else {
    if(any(my.score.name=="FairRpss")) save(my.FairRpssBoot, my.FairRpssConf, file=paste0(workdir,'/Data_',var.name,'/FairRpssBoot_',startdate.name,'.RData'))
    if(any(my.score.name=="FairCrpss")) save(my.FairCrpssBoot, my.FairCrpssConf, file=paste0(workdir,'/Data_',var.name,'/FairCrpssBoot_',startdate.name,'.RData'))
  }
  
  
  if(is.object(my.FairRpss)) rm(my.FairRpss); if(is.object(my.FairCrpss)) rm(my.FairCrpss)
  if(is.object(my.FairRpssBoot)) rm(my.FairRpssBoot); if(is.object(my.FairCrpssBoot)) rm(my.FairCrpssBoot)
  if(is.object(my.FairRpssConf)) rm(my.FairRpssConf); if(is.object(my.FairCrpssConf)) rm(my.FairCrpssConf)
  
} # next m (month)


#########################################################################################
#     Calculate and save the FairRpss for a chosen period using ff and Load()           #
#########################################################################################

anom.rean.big<-array(NA, dim=c(length(my.startdates)*n.yrs.hind, n.leadtimes, n.lat, n.lon)) 
anom.hind.big <- ff(NA, dim=c(n.members,length(my.startdates)*n.yrs.hind, n.leadtimes, n.lat, n.lon), vmode="double", filename="/scratch/Earth/anomhindbig")

for(startdate in my.startdates){
  pos.startdate<-which(startdate==my.startdates) # count of the number of stardates already loaded+1
  my.time.interv<-(1+(pos.startdate-1)*n.yrs.hind):(pos.startdate*n.yrs.hind)  # time interval where to load data
  
  #load(paste0(workdir,'/Data_',var.name,'/anom_rean_startdate',startdate,'.RData'))
  #anom.rean<-drop(anom.rean)
  #anom.rean.big[my.time.interv,,,] <- anom.rean
  
  my.date <- paste0(yr1.hind:yr2.hind,substr(sdates.seq[startdate],5,6),substr(sdates.seq[startdate],7,8))
  anom.rean <- Load(var=var.name, exp = 'EnsEcmwfWeekHind', 
                    obs = NULL, sdates=my.date, nleadtime = n.leadtimes, leadtimemin = 1, leadtimemax = n.leadtimes,
                    output = 'lonlat', configfile = file_path, method='distance-weighted' )
  
  #load(paste0(workdir,'/Data_',var.name,'/anom_hindcast_startdate',startdate,'.RData'))  # load hindcast data
  #anom.hindcast<-drop(anom.hindcast)
  
  anom.hind.big[,my.time.interv,,,] <- anom.hindcast
  rm(anom.hindcast)
}

my.FairRpss <- veriApplyBig("FairRpss", fcst=anom.hind.big, obs=anom.rean.big, prob=my.prob, tdim=2, ensdim=1, parallel=TRUE, ncpus=n.cpus)

save(my.FairRpss, file=paste0(workdir,'/Data_',var.name,'/FairRpss_',startdate.name,'.RData'))


#########################################################################################
#                      Alternative way to speed up Load()                               #
#########################################################################################

ERAint <- list(path = '/esnas/reconstructions/ecmwf/eraint/$STORE_FREQ$_mean/$VAR_NAME$_f6h/$VAR_NAME$_$YEAR$$MONTH$.nc')
var.rean=ERAint   # daily reanalysis dataset used for the var data; it can have a different resolution of the MSLP dataset
var.name='sfcWind' #'tas' #'prlr'         # any daily variable we want to find if it is WTs-driven
var <- Load(var = var.name, exp = NULL, obs = list(var.rean), paste0(y,'0101'), storefreq = 'daily', leadtimemax = 1, output = 'lonlat')

# Forecast system list: 
S4 <- list(path = ...)
CFSv2 <- list(path = ...)

# Reanalysis list:
ERAint <- list(path = '/esnas/reconstructions/ecmwf/eraint/$STORE_FREQ$_mean/$VAR_NAME$_f6h/$VAR_NAME$_$YEAR$$MONTH$.nc')
JRA55 <- list(path = ...)




# Select one forecast system and one reanalysis (put NULL if you don't need to load any experiment/observation):
exp.source <- NULL    
obs.source <- list(path = '/esnas/reconstructions/ecmwf/eraint/$STORE_FREQ$_mean/$VAR_NAME$_f6h/$VAR_NAME$_$YEAR$$MONTH$.nc')  

# Select one variable and its frequency:
var.name <- 'sfcWind'
store.freq <- 'daily'

# Extract only the directory path of the forecast and reanalysis:
obs.source2 <- gsub("\\$STORE_FREQ\\$", store.freq, obs.source$path)
obs.source3 <- gsub("\\$VAR_NAME\\$", var.name, obs.source2)
obs.source4 <- strsplit(obs.source3,'/')
obs.source5 <- paste0(obs.source4[[1]][-length(obs.source4[[1]])], collapse="/")

obs.source6 <- list.files(path = obs.source5)

system(paste0("ncks -O -h -d longitude,5,6 ", '/esnas/reconstructions/ecmwf/eraint/',STORE_FREQ,'_mean/',VAR_NAME,'_f6h'))
system("ncks -O -h -d longitude,5,6 sfcWind_201405.nc ~/test.nc")

y <- 1990
var <- Load(var = VAR_NAME, exp = list(exp.source), obs = list(obs.source), sdates = paste0(y,'0101'), storefreq = store.freq, leadtimemax = 1, output = 'lonlat')


} # close if on mare


