# 
print("List of functions : ",quote=FALSE)
print("",quote=FALSE)
print("CFU_load",quote=FALSE)
print("CFU_histo2hindcast",quote=FALSE)
print("CFU_season",quote=FALSE)
print("CFU_clim",quote=FALSE)
print("CFU_ano",quote=FALSE)
print("CFU_ano_crossvalid",quote=FALSE)
print("CFU_smoothing",quote=FALSE)
print("CFU_plotano",quote=FALSE)
print("CFU_plotclim",quote=FALSE)
print("CFU_spread",quote=FALSE)
print("CFU_plotvsltime",quote=FALSE)
print("CFU_plot2varsvsltime",quote=FALSE)
print("CFU_corr",quote=FALSE)
print("CFU_RMS",quote=FALSE)
print("CFU_RMSSS",quote=FALSE)
print("CFU_ratioRMS",quote=FALSE)
print("CFU_ratioSDRMS",quote=FALSE)
print("CFU_regression",quote=FALSE)
print("CFU_trend",quote=FALSE)
print("CFU_consist_trend",quote=FALSE)
print("CFU_plotequimap",quote=FALSE)
print("CFU_plotsection",quote=FALSE)
print("CFU_colorbar",quote=FALSE)
print("CFU_animvsltime",quote=FALSE)
print("CFU_eno",quote=FALSE)
print("CFU_selindices",quote=FALSE)
print("CFU_enlarge",quote=FALSE)
print("CFU_insertdim",quote=FALSE)
print("CFU_mean1dim",quote=FALSE)
print("CFU_meanlistdim",quote=FALSE)
print("CFU_inilistdims",quote=FALSE)
print("",quote=FALSE)
print("For more information about any function, type info_cd('function name')",quote=FALSE)
#
################################################################################
info_cd<-function(name) {

if (name=='CFU_load') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Load experimental data and corresponding observed ones in 2 matrix with similar structures",quote=FALSE)
print("PUT FIRST THE EXPERIMENT ID WITH THE LARGEST NUMBER OF MEMBERS & if possible,",quote=FALSE)
print("THE LARGEST NUMBER OF LEADTIMES. If not possible, fill up the nleadtime argument.",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("- var= 'tas','prlr','tos','g500','g200','ta50','psl','hflsd','hfssd','rls','rss','rsds','uas','vas'",quote=FALSE)
print("       'siaN','sieN','sivN','siaS','sieS','sivS','moc_40N55N_1-2km','moc_30N40N_1-2km'",quote=FALSE)
print("       'max_moc_38N50N_500m-2km','max_moc_40N','heatc','0-315_heatc','373-657_heatc','800-5350_heatc'",quote=FALSE)
print("       'mxl_heatc','NAtl_10N65N_heatc','NAtl_10N65N_0-315_heatc','NAtl_10N65N_373-657_heatc'",quote=FALSE)
print("       'NAtl_10N65N_800-5350_heatc','mxl_NAtl_10N65N_heatc','TAtl_30S30N_heatc','TAtl_30S30N_0-315_heatc'",quote=FALSE)
print("       'TAtl_30S30N_373-657_heatc','TAtl_30S30N_800-5350_heatc','mxl_TAtl_30S30N_heatc','NPac_10N70N_heatc'",quote=FALSE)
print("       'NPac_10N70N_0-315_heatc','NPac_10N70N_373-657_heatc','NPac_10N70N_800-5350_heatc','mxl_NPac_10N70N_heatc'",quote=FALSE)
print("       'TPac_30S30N_heatc','TPac_30S30N_0-315_heatc','TPac_30S30N_373-657_heatc','TPac_30S30N_800-5350_heatc'",quote=FALSE)
print("       'mxl_TPac_30S30N_heatc','Arc_65N90N_heatc','Arc_65N90N_0-315_heatc','Arc_65N90N_373-657_heatc'",quote=FALSE)
print("       'Arc_65N90N_800-5350_heatc','mxl_Arc_65N90N_heatc','Ant_90S60S_heatc','Ant_90S60S_0-315_heatc'",quote=FALSE)
print("       'Ant_90S60S_373-657_heatc','Ant_90S60S_800-5350_heatc','mxl_Ant_90S60S_heatc','TInd_30S30N_heatc'",quote=FALSE)
print("       'TInd_30S30N_0-315_heatc','TInd_30S30N_373-657_heatc','TInd_30S30N_800-5350_heatc','mxl_TInd_30S30N_heatc'",quote=FALSE)
print("- exp=c('EnsEcmwfDec','EnsUkmoDec','EnsCerfacsDec','EnsIfmDec','EnsEcmwfSeas','EnsCmccSeas','EnsIfmSeas'",quote=FALSE)
print("        'EnsMetfrSeas','EnsUkmoSeas','DePreSysAsimDec','DePreSysNoAsimDec','DePreSysAsimSeas','ECMWF_S3Seas',",quote=FALSE)
print("       'ECMWF_S4_sea','ECMWF_S4_ann','hadcm3dec','miroc4dec','miroc5dec','mri-cgcm3dec','cancm4dec1',",quote=FALSE)
print("       'cancm4dec2','cnrm-cm5dec','knmidec','smhidec','mpimdec','gfdldec','cmcc-cmdec','ipsldec','bccdec',",quote=FALSE)
print("       'hadcm3his','miroc4his','miroc5his','mri-cgcm3his','cancm4his','cnrm-cm5his','knmihis','mpimhis',",quote=FALSE)
print("       'gfdlhis','ipslhis','cmcc-cmhis','bcchis','i00k','b013','b014','yve2' ...)",quote=FALSE)
print("- obs=c('ERA40','NCEP','ERAint','20thCv2','GHCN','GHCNERSSTGISS','ERSST','HadISST',",quote=FALSE)
print("       'GPCP','GPCC','CRU','HadSLP','NSIDC','PIOMAS','UCL','DS94','OAFlux',",quote=FALSE)
print("       'DFS4.3','NCDCglo','NCDCland','NCDCoc','GISSglo','GISSland',",quote=FALSE)
print("       'GISSoc','HadCRUT3glo','HadCRUT4','HadSST2oc','CRUTEM3land'",quote=FALSE)
print("- sdates=c('YYYYMMDD','YYYYMMDD')",quote=FALSE)
print("- lonmin, lonmax, latmin, latmax : domain border 0 <= lonmin,lonmax <= 360 ",quote=FALSE)
print("                                   default : world ",quote=FALSE)
print("- nleadtime : optional argument needed only if the first exp does not have the largest number of leadtimes.",quote=FALSE)
print("              default : number of leadtimes of the first experiment.",quote=FALSE)
print("- leadtimemin : output only the leadtimes from leadtimemin. default = 1",quote=FALSE)
print("- leadtimemax : output only the leadtimes before leadtimemax. default = nleadtime",quote=FALSE)
print("- storefreq : frequency at wich are stored the data to be loaded on the repository",quote=FALSE)
print("              'monthly' / 'daily'. Default : 'monthly' ",quote=FALSE)
print("- sampleperiod : to load only a subset between leadtimemin and leadtimemax, ",quote=FALSE)
print("                 with a specified period of subsampling. Default : 1",quote=FALSE)
print("- output = 'areave' / 'lon' / 'lat' / 'lonlat' ",quote=FALSE)
print("         1) Time series of area-averaged variables over the specified domain",quote=FALSE)
print("         2) Time series of meridional averages as a function of longitudes",quote=FALSE)
print("         3) Time series of zonal averages as a function of latitudes",quote=FALSE)
print("         4) Time series of 2d fields",quote=FALSE)
print("            default : 'areave' ",quote=FALSE)
print("- method = 'bilinear' / 'bicubic' / 'conservative' / 'distance-weighted'",quote=FALSE)
print("            Method of interpolation for 'lon' / 'lat' / 'lonlat' output options",quote=FALSE)
print("            default : 'conservative' ",quote=FALSE)
print("- grid   = to choose the output grid ",quote=FALSE)
print("           possible options : rNXxNY or tTRgrid, ex: r96x72, t106grid",quote=FALSE)
print("           default : model grid, argument need to be filled if various exp on various grids",quote=FALSE)
print("- maskmod=list(mask[lon,lat]) = 1/0 : kept/removed grid cell over the entire model domains",quote=FALSE)
print("          Warning : list() compulsory even if 1 model !!!",quote=FALSE)
print("          default : 1 everywhere ",quote=FALSE)
print("- maskobs=list(mask[lon,lat]) = 1/0 : kept/removed grid cell over the entire",quote=FALSE)
print("          observed domains, only necessary for 'areave' output option ",quote=FALSE)
print("          Warning : list() compulsory even if 1 dataset !!!",quote=FALSE)
print("          default : 1 everywhere ",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("$mod = model outputs",quote=FALSE)
print("$obs = observations",quote=FALSE)
print("$lat = latitudes of the model grid",quote=FALSE)
print("$lon = longitudes of the model grid",quote=FALSE)
print("",quote=FALSE) 
print(" 2 matrix with dimensions ",quote=FALSE)
print(" c(nmod/nexp or nobs, nmemb/nparam, nsdates, nltime) if output   = 'areave'",quote=FALSE)
print(" c(nmod/nexp or nobs, nmemb/nparam, nsdates, nltime, nlat )  if  = 'lat'",quote=FALSE)
print(" c(nmod/nexp or nobs, nmemb/nparam, nsdates, nltime, nlon )  if  = 'lon'  ",quote=FALSE)
print(" c(nmod/nexp or nobs, nmemb/nparam, nsdates, nltime, nlat, nlon) = 'lonlat'",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> March 2011",quote=FALSE)
}

if (name=='CFU_histo2hindcast') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" This function reorganizes a long run (historical typically) with only one start date into chunks ",quote=FALSE)
print(" corresponding to a set of start dates. The expected input structure is the one output from CFU_load ",quote=FALSE)
print(" with 4 to 7 dimensions ",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("- varin         = input model or observational data : ",quote=FALSE)
print("                 c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to",quote=FALSE)
print("                 c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("- sdatesin      = start date of the input matrix 'YYYYMMDD' ",quote=FALSE)
print("- sdatesout     = list of start dates of the output matrix c('YYYYMMDD','YYYYMMDD' ..) ",quote=FALSE)
print("- nleadtimesout = number of leadtimes in the output matrix",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" A matrix with the same number of dimensions as the input one, the same dimensions 1 and 2",quote=FALSE)
print(" and potentially the same dimensions 5 to 7. Dimensions 3 and 4 are set by the arguments sdatesout",quote=FALSE) 
print(" and nleadtimesout",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> November 2012",quote=FALSE)
}

if (name=='CFU_clim') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" This function computes per-pair climatologies from experimental and observational matrix output from CFU_load ",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("- var_exp    = model data : ",quote=FALSE)
print("              c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to",quote=FALSE)
print("              c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("- var_obs    = observational data :",quote=FALSE) 
print("              c(nobs, nmemb, nsdates, nltime) up to",quote=FALSE)
print("              c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("- memb       = T/F (1 climatology for each member). Default = T ",quote=FALSE)
print("- kharin     = T/F (if Kharin method is applied or not). Default = F",quote=F)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("$clim_exp")
print("$clim_obs")
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> March 2011",quote=FALSE)
}

if (name=='CFU_ano') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("This function computes raw anomalies from experimental or observational matrix output from CFU_load and their climatologies output from CFU_clim",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("- var  = model or observational data : ",quote=FALSE)
print("          c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to",quote=FALSE)
print("          c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)               
print("- clim = climatologies from CFU_clim",quote=FALSE)
print("          c(nmod/nexp/nobs, nmemb/nparam, nltime) up to",quote=FALSE)
print("          c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("          or ",quote=FALSE)
print("          c(nmod/nexp/nobs, nltime) up to",quote=FALSE)
print("          c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-ano    : matrix with same dimensions as var",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> March 2011",quote=FALSE)
}

if (name=='CFU_ano_crossvalid') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("This function computes raw anomalies from experimental and observational matrix output from CFU_load",quote=FALSE)
print("by subtracting the climatologies computed in a cross-validation mode and with a per-pair method",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("- var_exp    = model data : ",quote=FALSE)
print("              c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to",quote=FALSE)
print("              c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("- var_obs    = observational data :",quote=FALSE)
print("              c(nobs, nmemb, nsdates, nltime) up to",quote=FALSE)
print("              c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("- memb       = T/F (1 climatology for each member). Default = T ",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("$ano_exp")
print("$ano_obs")
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> December 2011",quote=FALSE)
}

if (name=='CFU_smoothing') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Smoothes time-series organized in a matrix of any number of dimensions up to 10 dimensions (arbitrary choice, can be enlarged if needed --> ask Virginie )",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var        : Matrix in which are the time-series to smooth",quote=FALSE)
print("-runmeanlen : Running mean length in number of time-steps (typically months) ",quote=FALSE)
print("-numdimt    : Dimension along with to smooth",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-smt_ano    : matrix with same dimensions as var and smoothed time-series along the (numdimt)th dimension",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> March 2011",quote=FALSE)
}

if (name=='CFU_season') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Computes seasonal means on time-series organized in a matrix of any number of dimensions up to 10 dimensions",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var        : Matrix in which are the time-series",quote=FALSE)
print("-posdim     : Rank of the dimension along with to compute seasonal means",quote=FALSE)
print("-monini     : Position in the year of the first month of the time-series : 1 to 12",quote=FALSE)
print("-moninf     : Position in the year of the month when to start the seasonal means : 1 to 12",quote=FALSE)
print("-monsup     : Position in the year of the month when to stop the seasonal means : 1 to 12,",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-varout     : matrix with same dimensions as var except along the (posdim)th dimension which length",quote=FALSE)
print("              corresponds to the number of seasons. Partial seasons are not accounted for.",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> March 2011",quote=FALSE)
}



if (name=='CFU_plotano') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" Plots time-series of raw or smoothed anomalies of any index output from CFU_load or CFU_ano or CFU_smoothed and organized in matrix with dimensions :",quote=FALSE)
print("   c(nmod/nexp, nmemb/nparam, nsdates, nltime)",quote=FALSE)
print("   c(nobs, nmemb, nsdates, nltime)",quote=FALSE)
print("",quote=FALSE)
print(" One plot per experiment ",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-exp_ano  : Matrix with experimental data : ",quote=FALSE)
print("            c(nmod/nexp, nmemb/nparam, nsdates, nltime)",quote=FALSE)
print("-obs_ano  : Matrix with observational data",quote=FALSE)
print("             c(nobs, nmemb, nsdates, nltime), optional ",quote=FALSE)
print("-sdates   : list of starting dates : c('YYYYMMDD','YYYYMMDD')",quote=FALSE)
print("-toptitle : Main title for each experiment : c('',''), optional ",quote=FALSE)
print("-ytitle   : Title of Y-axis for each experiment : c('',''), optional",quote=FALSE)
print("-limits   : c(lower limit, upper limit) : limits of the Y-axis, optional",quote=FALSE)
print("-legends  : list of observational dataset names, optional",quote=FALSE)
print("-freq     : 1=yearly, 12=monthly, 4=seasonal ... Default : 12 ",quote=FALSE)
print("-biglag   : T/F for presentation/paper plot, Default = F",quote=FALSE)
print("-fill     : T/F if filled spread between members. Default = T ",quote=FALSE)
print("-memb     : T/F if all members/ensemble-mean only should be plotted.",quote=FALSE)
print("             Default=T",quote=FALSE)
print("-ensmean  : T/F if the ensemble-mean should be plotted. Default = T",quote=FALSE)
print("-linezero : T/F if a line at y=0 should be added. Default = F",quote=FALSE)
print("-points   : T/F if points instead of lines. Default = F",quote=FALSE)
print("-vlines   : list of x location where to add vertical black lines, optional",quote=FALSE)
print("-fileout  : Name of output ps file for each experiment : c('','')",quote=FALSE)
print("-sizetit   : multiplicative factor to scale title size, optional",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> March 2011",quote=FALSE)
}

if (name=='CFU_plotclim') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Plots time-series of climatologies of any index output from CFU_clim and organized in matrix with dimensions :",quote=FALSE)
print("  c(nmod/nexp, nmemb/nparam, nltime)",quote=FALSE)
print("  c(nobs, nmemb, nltime)",quote=FALSE)
print("",quote=FALSE)
print("One plot for all experiments",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-exp_clim : Matrix with experimental data : ",quote=FALSE)
print("            c(nmod/nexp, nmemb/nparam, nltime)",quote=FALSE)
print("-obs_clim : Matrix with observational data, optional",quote=FALSE)
print("            c(nobs, nmemb, nltime) ",quote=FALSE)
print("-toptitle : Main title, optional ",quote=FALSE)
print("-ytitle   : Title of Y-axis, optional ",quote=FALSE)
print("-monini   : starting month between 1 and 12. Default = 1",quote=FALSE)
print("-freq     : 1=yearly, 12=monthly, 4=seasonal ... Default = 12",quote=FALSE)
print("-limits   : c(lower limit, upper limit) : limits of the Y-axis, optional",quote=FALSE)
print("-listexp  : list of experiment names, optional",quote=FALSE)
print("-listobs  : list of observational dataset names, optional",quote=FALSE)
print("-biglag   : T/F for presentation/paper plot. Default = F",quote=FALSE)
print("-fileout  : Name of output ps file",quote=FALSE)
print("-sizetit   : multiplicative factor to scale title size, optional",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> March 2011",quote=FALSE)
}

if (name=='CFU_spread') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Compute InterQuartile Range, Maximum-Mininum, Standard Deviation and Median Absolute Deviation along the (posdim)th dimension of matrix var",quote=FALSE)
print("The confidence interval is computed by bootstrapping",quote=FALSE)
print("",quote=FALSE)
print("Example :",quote=FALSE)
print("---------",quote=FALSE)
print("To compute IQR, Max-Min, SD & MAD accross members and start dates of var output from CFU_load or CFU_ano, call",quote=FALSE)
print("           CFU_spread(var, posdim = c(2,3), narm=T)",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var    : Matrix of any number of dimensions up to 10 ",quote=FALSE)
print("-posdim : Dimensions along which to compute IQR/MaxMin/SD/MAD",quote=FALSE)
print("-narm   : T/F if NA removed/kept before computation. Default = T ",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Matrix with same dimensions as var except along the first posdim dimension which is replaced by a length 3 dimension, corresponding to the lower limit of the 95% confidence interval, the computed spread over the whole sample and the upper limit of the 95% confidence interval for each point of the matrix along all the other dimensions except for the other posdim dimensions which disappear.",quote=FALSE)
print("",quote=FALSE)
print("",quote=FALSE)
print("$iqr    : InterQuartile Range",quote=FALSE)
print("$maxmin : Maximum - Minimum",quote=FALSE)
print("$sd     : Standard Deviation",quote=FALSE)
print("$mad    : Median Value",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> March 2011",quote=FALSE)
}

if (name=='CFU_corr') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Matrix var_exp & var_obs should have the same dimensions except along posloop where the length can be different (nexp & nobs).",quote=FALSE)
print("CFU_corr compute correlation for each jexp in 1:nexp and each jobs in 1:nobs which gives nexp x nobs correlation for each ",quote=FALSE)
print("other grid point of the matrix. The correlations are computed along the poscor dimension. If compROW is given, the correlation are",quote=FALSE)
print("computed only if rows along the (compROW)th dimension are complete between limits[1] and limits[2], ",quote=FALSE)
print("that  mean with no NA between limits[1] and limits[2]. Default : limits[1]=1 and limits[2]=length(compROW dimension).",quote=FALSE)
print("The confidence interval is computed by a Fisher transformation",quote=FALSE)
print("The significance level relies on a one-sided student-T distribution",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var_exp : matrix of experimental data",quote=FALSE)
print("-var_obs : matrix of observational data, same dimensions as var_exp",quote=FALSE)
print("           except along posloop",quote=FALSE)
print("-posloop : dimension nobs and nexp",quote=FALSE)
print("-poscor  : dimension along which correlation are to be computed",quote=FALSE)
print("-compROW : data taken into account only if (compROW)th row is complete.",quote=FALSE)
print("           Default = NULL",quote=FALSE)
print("-limits  : complete between limits[1] & limits[2]. Default = NULL",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-corr    : Matrix with c(length(posloop) in var_exp, length(posloop) in var_obs, 4, all other dimensions of var_exp & var_obs except poscor)",quote=FALSE)
print("           The third dimension of length 4 corresponds to the lower limit of the  95% confidence interval, the computed correlation, the upper limit of the 95% confidence interval and the 95% significance level given by a one-sided T-test",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> April 2011",quote=FALSE)
}

if (name=='CFU_RMS') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Matrix var_exp & var_obs should have the same dimensions except along posloop where the length can be different (nexp & nobs).",quote=FALSE)
print("CFU_RMS compute for each grid point the Root Mean Square difference along the posRMS dimension between each model data in 1:nexp",quote=FALSE)
print(" and each observation in 1:nobs which gives nexp x nobs RMS dif for each other grid point of the matrix.",quote=FALSE)
print("The confidence interval relies on a chi2 distribution",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var_exp : matrix of experimental data",quote=FALSE)
print("-var_obs : matrix of observational data, same dimensions as var_exp",quote=FALSE)
print("           except along posloop",quote=FALSE)
print("-posloop : dimension nobs and nexp",quote=FALSE)
print("-posRMS  : dimension along which RMSE are to be computed",quote=FALSE)
print("-compROW : data taken into account only if (compROW)th row is complete.",quote=FALSE)
print("           Default = NULL",quote=FALSE)
print("-limits  : complete between limits[1] & limits[2]. Default = NULL",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-rms     : Matrix with c(length(posloop) in var_exp, length(posloop) in var_obs, 3, all other dimensions of var_exp & var_obs except posRMS)",quote=FALSE)
print("           The dimension 3 corresponds to the lower limit of the  95% confidence interval, the computed RMSE and the upper limit of the 95% confidence interval",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> May 2011",quote=FALSE)
}

if (name=='CFU_RMSSS') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Matrix var_exp & var_obs should have the same dimensions except along posloop where the length can be different (nexp & nobs).",quote=FALSE)
print("CFU_RMSSS compute for each grid point the Root Mean Square Skill Score along the posRMS dimension for each model in 1:nexp ",quote=FALSE)
print("against each observational data in 1:nobs which gives nexp x nobs RMSSS for each other grid point of the matrix.",quote=FALSE)
print("The p-value is provided by a one-sided Fisher test",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var_exp : matrix of experimental data",quote=FALSE)
print("-var_obs : matrix of observational data, same dimensions as var_exp",quote=FALSE)
print("           except along posloop",quote=FALSE)
print("-posloop : dimension nobs and nexp",quote=FALSE)
print("-posRMS  : dimension along which RMSE are to be computed",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-rms     : Matrix with c(length(posloop) in var_exp, length(posloop) in var_obs, 2, all other dimensions of var_exp & var_obs except posRMS)",quote=FALSE)
print("           The dimension 2 corresponds to the RMSSS and the p.value of the one-sided Fisher test with Ho: RMSSS=0",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> April 2012",quote=FALSE)
}

if (name=='CFU_ratioRMS') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Matrix var_exp1 / var_exp2 / var_obs should have the same dimensions.",quote=FALSE)
print("The ratio RMSE(var_exp1,var_obs) / RMSE(var_exp2,var_obs) is output.",quote=FALSE)
print("The p-value is provided by a two-sided Fischer test",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var_exp1: matrix of experimental data 1",quote=FALSE)
print("-var_exp2: matrix of experimental data 2, same dimensions as var_exp1",quote=FALSE)
print("-var_obs : matrix of observational data, same dimensions as var_exp1",quote=FALSE)
print("-posRMS  : dimension along which RMS are to be computed",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-ratiorms: Matrix with the same dimensions than var_exp1/var_exp2/var_obs except along posRMS where the dimension has length 2",quote=FALSE)
print("           The dimension 2 corresponds to the ratio between the computed RMSE (RMSE1/RMSE2) and the p.value of the two-sided Fisher test with Ho: RMSE1/RMSE2=1 ",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> November 2011",quote=FALSE)
}

if (name=='CFU_ratioSDRMS') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Matrix var_exp & var_obs should have the common diagnostic structure :",quote=FALSE)
print("between c(nmod/nexp, nmemb/nparam, nsdates, nltime)",quote=FALSE)
print("and     c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("The ratio between the standard deviation of the members around the ensemble mean in var_exp",quote=FALSE)
print("and the RMSE between var_exp and var_obs is output",quote=FALSE)
print("for each experiment and each observational dataset",quote=FALSE)
print("The p-value is provided by a one-sided Fischer test",quote=FALSE)
print("",quote=FALSE)
print("- var_exp    = model data : ",quote=FALSE)
print("              c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to",quote=FALSE)
print("              c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("- var_obs    = observational data :",quote=FALSE)
print("              c(nobs, nmemb, nsdates, nltime) up to",quote=FALSE)
print("              c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-ratiosdrms: Matrix with c(nexp/nmod, nobs, 2, nltime) up to",quote=FALSE)
print("                         c(nexp/nmod, nobs, 2, nltime, nlevel, nlat, nlon) dimensions",quote=FALSE)
print("             The dimension 2 corresponds to the ratio (SD/RMSE) and the p.value of the one-sided Fisher test with Ho: SD/RMSE=1 ",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> December 2011",quote=FALSE)
}

if (name=='CFU_trend') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Compute trends along the (posTR)th dimension of matrix var by least square fitting, and the associated an error interval.",quote=FALSE)
print("Provide also the detrended data",quote=FALSE)
print("The confidence interval relies on a student-T distribution",quote=FALSE)
print("",quote=FALSE)
print(" Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var       : Matrix of any number of dimensions up to 10 ",quote=FALSE)
print("-posTR     : Position along which to compute trends",quote=FALSE)
print("-interval  : number of months between 2 points along posTR dimension",quote=FALSE) 
print("             Default = 1",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("$trend     : same dimensions as var except along posTR dimension which is replaced by a length 3 dimension, corresponding to the lower limit of the  95% confidence interval, the computed trends and the upper limit of the 95% confidence interval for each point of the matrix along all the other dimensions",quote=FALSE)
print("$detrended : same dimensions as var with linearly detrended var along the posTR dimension",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> May 2011",quote=FALSE)
}

if (name=='CFU_regression') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Compute the regression of matrice vary on matrice varx along the (posREG)th dimension",quote=FALSE)
print("by least square fitting. Provides the slope of the regression, the associated confidence interval, and the intercept.",quote=FALSE)
print("Provide also the vary data filtered out from the regression onto varx.",quote=FALSE)
print("The confidence interval relies on a student-T distribution",quote=FALSE)
print("",quote=FALSE)
print(" Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-vary      : Matrix of any number of dimensions up to 10 ",quote=FALSE)
print("-varx      : Matrix of any number of dimensions up to 10 ",quote=FALSE)
print("-posREG    : Position along which to compute the regression",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("$regression     : same dimensions as varx and vary except along posREG dimension which is replaced",quote=FALSE)
print("by a length 4 dimension, corresponding to the lower limit of the  95% confidence interval, the computed slope and",quote=FALSE)
print("the upper limit of the 95% confidence interval and the intercept for each point of the matrice along all the other dimensions",quote=FALSE)
print("$filtered : same dimensions as vary filtered out from the regression onto varx along the posREG dimension.",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> May 2013",quote=FALSE)
}

if (name=='CFU_consist_trend') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Compute trends by least square fitting and the associated error interval for both the observational and model data.",quote=FALSE)
print("Provide also the detrended observational and modelled data",quote=FALSE)
print("The trend is computed along the start date dimension",quote=FALSE)
print("",quote=FALSE)
print(" Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var_exp   : ensemble mean of model hindcasts with dimensions : ",quote=FALSE)
print("             c(nmod/nexp, nsdates, nltime) up to",quote=FALSE)
print("             c(nmod/nexp, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("-var_obs   : ensemble mean of observational data with dimensions :",quote=FALSE)
print("             c(nobs, nsdates, nltime) up to",quote=FALSE)
print("             c(nobs, nsdates, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("-interval  : number of months between 2 start dates. Default = 1",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("$trend        : trends of model and observational data same dimensions with dimensions :",quote=FALSE)
print("                c(nmod/nexp+nobs, 3, nltime) up to",quote=FALSE)
print("                c(nmod/nexp+nobs, 3, nltime, nlevel, nlat, nlon)",quote=FALSE)
print("                The length 3 dimension corresponds to the lower limit of the  95% confidence interval, the computed trends and the upper limit of the 95% confidence interval",quote=FALSE)
print("$detrendedmod : same dimensions as var_exp with linearly detrended var along the start date dimension",quote=FALSE)
print("$detrendedobs : same dimensions as var_obs with linearly detrended var along the start date dimension",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> Nov 2011",quote=FALSE)
}

if (name=='CFU_eno') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Compute the effective number of independant observations along the (posdim)th dimension of an observational matrix. This effective number of independant observations may be required to perform statistical tests.")
print("",quote=FALSE)
print(" Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-obs       : Observational matrix of any number of dimensions up to 10 ",quote=FALSE)
print("-posdim    : Position along which to compute the effective number of observations ",quote=FALSE)
print("",quote=FALSE)
print(" Outputs",quote=FALSE)
print("~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-effnumobs : same dimensions as var except without posdim dimension",quote=FALSE)
print("",quote=FALSE)
print("Example of input :",quote=FALSE)
print("-------------------",quote=FALSE)
print("",quote=FALSE)
print(" Output from CFU_load/CFU_ano/CFU_smoothing ",quote=FALSE) 
print("        with dimensions (nobs, nmemb, sdate, nltime, nlat, nlon)",quote=FALSE)
print("        send with argument posdim=3 to get the number of independant",quote=FALSE)
print("        observations along the starting date dimensions",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" Based on eno function from Caio Coelho",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> May 2011",quote=FALSE)
}

if (name=='CFU_plotequimap') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Map two dimensional matrix with (longitude, latitude) dimensions in",quote=FALSE)
print("cylindrical equidistant latitude and longitude projection",quote=FALSE)
print("",quote=FALSE)
print(" Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var       : matrix to plot with (longitude, latitude) dimensions",quote=FALSE)
print("-lon       : array of longitudes",quote=FALSE)
print("-lat       : array of latitudes",quote=FALSE)
print("-toptitle  : title, optional",quote=FALSE)
print("-sizetit   : multiplicative factor to increase title size, optional",quote=FALSE)
print("-brks      : colour levels, optional",quote=FALSE)
print("-cols      : list of colours, optional",quote=FALSE)
print("-square    : map with squares (TRUE) for each grid points",quote=FALSE)
print("             or smoothing (FALSE). Default : TRUE",quote=FALSE)
print("-filled.continents : continents filled in grey (TRUE) or represented",quote=FALSE)
print("                    by a black line (FALSE). Default = TRUE",quote=FALSE)
print("                    filling unavailable if crossing Greenwich",quote=FALSE)
print("                    filling unavailable if square=FALSE",quote=FALSE)
print("-contours  : matrix to add to the plot with contours. Default = NULL",quote=FALSE)
print("-brks2     : contour levels, optional",quote=FALSE)
print("-dots      : matrix with TRUE / FALSE flags to add black dots",quote=FALSE)
print("             option only available if square = TRUE",quote=FALSE)
print("-axelab    : TRUE/FALSE, label the axis. Default = TRUE",quote=FALSE)
print("-intylat   : interval between latitude ticks on y-axis. Default : 20deg",quote=FALSE)
print("-intxlon   : interval between longitude ticks on x-axis. Default : 20deg",quote=FALSE)
print("-drawleg   : draw colorbar. Can be FALSE only if square=FALSE.",quote=FALSE)
print("             Must be FALSE if numbfig > 1. ",quote=FALSE)
print("             Default : T",quote=FALSE) 
print("-subsampleg: Supsampling factor of the interval between ticks on colorbar. ",quote=FALSE)
print("             Default : 1 = every colour level",quote=FALSE)
print("-numbfig   : Number of figures in the final multipanel",quote=FALSE) 
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> November 2011",quote=FALSE)
}

if (name=='CFU_plotsection') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Plot a (longitude,depth) or (latitude,depth) section",quote=FALSE)
print("",quote=FALSE)
print(" Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var       : matrix to plot with (longitude/latitude, depth) dimensions",quote=FALSE)
print("-horiz     : array of longitudes/latitudes",quote=FALSE)
print("-depth     : array of depths",quote=FALSE)
print("-toptitle  : title, optional",quote=FALSE)
print("-sizetit   : multiplicative factor to increase title size, optional",quote=FALSE)
print("-brks      : colour levels, optional",quote=FALSE)
print("-cols      : list of colours, optional",quote=FALSE)
print("-axelab    : TRUE/FALSE, label the axis. Default = TRUE",quote=FALSE)
print("-intydep   : interval between depth ticks on y-axis. Default : 200m",quote=FALSE)
print("-intxhoriz : interval between longitude/latitude ticks on x-axis. Default : 20deg",quote=FALSE)
print("-drawleg   : draw colorbar. Default : TRUE",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> September 2012",quote=FALSE)
}

if (name=='CFU_colorbar') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Creates a horizontal or vertical colorbar to introduce in multipanels",quote=FALSE)
print("",quote=FALSE)
print(" Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-brks      : levels",quote=FALSE)
print("-cols      : list of colours, optional",quote=FALSE)
print("-vert      : TRUE/FALSE for vertical/horizontal colorbar",quote=FALSE)
print("-subsampleg: Supsampling factor of the interval between ticks on colorbar. ",quote=FALSE)
print("             Default : 1 = every level",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> April 2012",quote=FALSE)
}

if (name=='CFU_animvsltime') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Create animations showing the anomalies, the climatologies, the mean InterQuartile Range, Maximum-Mininum, Standard Deviation, Median Absolute Deviation, the trends, the RMSE or correlation between modelled and observed data along the forecast time for all input experiments & input observational datasets",quote=FALSE)
print("",quote=FALSE)
print("One plot for each experiment for IQR/Max-Min/SD/MAD/clim/trends",quote=FALSE)
print("One plot for each experiment/obervational dataset combination for correlations & RMSE",quote=FALSE)
print("",quote=FALSE)
print("Input var should have dimensions (nltime, nlat, nlon)",quote=FALSE)
print("                              or (nexp/nmod, nltime, nlat, nlon)",quote=FALSE)
print("                              or (nexp/nmod, 3 ,nltime, nlat, nlon)",quote=FALSE)
print("                              or (nexp/nmod, nobs, 3 ,nltime, nlat, nlon)",quote=FALSE)
print("",quote=FALSE)
print("Examples of input :",quote=FALSE)
print("-------------------",quote=FALSE)
print("",quote=FALSE)
print(" 1-Outputs from CFU_clim (exp, obs, memb=F) :",quote=FALSE)
print("                                      (nmod, nltime, nlat, nlon)",quote=FALSE)
print("                                   or (nobs, nltime, nlat, nlon)",quote=FALSE)
print("",quote=FALSE)
print(" 2-model output from CFU_load/CFU_ano/CFU_smoothing : ",quote=FALSE)
print("                                      (nmod, nmemb, sdate, nltime, nlat, nlon)",quote=FALSE)
print("   then passed through CFU_spread(var, posdim=2, narm=T)",quote=FALSE)
print("                     & CFU_mean1dim(var, posdim = 3, narm=T) : ",quote=FALSE)
print("   or through CFU_trend(CFU_mean1dim(var,2), posTR=2)        : ",quote=FALSE)
print("                                      (nmod, 3, nltime, nlat, nlon)",quote=FALSE)
print("   animates average along start dates of IQR/MaxMin/SD/MAD across members or trends of the ensemble-mean computed accross the start dates",quote=FALSE)
print("",quote=FALSE)
print(" 3-model and observed output from CFU_load/CFU_ano/CFU_smoothing : ",quote=FALSE)
print("                                      (nmod, nmemb, sdate, nltime, nlat, nlon)",quote=FALSE)
print("                                    & (nobs, nmemb, sdate, nltime, nlat, nlon)",quote=FALSE)
print("   then averaged along members CFU_mean1dim(var_exp/var_obs,posdim=2) :  ",quote=FALSE)
print("                                      (nmod, sdate, nltime, nlat, nlon)      ",quote=FALSE)
print("                                    & (nobs, sdate, nltime, nlat, nlon)",quote=FALSE)
print("   then passed through CFU_corr(exp, obs, posloop=1, poscor=2) : ",quote=FALSE)
print("                    or CFU_RMS(exp, obs, posloop=1, posRMS=2)  :",quote=FALSE)
print("                                      (nmod, nobs, 3, nltime, nlat, nlon)    ",quote=FALSE) 
print("   animates correlations or RMS between each exp & each obs against leadtime",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var      : Matrix of dimensions :",quote=FALSE)
print("                            (nltime, nlat, nlon) ",quote=FALSE)
print("                            (nexp/nmod, nltime, nlat, nlon) ",quote=FALSE)
print("                            (nexp/nmod, 3 ,nltime, nlat, nlon) ",quote=FALSE)
print("                         or (nexp/nmod, nobs, 3 ,nltime, nlat, nlon)",quote=FALSE)
print("-lat      : vector containing latitudes (°)",quote=FALSE)
print("-lon      : vector containing longtitudes (°)",quote=FALSE)
print("-toptitle : c('','') array of main title for each animation, optional ",quote=FALSE)
print("            If RMS or correlations : first exp with successive obs, ",quote=FALSE) 
print("            then second exp with successive obs, etc ... ",quote=FALSE)
print("-units    : units, optional  ",quote=FALSE)
print("-monini   : starting month between 1 and 12. Default = 1",quote=FALSE)
print("-freq     : 1=yearly, 12=monthly, 4=seasonal ... Default = 12",quote=FALSE)
print("-msk95lev : T/F grid points masked if 95% significance level not reached",quote=FALSE)
print("            Default = F ",quote=FALSE)
print("-brk      : limits of colour levels, optional",quote=FALSE)
print("            ex : seq(min(var),max(var),(max(var)-min(var))/10) ",quote=FALSE)
print("-col      : vector of colours of length(brk)-1, optional",quote=FALSE)
print("-lonmin   : Westward limit of the domain to plot (>0 or <0). Default : 0°",quote=FALSE)
print("-lonmax   : Eastward limit of the domain to plot (>0 or <0). ",quote=FALSE)
print("            lonmax > lonmin. Default : 360°",quote=FALSE)
print("-latmin   : Southward limit of the domain to plot. Default : -90°",quote=FALSE)
print("-latmax   : Northward limit of the domain to plot. Default : 90°",quote=FALSE)
print("-center   : (latitude, longitude, angle) for stereographic projection",quote=FALSE)
print("-equi     : TRUE/FALSE == cylindrical equidistant/stereographic projection.",quote=FALSE)
print("            Default : TRUE",quote=FALSE)
print("-fileout  : c('','') array of output file name for each animation ",quote=FALSE)
print("            without extension. If RMS or correlations : first exp ",quote=FALSE)
print("            with successive obs, then second exp with successive obs, etc ...",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> May 2011",quote=FALSE)
}

if (name=='CFU_plotvsltime') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Plots mean InterQuartile Range, Maximum-Mininum, Standard Deviation, Median Absolute Deviation, the trends, the RMS and correlation between modelled and observed data against the forecast time for all input experiments.",quote=FALSE)
print("",quote=FALSE)
print("One plot for all experiments",quote=FALSE)
print("Input var should have dimensions (nexp/nmod, 3 ,nltime)",quote=FALSE)
print("                              or (nexp/nmod, nobs, 3 ,nltime)",quote=FALSE)
print("",quote=FALSE)
print("Examples of input :",quote=FALSE)
print("-------------------",quote=FALSE)
print("",quote=FALSE)
print(" 1-model output from CFU_load/CFU_ano/CFU_smoothing : ",quote=FALSE)
print("                                      (nmod, nmemb, sdate, nltime)",quote=FALSE)
print("   then passed through CFU_spread(var, posdim=2, narm=T)",quote=FALSE)
print("                     & CFU_mean1dim(var, posdim = 3, narm=T) : ",quote=FALSE)
print("   or through CFU_trend(CFU_mean1dim(var,2), posTR=2)        : ",quote=FALSE)
print("                                      (nmod, 3, nltime)",quote=FALSE)
print("   plots average along start dates of IQR/MaxMin/SD/MAD across members or trends of the ensemble-mean computed accross the start dates",quote=FALSE)
print("",quote=FALSE)
print(" 2-model and observed output from CFU_load/CFU_ano/CFU_smoothing : ",quote=FALSE)
print("                                      (nmod, nmemb, sdate, nltime)",quote=FALSE)
print("                                    & (nobs, nmemb, sdate, nltime)",quote=FALSE)
print("   then averaged along members CFU_mean1dim(var_exp/var_obs,posdim=2) :  ",quote=FALSE)
print("                                      (nmod, sdate, nltime)      ",quote=FALSE)
print("                                    & (nobs, sdate, nltime)",quote=FALSE)
print("   then passed through CFU_corr(exp, obs, posloop=1, poscor=2) : ",quote=FALSE)
print("                    or CFU_RMS(exp, obs, posloop=1, posRMS=2)  :",quote=FALSE)
print("                                      (nmod, nobs, 3, nltime)    ",quote=FALSE)
print("   plots correlations or RMS between each exp & each obs against leadtime",quote=FALSE)
print("",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var      : Matrix of dimensions :",quote=FALSE)
print("                            (nexp/nmod, 3 ,nltime) ",quote=FALSE)
print("                         or (nexp/nmod, nobs, 3 ,nltime)",quote=FALSE)
print("-toptitle : Main title, optional",quote=FALSE)
print("-ytitle   : Title of Y-axis, optional  ",quote=FALSE)
print("-monini   : starting month between 1 and 12. Default = 1",quote=FALSE)
print("-freq     : 1=yearly, 12=monthly, 4=seasonal ... Default = 12",quote=FALSE)
print("-nticks   : Number of ticks and labels on the x-axis, optional",quote=FALSE)
print("-limits   : c(lower limit, upper limit) : limits of the Y-axis, optional",quote=FALSE)
print("-listexp  : list of experiment names, optional",quote=FALSE)
print("-listobs  : list of observation names, optional",quote=FALSE)
print("-biglag   : T/F for presentation/paper plot. Default = F",quote=FALSE)
print("-hlines   : c(a,b, ..) Add horizontal black lines at Y-positions a,b, ...",quote=FALSE)
print("            Default = NULL  ",quote=FALSE)
print("-leg      : T/F if legend should be added or not to the plot. Default = T",quote=FALSE)
print("-siglev   : T/F if significance level should replace confidence interval.",quote=FALSE)
print("            Default = F",quote=FALSE)
print("-fileout  : Name of output ps file",quote=FALSE)
print("-sizetit   : multiplicative factor to change title size, optional",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <vguemas@ic3.cat> March 2011",quote=FALSE)
print(" Modified <isabel.andreu-burillo@ic3.cat> March 2013",quote=FALSE)
print(" - Introduced parameter sizetit",quote=FALSE)
}
#
if (name=='CFU_plot2varsvsltime') {
print("",quote=FALSE)
print(" Description ",quote=FALSE)
print("~~~~~~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("Plots two input variables havind the same dimensions in a common plot.",quote=FALSE)
print("",quote=FALSE)
print("One plot for all experiments",quote=FALSE)
print("Input variables should have dimensions (nexp/nmod, nltime)",quote=FALSE)
print("",quote=FALSE)
print("Examples of input :",quote=FALSE)
print("-------------------",quote=FALSE)
print("",quote=FALSE)
print(" RMSE error for a number of experiments and along lead-time : ",quote=FALSE)
print("                                      (nexp, nltime)",quote=FALSE)
print("Inputs",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print("-var1      : Matrix of dimensions :",quote=FALSE)
print("                            (nexp/nmod, nltime) ",quote=FALSE)
print("-var2      : Matrix of dimensions :",quote=FALSE)
print("                            (nexp/nmod, nltime) ",quote=FALSE)
print("-toptitle : Main title, optional",quote=FALSE)
print("-ytitle   : Title of Y-axis, optional  ",quote=FALSE)
print("-monini   : starting month between 1 and 12. Default = 1",quote=FALSE)
print("-freq     : 1=yearly, 12=monthly, 4=seasonal ... Default = 12",quote=FALSE)
print("-nticks   : Number of ticks and labels on the x-axis, optional",quote=FALSE)
print("-limits   : c(lower limit, upper limit) : limits of the Y-axis, optional",quote=FALSE)
print("-listexp  : list of experiment names, up to three, optional",quote=FALSE)
print("-listvars  : list of names of input variables, optional",quote=FALSE)
print("-biglag   : T/F for presentation/paper plot. Default = F",quote=FALSE)
print("-hlines   : c(a,b, ..) Add horizontal black lines at Y-positions a,b, ...",quote=FALSE)
print("            Default = NULL  ",quote=FALSE)
print("-leg      : T/F if legend should be added or not to the plot. Default = T",quote=FALSE)
print("-siglev   : T/F if significance level should replace confidence interval.",quote=FALSE)
print("            Default = F",quote=FALSE)
print("-sizetit   : multiplicative factor to change title size, optional",quote=FALSE)
print("-fileout  : Name of output ps file",quote=FALSE)
print("-show_conf  : T/F to show/not confidence intervals for input variables",quote=FALSE)
print("",quote=FALSE)
print(" Author ",quote=FALSE)
print("~~~~~~~~",quote=FALSE)
print("",quote=FALSE)
print(" CFUers <isabel.andreu-burillo@ic3.cat> March 2013",quote=FALSE)
}

}
################################################################################
CFU_load<-function(var, exp, obs=NULL, sdates, lonmin=0, lonmax=360, latmin=-90, latmax=90, nleadtime=NULL, nmember=NULL, leadtimemin=1, leadtimemax=NULL, storefreq='monthly', sampleperiod=1, output='areave', method='conservative', grid=NULL, maskmod=list(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), maskobs=list(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)) {
#===============================================================================
#
# Get matrix dimensions
# ~~~~~~~~~~~~~~~~~~~~~~~~
nmod=length(exp)
nmemb=9
nobs=length(obs)
nsdates=length(sdates)
dims2define='T'
mat2define='T'
defgrid=is.null(grid)
flag_mask_mod=array('T',dim=nmod)
flag_mask_obs=array('T',dim=nobs)
remap=switch(method,'bilinear'='remapbil','bicubic'='remapbic','conservative'='remapcon','distance-weighted'='remapdis')
weight_area=list()
weight_area_obs=list()
#
# Make sure that longitude bounds are positive
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if  (lonmin < 0)  {
    lonmin = lonmin + 360
}
if (lonmax < 0) {
    lonmax = lonmax + 360
}
#
# Parameters needed to load data
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
roota='/cfunas/exp/ENSEMBLES/decadal/MME/'
rootb='/cfunas/exp/*/'
rootc='/cfunas/exp/ENSEMBLES/'
rootd='/cfunas/exp/CMIP5/decadal/'
roote='/cfunas/exp/CMIP5/historical/'
rootf='/cfunas/exp/ECMWF/seasonal/0001/s004/'
rootg='/cfunas/exp/ECMWF/seasonal/0001/s003/m001'
lstatms=c('tas','prlr','tos','g500','g200','ta50','psl','hflsd','hfssd','rls','rss','rsds','uas','vas')
lstatm_stats=c('tas_q90','tas_mean','tas_ndaysq90','prlr_q90','prlr_mean','prlr_ndaysq90')
lstoces=c('siaN','sieN','sivN','siaS','sieS','sivS','moc_40N55N_1-2km','moc_30N40N_1-2km','max_moc_38N50N_500m-2km','max_moc_40N','NAtl_stc_0N25N_0-200m','SAtl_stc_25S0S_0-200m','SPac_stc_25S0S_0-200m','NPac_stc_0N25N_0-200m','heatc','0-315_heatc','373-657_heatc','800-5350_heatc','mxl_heatc','NAtl_10N65N_heatc','NAtl_10N65N_0-315_heatc','NAtl_10N65N_373-657_heatc','NAtl_10N65N_800-5350_heatc','mxl_NAtl_10N65N_heatc','TAtl_30S30N_heatc','TAtl_30S30N_0-315_heatc','TAtl_30S30N_373-657_heatc','TAtl_30S30N_800-5350_heatc','mxl_TAtl_30S30N_heatc','NPac_10N70N_heatc','NPac_10N70N_0-315_heatc','NPac_10N70N_373-657_heatc','NPac_10N70N_800-5350_heatc','mxl_NPac_10N70N_heatc','TPac_30S30N_heatc','TPac_30S30N_0-315_heatc','TPac_30S30N_373-657_heatc','TPac_30S30N_800-5350_heatc','mxl_TPac_30S30N_heatc','Arc_65N90N_heatc','Arc_65N90N_0-315_heatc','Arc_65N90N_373-657_heatc','Arc_65N90N_800-5350_heatc','mxl_Arc_65N90N_heatc','Ant_90S60S_heatc','Ant_90S60S_0-315_heatc','Ant_90S60S_373-657_heatc','Ant_90S60S_800-5350_heatc','mxl_Ant_90S60S_heatc','TInd_30S30N_heatc','TInd_30S30N_0-315_heatc','TInd_30S30N_373-657_heatc','TInd_30S30N_800-5350_heatc','mxl_TInd_30S30N_heatc')
locat=match(var,lstoces)
lat_mod=NULL
lon_mod=NULL
if (is.na(locat)) {
  freq="_[36]hourly/"
  var2d=TRUE
  nmembobs=1
}else{
  freq="/"
  defgrid=TRUE
  var2d=FALSE
  output='areave'
  if ( substr(var,1,2) == 'si' ) {nmembobs=1} else {nmembobs=5}
}
if (is.na(match(var,lstatm_stats))==FALSE) { dirtype='statistics' } else { dirtype='mean' }
#
library(ncdf)
source("/cfu/pub/scripts/R/calendar.txt")
#
indyear=1
for (jyear in sdates) {            # Loop on starting dates
  #
  # Loading experimental data
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (jmod in 1:nmod){
    if ( substr(exp[jmod],1,8) != 'DePreSys' ) {
      if (is.na(locat)) {
        dirin=var
        file2load=paste(var,"_",jyear,".nc",sep="")
        namevar=var
      }else{
        if (substr(var,1,2)=='si') { dirin='ice'; file2load=paste('siasiesiv_',substr(var,4,4),'_',exp[jmod],"_",jyear,"*.nc",sep=''); namevar=substr(var,1,3) }
        if (locat>6 & locat<15) { dirin='moc'; file2load=paste(var,"_",exp[jmod],'_',jyear,"*.nc",sep=""); namevar=switch(substr(var,1,3),'max'='maxmoc',switch(substr(var,2,4),'Pac'='zomsfpac','zomsfatl')) }
        if (locat>14 ) { dirin='heatc'; file2load=paste(var,"_",exp[jmod],'_',jyear,"*.nc",sep=""); namevar='thc' }
      }
      argfiles=paste('ls ',switch(exp[jmod],'EnsEcmwfDec'=paste(roota,'ecmwf/2005/s001/m001',sep=""),'EnsCerfacsDec'=paste(roota,'cerfacs/2002/s000/m001',sep=""),'EnsIfmDec'=paste(roota,'ifm/2002/s001/m010',sep=""),'EnsUkmoDec'=paste(roota,'ukmo/2026/s001/m001',sep=""),'EnsEcmwfSeas'=paste(rootc,'/seasonal/ecmwf',sep=""),'EnsCerfacsSeas'=paste(rootc,'seasonal/cerfacs',sep=""),'EnsIfmSeas'=paste(rootc,'seasonal/ifm',sep=""),'EnsUkmoSeas'=paste(rootc,'seasonal/ukmo',sep=""),'EnsCmccSeas'=paste(rootc,'/seasonal/cmcc',sep=""),'EnsMetfrSeas'=paste(rootc,'/seasonal/metfr',sep=""),'ecmwf'=paste(rootc,'ecmwf/2005/s001/m001',sep=""),'cerfacs'=paste(roota,'cerfacs/2002/s000/m001',sep=""),'ifm'=paste(roota,'ifm/2002/s001/m010',sep=""),'ukmo'=paste(roota,'ukmo/2026/s001/m001',sep=""),'ECMWF_S3Seas'=rootg,'ECMWF_S4_sea'=paste(rootf,'m001',sep=""),'ECMWF_S4_ann'=paste(rootf,'m003',sep=""),'bccdec'=paste(rootd,'bcc/i1p1',sep=""),'hadcm3dec'=paste(rootd,'hadcm3/i2p1',sep=""),'miroc4dec'=paste(rootd,'miroc4h/i1p1',sep=""),'miroc5dec'=paste(rootd,'miroc5/i1p1',sep=""),'mri-cgcm3dec'=paste(rootd,'mri-cgcm3/i1p1',sep=""),'cnrm-cm5dec'=paste(rootd,'cnrm-cm5/i1p1',sep=""),'cancm4dec1'=paste(rootd,'cancm4/i1p1',sep=""),'cancm4dec2'=paste(rootd,'cancm4/i2p1',sep=""),'knmidec'=paste(rootd,'ecearth/i1p1',sep=""),'smhidec'=paste(rootd,'ecearth/i3p1',sep=""),'mpimdec'=paste(rootd,'mpi-esm-lr/i1p1',sep=""),'gfdldec'=paste(rootd,'gfdl/i1p1',sep=""),'cmcc-cmdec'=paste(rootd,'cmcc-cm/i1p1',sep=""),'ipsldec'=paste(rootd,'ipsl/i1p1',sep=""),'bcchis'=paste(roote,'bcc/i0p1',sep=""),'hadcm3his'=paste(roote,'hadcm3/i0p1',sep=""),'miroc4his'=paste(roote,'miroc4h/i0p1',sep=""),'miroc5his'=paste(roote,'miroc5/i0p1',sep=""),'mri-cgcm3his'=paste(roote,'mri-cgcm3/i0p1',sep=""),'cnrm-cm5his'=paste(roote,'cnrm-cm5/i0p1',sep=""),'knmihis'=paste(roote,'ecearth/iXpY',sep=""),'cancm4his'=paste(roote,'cancm4/i0p1',sep=""),'mpimhis'=paste(roote,'mpi-esm-lr/i0p1',sep=""),'gfdlhis'=paste(roote,'gfdl/i0p1',sep=""),'ipslhis'=paste(roote,'ipsl/i1p1',sep=""),'cmcc-cmhis'=paste(roote,'cmcc-cm/i0p1',sep=""),paste(rootb,exp[jmod],sep="")),'/',storefreq,'_',dirtype,'/',dirin,switch(exp[jmod],'ecmwf'='/','cerfacs'='/','ifm'='/','ukmo'='/','EnsEcmwfDec'='/','EnsCerfacsDec'='/','EnsUkmoDec'='/','EnsIfmDec'='/','EnsEcmwfSeas'='/','EnsCerfacsSeas'='/','EnsUkmoSeas'='/','EnsIfmSeas'='/','EnsCmccSeas'='/','EnsMetfrSeas'='/','ECMWF_S3Seas'=switch(var,'tos'='_24hourly/','tas'='_6hourly/','/'),'ECMWF_S4_sea'=switch(var,'tos'='_24hourly/','_6hourly/'),'ECMWF_S4_ann'=switch(var,'prlr'='/','tos'='_24hourly/','_6hourly/'),'bccdec'='/','hadcm3dec'='/','miroc4dec'='/','miroc5dec'='/','mri-cgcm3dec'='/','cnrm-cm5dec'='/','cancm4dec1'='/','cancm4dec2'='/','knmidec'='/','smhidec'='/','bcchis'='/','hadcm3his'='/','miroc4his'='/','miroc5his'='/','mri-cgcm3his'='/','cancm4his'='/','cnrm-cm5his'='/','knmihis'='/','mpimdec'='/','gfdldec'='/','mpimhis'='/','gfdlhis'='/','cmcc-cmdec'='/','cmcc-cmhis'='/','ipsldec'='/','ipslhis'='/',freq),file2load,sep="")
      files=system(argfiles,intern=T,ignore.stderr=T)
      if (length(files)>0) {
        filename=files[length(files)]
        print(filename)        
        if (defgrid) {
          grid=switch(exp[jmod],'ecmwf'='r144x73','cerfacs'='r144x73','ukmo'='r144x73','ifm'='r144x73','EnsEcmwfDec'='r144x73','EnsCerfacsDec'='r144x73','EnsUkmoDec'='r144x73','EnsIfmDec'='r144x73','EnsEcmwfSeas'='r144x73','EnsCerfacsSeas'='r144x73','EnsUkmoSeas'='r144x73','EnsIfmSeas'='r144x73','EnsCmccSeas'='r144x73','EnsMetfrSeas'='r144x73','ECMWF_S4_sea'='t170grid','ECMWF_S4_ann'='t170grid','bccdec'='t42grid','hadcm3dec'=switch(var,'tos'='r288x144','tas'='r96x73','prlr'='r96x73','psl'='r96x73'),'miroc4dec'='r360x180','miroc5dec'='t85grid','mri-cgcm3dec'=switch(var,'tos'='r240x180','tas'='t106grid','prlr'='t106grid','psl'='t106grid'),'cnrm-cm5dec'='t85grid','cancm4dec1'=switch(var,'tas'='t42grid','prlr'='t42grid','psl'='t42grid'),'cancm4dec2'=switch(var,'tas'='t42grid','prlr'='t42grid'),'knmidec'='r320x161','mpimdec'='t63grid','gfdldec'=switch(var,'tas'='r144x90','prlr'='r144x90','tos'='r144x90'),'cmcc-cmdec'=switch(var,'tas'='t159grid','prlr'='t159grid'),'ipsldec'='r96x96','bcchis'='t42grid','hadcm3his'=switch(var,'tos'='r288x144','tas'='r96x73','prlr'='r96x73','psl'='r96x73'),'miroc4his'='r360x180','miroc5his'='t85grid','mri-cgcm3his'=switch(var,'tos'='r240x180','tas'='t106grid','prlr'='t106grid','psl'='t106grid'),'cnrm-cm5his'='t85grid','cancm4his'=switch(var,'tas'='t42grid','prlr'='t42grid','psl'='t42grid'),'mpimhis'='t63grid','gfdlhis'=switch(var,'tas'='r144x90','prlr'='r144x90','tos'='r144x90'),'ipslhis'='r96x96','cmcc-cmhis'='t159grid',switch(var,'ta50'='t159grid','t106grid'))
          filein=filename
        } else {
          system(paste("cdo ",remap,",",grid," ",filename," tmp.nc 2>/dev/null",sep=""))
          system("ncrename -v lat,latitude -d lat,latitude -v lon,longitude -d lon,longitude tmp.nc")
          filein="tmp.nc"
        }
        fnc=open.ncdf(filein)
        tmp=get.var.ncdf(fnc,namevar)
        if (is.na(locat)) {
          tmp[which(tmp>1e11)]=NA
          tmp[which(tmp<(-1e33))]=NA
        }
        if (var2d==TRUE) { 
          tmp[which(tmp>1e11)]=NA
          if (length(dim(tmp)) == 3) { tmp=CFU_insertdim(tmp,3,1) }
          lat=get.var.ncdf(fnc,"latitude")
          lon=get.var.ncdf(fnc,"longitude")
          if ( lat[1] < lat[length(lat)]  ) {           
            tmp=tmp[,length(lat):1,,]
            lat=lat[length(lat):1]
            if (length(dim(tmp)) == 3) { tmp=CFU_insertdim(tmp,3,1) }
          }
        }else{
          if (is.null(dim(tmp))) { tmp=CFU_insertdim(tmp,1,1) }
          if (length(dim(tmp))<2) { tmp=CFU_insertdim(tmp,1,1) } 
          tmp=CFU_insertdim(tmp,1,1)
          tmp=CFU_insertdim(tmp,1,1)
          lat_mod=0
          lon_mod=0
        }
        close.ncdf(fnc)
        if (dims2define) {
          if (is.null(nleadtime) ) { nleadtime=dim(tmp)[4] }
          if (is.null(leadtimemax) ) { leadtimemax=nleadtime }
          if (is.null(nmember) ) { nmemb=dim(tmp)[3] } else { nmemb=nmember } 
          dims2define='F'
        }else{
          if ( dim(tmp)[3] > nmemb ) {
            stop("PUT FIRST THE EXPERIMENT ID WITH THE LARGEST NUMBER OF MEMBERS. If already done, check the dimensions of your files in the repository.")
          }
          if ( dim(tmp)[4] > nleadtime ) {
            stop("nleadtime argument is wrong")
          }
        }
      }else{
        print(paste('No file in ',argfiles))
        filename='nofile.nc'
      }
    }
    for (jmemb in 1:nmemb){
      if ( substr(exp[jmod],1,8) == 'DePreSys') {
        type=switch(substr(exp[jmod],(nchar(exp[jmod])-3),nchar(exp[jmod])),'Seas'='seasonal','decadal')
        asim=switch(substr(exp[jmod],1,12),'DePreSysAsim'='2502','DePreSysNoAs'='2501')
        numPP=seq(10,18)
        dir=switch(var,'uas'='_rg/','vas'='_rg/','/')
        filename=paste(rootc,type,'/DePreSys/',asim,"/s051/m0",as.character(numPP[jmemb]),"/monthly_mean/",var,dir,var,"_",jyear,".nc",sep="")
        if (is.null(nleadtime) ) { nleadtime=switch(type,'seasonal'=7,'decadal'=120) }
        if (is.null(leadtimemax) ) { leadtimemax=nleadtime }
        print(filename)
        if (file.exists(filename)) {
          if (defgrid) {
            if (type=='seasonal') { grid='r144x73' } else { grid=switch(var,'hfssd'='r144x73','hflsd'='r144x73','r96x73') }
            filein=filename
          } else {
            system(paste("cdo ",remap,",",grid," ",filename," tmp.nc 2>/dev/null",sep=""))
            system("ncrename -v lat,latitude -d lat,latitude -v lon,longitude -d lon,longitude tmp.nc")
            filein="tmp.nc"
          } 
          fnc=open.ncdf(filein)
          tmp=get.var.ncdf(fnc,var)
          tmp[which(tmp>1e11)]=NA
          tmp[which(tmp<(-1e33))]=NA
          lat=get.var.ncdf(fnc,"latitude")
          lon=get.var.ncdf(fnc,"longitude")
          close.ncdf(fnc)
          if ( lat[1] < lat[length(lat)] ) { 
            tmp=tmp[,length(lat):1,]
            lat=lat[length(lat):1]
          }
        }
      }
      jens=(jmod-1)*nmemb+jmemb
      if (file.exists(filename)) {
        if (var2d==TRUE) {
          for (jtime in seq(leadtimemin,leadtimemax,sampleperiod)){
            tmp1=array(dim=c(length(lon),length(lat)))
            if ( substr(exp[jmod],1,8) == 'DePreSys' ) {
              if ( jtime<=dim(tmp)[3] ) {
                tmp1=tmp[,,jtime]
              }
            }else{
              if (jmemb <= dim(tmp)[3] & jtime<=dim(tmp)[4] ) {
                tmp1=tmp[,,jmemb,jtime]
              }
            }
            #
            # Selecting the masked domain
            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
            #
            indlon=which( (lon>=lonmin & lon<=lonmax) | (lonmax<lonmin & (lon>=lonmin | lon<=lonmax)) )
            tmp2=tmp1[indlon,which(lat>=latmin & lat <=latmax)]
            if (flag_mask_mod[jmod]) {
              if (is.null(maskmod[[jmod]])) {maskmod[[jmod]]=array(1,dim=dim(tmp1))}
              maskmod[[jmod]]=maskmod[[jmod]][indlon,which(lat>=latmin & lat <=latmax)]
              lat_mod=lat[which(lat>=latmin & lat <=latmax)]
              lon_mod=lon[indlon]
              flag_mask_mod[jmod]='F'
              #
              #  Computing weigths for averaging
              # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              #
              weight=CFU_insertdim(cos(lat_mod*pi/180),1,dim(tmp2)[1])
              weight[which(maskmod[[jmod]]<0.5 | is.na(tmp2))]=NA
              weight_lon=weight/CFU_insertdim(CFU_mean1dim(weight,2,narm=T),2,dim(tmp2)[2])
              weight_area[[jmod]]=weight/mean(weight,na.rm=T)
              #
              #  Defining output matrix
              # ~~~~~~~~~~~~~~~~~~~~~~~~
              #
              if (mat2define) {
                nleadtime2=(leadtimemax-leadtimemin)%/%sampleperiod+1
                var_exp=switch(output,'areave'=array(dim=c(nmod,nmemb,nsdates,nleadtime2)),'lon'=array(dim=c(nmod,nmemb,nsdates,nleadtime2,dim(tmp2)[1])),'lat'=array(dim=c(nmod,nmemb,nsdates,nleadtime2,dim(tmp2)[2])),'lonlat'=array(dim=c(nmod,nmemb,nsdates,nleadtime2,dim(tmp2)[2:1])))
                var_obs=switch(output,'areave'=array(dim=c(nobs,nmembobs,nsdates,nleadtime2)),'lon'=array(dim=c(nobs,1,nsdates,nleadtime2,dim(tmp2)[1])),'lat'=array(dim=c(nobs,1,nsdates,nleadtime2,dim(tmp2)[2])),'lonlat'=array(dim=c(nobs,1,nsdates,nleadtime2,dim(tmp2)[2:1])))
                mat2define='F'
              }
            }
            tmp2[which(maskmod[[jmod]]<0.5)]=NA
            # 
            #  Computing the outputs
            # ~~~~~~~~~~~~~~~~~~~~~~~
            #
            jtime2=(jtime-leadtimemin)%/%sampleperiod+1
            if ( output=='areave') {
              var_exp[jmod,jmemb,indyear,jtime2]=mean(tmp2*weight_area[[jmod]],na.rm=T)
            }else if ( output=='lon') {
              var_exp[jmod,jmemb,indyear,jtime2,]=CFU_mean1dim(tmp2*weight_lon,2,narm=T) 
            }else if ( output=='lat') {
              var_exp[jmod,jmemb,indyear,jtime2,]=CFU_mean1dim(tmp2,1,narm=T)
            }else if (output=='lonlat') {
              var_exp[jmod,jmemb,indyear,jtime2,,]=t(signif(tmp2,5))
            }else{
              stop("Wrong output option")
            }
          }          
        }else{
          if (mat2define) {
            nleadtime2=(leadtimemax-leadtimemin)%/%sampleperiod+1
            var_exp=array(dim=c(nmod,nmemb,nsdates,nleadtime2))
            var_obs=array(dim=c(nobs,nmembobs,nsdates,nleadtime2))
            mat2define='F'
          }
          if ( dim(tmp)[3] >= jmemb ) { var_exp[jmod,jmemb,indyear,1:min(nleadtime2,(dim(tmp)[4]-leadtimemin)%/%sampleperiod+1)]=tmp[1,1,jmemb,seq(leadtimemin,min(leadtimemax,dim(tmp)[4]),sampleperiod)] }
        }
      }
    }
  }
  #
  # Loading observational data
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #
  indobs=1
  for (jobs in obs) {
    if (is.na(locat)) {
      suffixeraint=switch(var,'tas'='_f6h/','tas_q90'='_f6h/','tas_mean'='_f6h/','tas_ndaysq90'='_f6h/','tos'='_f6h/','prlr'='_s0-12h/','prlr_mean'='_s0-12h/','prlr_ndaysq90'='_s0-12h/','prlr_q90'='_s0-12h/','g200'='_f6h/','g500'='_f6h/','psl'='_f6h/','rls'='_s0-12h/','rss'='_s0-12h/','rsds'='_s0-12h/','hflsd'='_s0-12h/','hfssd'='_s0-12h/','uas'='_f6h/','vas'='_f6h/','ta50'='_f6h/')
      suffixncep=switch(var,'tas'='_6hourly/','psl'='_6hourly/','rls'='_step6h/','rss'='_step6h/','hflsd'='_step6h/','hfssd'='_step6h/','rsds'='_step6h/','uas'='_6hourly/','vas'='_6hourly/')
      pathobs=switch(jobs,'ERA40'=paste('/cfu/data/ecmwf/era40/',storefreq,'_',dirtype,'/',var,'_f6h/',var,'_',sep=""),'NCEP'=paste('/cfu/data/ncep/',storefreq,'_',dirtype,'/',var,suffixncep,var,'_ncep_',sep=""),'ERAint'=paste('/cfu/data/ecmwf/eraint/',storefreq,'_',dirtype,'/',var,suffixeraint,var,'_',sep=""),'20thCv2'=paste('/cfu/data/noaa/20thc_reanv2/',storefreq,'_',dirtype,'/',var,suffixeraint,var,'_',sep=""),'GHCN'=paste('/cfu/data/noaa/ghcn_v2/',storefreq,'_',dirtype,'/tas/tas_',sep=''),'GHCNERSSTGISS'=paste('/cfu/data/noaanasa/ghcnersstgiss/',storefreq,'_',dirtype,'/tas/tas_',sep=''),'ERSST'=paste('/cfu/data/noaa/ersstv3b/',storefreq,'_',dirtype,'/tos/tos_',sep=""),'UKMO'=paste('/cfu/data/ukmo/hadisstv1.1/',storefreq,'_',dirtype,'/tos/tos_',sep=''),'HadISST'=paste('/cfu/data/ukmo/hadisstv1.1/',storefreq,'_',dirtype,'/tos/tos_',sep=''),'HadSLP'=paste('/cfu/data/ukmo/hadslp2/',storefreq,'_',dirtype,'/psl/psl_',sep=''),'GPCC'=paste('/cfu/data/dwd/gpcc_combined1x1_v4/',storefreq,'_',dirtype,'/prlr/prlr_',sep=''),'CRU'=paste('/cfu/data/cru/',storefreq,'_',dirtype,'/',var,'/',var,'_cru_',sep=""),'GPCP'=paste('/cfu/data/noaa/gpcp_v2.2/',storefreq,'_',dirtype,'/prlr/prlr_',sep=''),'EOBS'='/cfu/data/eobs/prlr_eobs_0.5x0.5/prlr_eobs_','DS94'=paste('/cfu/data/iri/DaSilva/',storefreq,'_',dirtype,'/',var,'/',var,'_',sep=""),'OAFlux'=paste('/cfu/data/whoi/oaflux/',storefreq,'_',dirtype,'/',var,'/',var,'_',sep=""),'DFS4.3'=paste('/cfu/data/legi/dfs4.3/',storefreq,'_',dirtype,'/',var,'/',var,'_',sep=""),'GISSglo'='/cfu/data/nasa/global_mean/tas_GISS_','GISSland'='/cfu/data/nasa/land_mean/tas_GISS_','GISSoc'='/cfu/data/nasa/ocean_mean/tos_GISS_','CRUTEM3land'='/cfu/data/ukmo/land_mean/tas_CRUTEM3_','HadSST2oc'='/cfu/data/ukmo/ocean_mean/tos_HadSST2_','HadCRUT3glo'='/cfu/data/ukmo/global_mean/tas_hadCRUT3_','HadCRUT4'='/cfu/data/ukmo/hadcrut4/monthly_mean/tas_anom/tas_','NCDCoc'=paste('/cfu/data/noaa/merged_ocean_mean/',storefreq,'_',dirtype,'/tos/tos_',sep=''),'NCDCland'=paste('/cfu/data/noaa/merged_land_mean/',storefreq,'_',dirtype,'/tas/tas_',sep=''),'NCDCglo'=paste('/cfu/data/noaa/merged_global_mean/',storefreq,'_',dirtype,'/tas/tas_',sep=''))
      filesobs=system(paste('ls ',pathobs,'*',sep=''),intern=T,ignore.stderr=T)
      print(paste('Files loaded from ',pathobs,'*',sep=''))
      if (length(filesobs)>0) {
        if ( storefreq == 'daily' ) {
          iday=substr(jyear,7,8)
          if ( iday=='' ) { iday='01' } 
          startdate=as.POSIXct(paste(substr(jyear,1,4),'-',substr(jyear,5,6),'-',iday,' 12:00:00',sep=''))+(leadtimemin-1)*86400
        } else {
          imon=(as.integer(substr(jyear,5,6))+leadtimemin-2)%%12+1
          iyear=as.integer(substr(jyear,1,4))+(as.integer(substr(jyear,5,6))+leadtimemin-2)%/%12
        }
        jtime=1
        while (jtime<=nleadtime2) {
          if ( storefreq == 'daily' ) {
            newdate=startdate+86400*(jtime-1)*sampleperiod
            iyear=substr(newdate,1,4)
            imon=as.integer(substr(newdate,6,7))
            itimind=as.integer(substr(newdate,9,10))
            if ( CFU_leapyear(as.integer(iyear)) ) { lenmon=29 } else { lenmon=28 }
            lenmon=switch(substr(newdate,6,7),'01'=31,'03'=31,'04'=30,'05'=31,'06'=30,'07'=31,'08'=31,'09'=30,'10'=31,'11'=30,'12'=31,lenmon)
          }else{
            if (jtime > 1) {
              imon=imon+sampleperiod
              iyear=iyear+(imon-1)%/%12
              imon=(imon-1)%%12+1
            }
            itimind=1
            lenmon=1
          }
          filename=paste(pathobs,iyear,sprintf("%2.2i",imon),".nc",sep="")
          if (file.exists(filename)) {
            print(filename)
            if ( output!='areave' | defgrid==F) {
              system(paste("cdo ",remap,",",grid," ",filename," tmp.nc 2>/dev/null",sep=""))
              system("ncrename -v lat,latitude -d lat,latitude -v lon,longitude -d lon,longitude tmp.nc")
              filename="tmp.nc"
            }
            fnc=open.ncdf(filename)
            var2=switch(jobs,'ERSST'='tos','UKMO'='tos','HadISST'='tos',var)
            tmp=get.var.ncdf(fnc,var2)
            if ( var == 'tos' | var =='tas' | var=='prlr' ) { tmp[which(tmp>599|tmp<(-999))]=NA }
            if ( substr(jobs,(nchar(jobs)-3),nchar(jobs)) != 'land' & substr(jobs,(nchar(jobs)-1),nchar(jobs)) != 'oc' & substr(jobs,(nchar(jobs)-2),nchar(jobs)) != 'glo' ) {
              lat=get.var.ncdf(fnc,"latitude")
              lon=get.var.ncdf(fnc,"longitude")
              lon[which(lon<0)]=lon[which(lon<0)]+360
            }
            close.ncdf(fnc)
            if ( length(dim(tmp)) == 2 ) { tmp=CFU_insertdim(tmp,3,1) }
            if ( (output!='areave' | defgrid==F) & lat[1]<0 ) { 
              tmp=tmp[,length(lat):1,] 
              lat=lat[length(lat):1]
            }
            if ( length(dim(tmp)) == 2 ) { tmp=CFU_insertdim(tmp,3,1) }
            #
            #  Selecting the masked domain 
            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            #
            if ( storefreq == 'monthly' ) { rangeind=jtime } else { rangeind=jtime:min((lenmon-itimind)%/%sampleperiod+jtime,nleadtime2) }
            rangeindout=seq(itimind,min(lenmon,(nleadtime2-jtime+1)*sampleperiod+itimind-1),sampleperiod)
            if ( substr(jobs,(nchar(jobs)-3),nchar(jobs)) != 'land' & substr(jobs,(nchar(jobs)-1),nchar(jobs)) != 'oc' & substr(jobs,(nchar(jobs)-2),nchar(jobs)) != 'glo' ) {
              indlon=which( (lon>=lonmin & lon<=lonmax) | (lonmax<lonmin & (lon>=lonmin | lon<=lonmax)) )
              tmp1=tmp[indlon,which(lat>=latmin & lat <=latmax),]
              if ( length(dim(tmp1)) == 2 ) { tmp1=CFU_insertdim(tmp1,3,1) }
              lat1=lat[which(lat>=latmin & lat <=latmax)]
              if (flag_mask_obs[indobs]) {
                if ( output != 'areave' | defgrid==F ) { maskobs[[indobs]]=maskmod[[nmod]] } else {
                  if (is.null(maskobs[[indobs]])) {maskobs[[indobs]]=array(1,dim=dim(tmp)[1:2])} 
                  maskobs[[indobs]]=maskobs[[indobs]][indlon,which(lat>=latmin & lat <=latmax)] 
                }
                flag_mask_obs[indobs]='F'
                #
                #  Computing weigths for averaging
                # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                #
                weight=CFU_insertdim(cos(lat1*pi/180),1,dim(tmp1)[1])
                weight[which(maskobs[[indobs]]<0.5 | is.na(tmp1[,,1]))]=NA
                weight_area_obs[[jobs]]=weight/mean(weight,na.rm=T)
              }
              tmp1[which(CFU_insertdim(maskobs[[indobs]],3,lenmon)<0.5)]=NA
              #
              #  Computing the outputs
              # ~~~~~~~~~~~~~~~~~~~~~~~
              #
              if ( output=='areave') {
                for ( ind in 1:lenmon) { 
                  var_obs[indobs,1,indyear,rangeind[ind]]=mean(tmp1[,,rangeindout[ind]]*weight_area_obs[[jobs]],na.rm=T)
                }
              }else if ( output=='lon') {
                var_obs[indobs,1,indyear,rangeind,]=aperm(CFU_mean1dim(tmp1*CFU_insertdim(weight_lon,3,lenmon),2,narm=T)[,rangeindout],length(dim(tmp1[,,rangeindout])):1)
              }else if ( output=='lat') {
                var_obs[indobs,1,indyear,rangeind,]=aperm(CFU_mean1dim(tmp1,1,narm=T)[,rangeindout],length(dim(tmp1[,,rangeindout])):1)
              }else if (output=='lonlat') {
                var_obs[indobs,1,indyear,rangeind,,]=aperm(signif(tmp1[,,rangeindout],5),length(dim(tmp1[,,rangeindout])):1)
              }else{
                stop("Wrong output option")
              }
            }else{
              var_obs[indobs,1,indyear,rangeind]=tmp[rangeindout]
            }
          }
          jtime=jtime+(lenmon-itimind)%/%sampleperiod+1
        }
      }else{
        print(paste('No file in ',pathobs,'*',sep=''))
      }
    }else{
      if (locat==3 | locat==6) { filein=switch(jobs,'PIOMAS'=paste('/cfu/data/psc/piomas/original_files/',var,'_piomas.nc',sep=''),'UCL'=paste('/cfunas/exp/UCL/monthly_mean/ice/siasiesiv_',substr(var,4,5),'_ucl_fc0-0_19790101_197901_200712.nc',sep='')); namevar=switch(jobs,'PIOMAS'=var,'UCL'=substr(var,1,3))} 
      if (locat<3 | (locat>3 & locat<6)) { filein=paste('/cfu/diagnostics/postprocessed/ice/',switch(jobs,'HadISST'='ukmo/ice_hadisst','NSIDC'='nsidc/ice_nsidc'),'_',substr(var,4,5),'.nc',sep=''); namevar=substr(var,1,3) }
      if (locat>6 & locat<15) { filein=paste('/cfunas/exp/ECMWF/NEMOVAR_S4/monthly_mean/moc/',var,'_nemovar_s4_19570901_fc0-4_195709_201108.nc',sep=""); namevar=switch(substr(var,1,3),'max'='maxmoc',switch(substr(var,2,4),'Pac'='zomsfpac','zomsfatl')) }
      if (locat>14 ) { filein=paste('/cfunas/exp/ECMWF/NEMOVAR_S4/monthly_mean/heatc/',var,'_nemovar_s4_19570901_fc0-4_195709_201108.nc',sep=""); namevar='thc' }
      fnc=open.ncdf(filein)
      tmp=get.var.ncdf(fnc,namevar)
      if ( is.na(dim(tmp)[2]) ) { tmp=CFU_insertdim(tmp,1,1) }
      close.ncdf(fnc)
      mons=strsplit(system(paste('cdo showmon ',filein,' 2>/dev/null'),intern=T),split=' ')
      years=strsplit(system(paste('cdo showyear ',filein,' 2>/dev/null'),intern=T),split=' ')
      mons=as.integer(mons[[1]][which(mons[[1]]!="")])
      years=as.integer(years[[1]][which(years[[1]]!="")])
      tmp_ts=ts(t(tmp),start=c(years[1],mons[1]),end=c(years[length(years)],mons[length(mons)]),frequency=12)
      tmp2=window(tmp_ts,start=c(as.integer(substr(jyear,1,4)),as.integer(substr(jyear,5,6))),end=c(3000,12),frequency=12,extend=TRUE)
      var_obs[indobs,1:dim(tmp)[1],indyear,]=as.matrix(t(tmp2))[,seq(leadtimemin,leadtimemax,sampleperiod)]
    }
    indobs=indobs+1
  } 
  indyear=indyear+1
}
#
system("rm -f tmp.nc")
#
#  Outputs
# ~~~~~~~~~
#
invisible(list(mod=var_exp,obs=var_obs,lat=lat_mod,lon=lon_mod))
#
}
#
################################################################################
CFU_clim<-function( var_exp, var_obs, memb = T, kharin = F, NDV = F ) {
#===============================================================================
#
#  Enlarge the number of dimensions of var_exp and var_obs to 7 if necessary
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimexp=dim(var_exp)
dimobs=dim(var_obs)
if ( length(dimexp) < 4 | length(dimobs) < 4 ) {
  stop("At least 4 dim needed : c(nexp/nobs, nmemb, nsdates, nltime)") 
}
for ( jn in 3:max(length(dimexp),length(dimobs)) )  
  if ( dimexp[jn]!=dimobs[jn] ) { stop("Wrong input dimensions") }
var_exp=CFU_enlarge(var_exp,7)
var_obs=CFU_enlarge(var_obs,7)
#
#  Find common points to compute climatologies 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
tmp=CFU_meanlistdim(var_obs,dims=5:7,narm=T)
tmp2=CFU_meanlistdim(var_exp,dims=5:7,narm=T)
nan=CFU_meanlistdim(tmp,dims=1:2,narm=F)+CFU_mean1dim(CFU_mean1dim(tmp2,2,narm=T),1,narm=F)
for (jdate in 1:dimexp[3]) {
  for (jtime in 1:dimexp[4]) {
    if (is.na(nan[jdate,jtime])) {
      var_exp[,,jdate,jtime,,,]=NA
      var_obs[,,jdate,jtime,,,]=NA
    }
  }
}
#
#  Compute climatologies 
# ~~~~~~~~~~~~~~~~~~~~~~~
#
out_clim_obs=CFU_mean1dim(var_obs,posdim=3,narm=T)
dim_clim_obs=c(dimobs[1:2],dimobs[4:length(dimobs)])
#
if (kharin==T){
  tmp_obs=CFU_trend(var_obs,posTR=3)
  tmp_exp=CFU_trend(var_exp,posTR=3)
  trend_obs=array(dim=dim(var_exp))
  trend_exp=array(dim=dim(var_exp))
  for (jdate in 1:dimexp[3]) {
    trend_exp[,,jdate,,,,]=tmp_exp$trend[,,4,,,,] + jdate*tmp_exp$trend[,,2,,,,]
    trend_obs[,,jdate,,,,]=CFU_insertdim(CFU_insertdim(CFU_meanlistdim(tmp_obs$trend[,,4,,,,] + jdate*tmp_obs$trend[,,2,,,,],c(2,1)),1,dimexp[1]),2,dimexp[2])
  }
  out_clim_exp=trend_exp-trend_obs+CFU_insertdim(CFU_insertdim(CFU_insertdim(CFU_meanlistdim(out_clim_obs,c(2,1)),1,dimexp[1]),2,dimexp[2]),3,dimexp[3])
  dim_clim_exp=dimexp
}else if (NDV==T){
  iniobs=CFU_insertdim(CFU_selindices(var_obs,4,c(1,1)),4,dimobs[4])
  iniexp=CFU_insertdim(CFU_selindices(var_exp,4,c(1,1)),4,dimexp[4])
  tmp_obs=CFU_regression(var_obs,iniobs,posREG=3)
  tmp_exp=CFU_regression(var_exp,iniexp,posREG=3)
  reg_obs=array(dim=dim(var_exp))
  reg_exp=array(dim=dim(var_exp))
  for (jdate in 1:dimexp[3]) {
    reg_exp[,,jdate,,,,]=tmp_exp$regression[,,4,,,,] + iniexp[,,jdate,,,,]*tmp_exp$regression[,,2,,,,]
    reg_obs[,,jdate,,,,]=CFU_insertdim(CFU_insertdim(CFU_meanlistdim(tmp_obs$regression[,,4,,,,] + iniobs[,,jdate,,,,]*tmp_obs$regression[,,2,,,,],c(2,1)),1,dimexp[1]),2,dimexp[2])
  }
  out_clim_exp=reg_exp-reg_obs+CFU_insertdim(CFU_insertdim(CFU_insertdim(CFU_meanlistdim(out_clim_obs,c(2,1)),1,dimexp[1]),2,dimexp[2]),3,dimexp[3])
  dim_clim_exp=dimexp
}else{
  out_clim_exp=CFU_mean1dim(var_exp,posdim=3,narm=T)
  dim_clim_exp=c(dimexp[1:2],dimexp[4:length(dimexp)])
}
#
if (memb!=T) {
  out_clim_obs=CFU_mean1dim(out_clim_obs,posdim=2,narm=T) 
  out_clim_exp=CFU_mean1dim(out_clim_exp,posdim=2,narm=T)
  dim_clim_exp=dim_clim_exp[-2]
  dim_clim_obs=dim_clim_obs[-2]
}
#
#  Reduce the number of dimensions to the original one 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 
clim_exp=array(dim=dim_clim_exp)
clim_exp[]=out_clim_exp
clim_obs=array(dim=dim_clim_obs)
clim_obs[]=out_clim_obs
#
#
#  Outputs
# ~~~~~~~~~
#
invisible(list(clim_exp=clim_exp,clim_obs=clim_obs))
#
}
################################################################################
CFU_ano_crossvalid<-function( var_exp, var_obs, memb = T ) {
#===============================================================================
#
#  Enlarge the number of dimensions of var_exp and var_obs to 7 if necessary
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimexp=dim(var_exp)
dimobs=dim(var_obs)
if ( length(dimexp) < 4 | length(dimobs) < 4 ) {
  stop("At least 4 dim needed : c(nexp/nobs, nmemb, nsdates, nltime)")
}
for ( jn in 3:max(length(dimexp),length(dimobs)) )
  if ( dimexp[jn]!=dimobs[jn] ) { stop("Wrong input dimensions") }
var_exp=CFU_enlarge(var_exp,7)
var_obs=CFU_enlarge(var_obs,7)
#
#  Computation of anomalies in cross-validation mode
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
enl_ano_exp=array(dim=dim(var_exp))
enl_ano_obs=array(dim=dim(var_obs))
for ( jsdat in 1:dimexp[3] ) {
  tmp1=array(var_exp[,,jsdat,,,,],dim=dim(var_exp)[-3])
  tmp2=array(var_obs[,,jsdat,,,,],dim=dim(var_obs)[-3])
  tmp3=array(var_exp[,,-jsdat,,,,],dim=c(dimexp[1:2],dimexp[3]-1,dim(var_exp)[4:7]))
  tmp4=array(var_obs[,,-jsdat,,,,],dim=c(dimobs[1:2],dimobs[3]-1,dim(var_obs)[4:7]))
  tmp=CFU_clim(tmp3,tmp4,memb)
  if (memb) { 
    clim_exp=tmp$clim_exp
    clim_obs=tmp$clim_obs
  }else{
    clim_exp=CFU_insertdim(tmp$clim_exp,2,dimexp[2]) 
    clim_obs=CFU_insertdim(tmp$clim_obs,2,dimobs[2]) 
  }
  enl_ano_exp[,,jsdat,,,,]=tmp1-clim_exp
  enl_ano_obs[,,jsdat,,,,]=tmp2-clim_obs  
} 
#
#  Reduce the number of dimensions to the original one 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
ano_exp=array(dim=dimexp)
ano_obs=array(dim=dimobs)
ano_exp[]=enl_ano_exp
ano_obs[]=enl_ano_obs
#
#  Outputs
# ~~~~~~~~~
#
invisible(list(ano_exp=ano_exp,ano_obs=ano_obs))
#
}
################################################################################
CFU_ano<-function( var, clim ) {
#===============================================================================
#
#  Duplicate clim dimensions to heve same dimensions as var
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimvar=dim(var)
if ( (length(dimvar) > length(dim(clim))) & (dim(clim)[2] != dimvar[2]) ) { clim=CFU_insertdim(clim,2,dimvar[2]) }
if ( (length(dimvar) > length(dim(clim))) & (dim(clim)[3] != dimvar[3]) ) { clim=CFU_insertdim(clim,3,dimvar[3]) }
if ( (length(dimvar) > length(dim(clim))) & (dim(clim)[4] != dimvar[4]) ) { clim=CFU_insertdim(clim,4,dimvar[4]) }
#
#  Raw anomalies
# ~~~~~~~~~~~~~~~
#
ano=var-clim
#
#  Outputs
# ~~~~~~~~~
#
ano
#
}

################################################################################
CFU_smoothing<-function( var, runmeanlen=12, numdimt=4 ) {
#===============================================================================
#
#  Enlarge the number of dimensions of var to 10 --> enlvar 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dimsvar=dim(var)
if ( is.null(dimsvar) ) { dimsvar=length(var) }
u=CFU_inilistdims(dimsvar,10)
enlvar=CFU_enlarge(var,10)
#
#  Smoothing 
# ~~~~~~~~~~~
smt_enlano=array(dim=c(dimsvar,array(1,dim=(10-length(dimsvar)))))

nmr1=floor(runmeanlen/2)
nltime=dimsvar[numdimt]
for (jtime in (1+nmr1):(nltime-nmr1)){
  # First, averaging the two extreme values
  u[[numdimt]]=jtime-nmr1
  left=enlvar[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]
  u[[numdimt]]=jtime+nmr1
  right=enlvar[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]
  u[[numdimt]]=jtime
  smt_enlano[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]=(left+right)/(2*(2*nmr1))
  if ( nmr1 > 0 ) { 
    for (k in -(nmr1-1):(nmr1-1)){
    # Second, adding the equally-weighted values around the centered
      u[[numdimt]]=jtime+k
      mid=enlvar[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]
      u[[numdimt]]=jtime
      smt_enlano[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]=smt_enlano[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]+(mid/(2*nmr1))
    }
  }
}
#
#  Reduce the number of dimensions to the original one 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
smt_ano=array(dim=dimsvar)
smt_ano[]=smt_enlano
#
#  Outputs
# ~~~~~~~~~
#
smt_ano
#
}
#
################################################################################
CFU_plotano<-function( exp_ano, obs_ano=NULL, sdates, toptitle=c('','','','','','','','','','','','','','',''), ytitle=c('','','','','','','','','','','','','','',''), limits=NULL, legends = NULL, freq=12, biglab=F, fill=T, memb=T, ensmean=T, linezero=F, points=F, vlines=NULL, fileout=c('output1_CFU_plotano.eps','output2_CFU_plotano.eps','output3_CFU_plotano.eps','output4_CFU_plotano.eps','output5_CFU_plotano.eps'),sizetit=1 ) {
#===============================================================================
#
#  Get some arguments
# ~~~~~~~~~~~~~~~~~~~~
#
if ( length(dim(exp_ano)) != 4 ) {
  stop("4 dim needed : c(nexp/nobs, nmemb, nsdates, nltime)")
}
nexp=dim(exp_ano)[1]
nmemb=dim(exp_ano)[2]
nleadtime=dim(exp_ano)[4]
nsdates=dim(exp_ano)[3]
if (is.null(obs_ano)==F){ 
  nobs=dim(obs_ano)[1] 
  if ( length(dim(obs_ano)) != 4 ) 
    { stop("4 dim needed : c(nexp/nobs, nmemb, nsdates, nltime)") }
  if ( dim(obs_ano)[3] != nsdates | dim(obs_ano)[4] != nleadtime )
    { stop("obs and exp must have same number of sdates & ltimes") }
} else { nobs = 0 }
if (is.null(limits)==T) {
  if (memb){
    ll=min(min(exp_ano,na.rm=T),min(obs_ano,na.rm=T),na.rm=T)
    ul=max(max(exp_ano,na.rm=T),max(obs_ano,na.rm=T),na.rm=T)
  }else{
    ll=min(min(CFU_mean1dim(exp_ano,2),na.rm=T),min(obs_ano,na.rm=T),na.rm=T)
    ul=max(max(CFU_mean1dim(exp_ano,2),na.rm=T),max(obs_ano,na.rm=T),na.rm=T)
  }
  if (nobs>0) {
    if (biglab) {ul=ul+0.3*(ul-ll)} else {ul=ul+0.2*(ul-ll)}
  }
} else {
  ll=limits[1]
  ul=limits[2]
}
#
#  Define some plot parameters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
yearinit=as.integer(substr(sdates[1],1,4))
moninit=as.integer(substr(sdates[1],5,6))
lastyear=as.integer(substr(sdates[nsdates],1,4))+(moninit+(nleadtime-1)*12/freq-1)%/%12
lastmonth=(moninit+(nleadtime-1)*(12/freq) -1)%%12+1
empty_ts=ts(start=c(yearinit,(moninit-1)%/%(12/freq)+1),end=c(lastyear,(lastmonth-1)%/%(12/freq)+1),frequency=freq)
color=c("red4","orange4","lightgoldenrod4","olivedrab4","green4","lightblue4","dodgerblue4","mediumpurple4","mediumorchid4","deeppink4")
color=c(color,color,color,color,color,color,color,color,color,color,color)
colorblock=c("red1","orange1","lightgoldenrod1","olivedrab1","green1","lightblue1","dodgerblue1","mediumpurple1","mediumorchid1","deeppink1")
colorblock=c(colorblock,colorblock,colorblock,colorblock,colorblock,colorblock,colorblock,colorblock,colorblock,colorblock)
type=c(1,3,2,4)
thickness=c(1,3,2,2)
#
#  Loop on the experiments : one plot for each
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 
for (jexp in 1:nexp){
  #
  #  Define plot layout
  # ~~~~~~~~~~~~~~~~~~~~
  #
  postscript(fileout[jexp],width=550,height=300)
  if ( biglab ) {
    par(mai=c(1,1.1,0.5,0),mgp=c(2.8,0.9,0))
    par(cex=1.3,cex.lab=2,cex.axis=1.8)
    cexmain=2.2
    legsize=1.5
  }else{
    par(mai=c(0.8,0.8,0.5,0.1),mgp=c(2,0.5,0))
    par(cex=1.3,cex.lab=1.5,cex.axis=1.1)
    cexmain=1.5
    legsize=1
  }
  plot(empty_ts,ylim=c(ll,ul),xlab="Time (years)",ylab=ytitle[jexp],main=toptitle[jexp],cex.main=cexmain*sizetit)
  # 
  #  Plot experimental data + all observational datasets sdate by sdate
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #
  for (jdate in 1:nsdates) {
    #
    year0=as.integer(substr(sdates[jdate],1,4))
    mon0=as.integer(substr(sdates[jdate],5,6))
    start=(year0-yearinit)*freq+1
    end=start+nleadtime-1
    var=array(dim=c(nmemb,length(empty_ts)))
    var[,start:end]=exp_ano[jexp,,jdate,]
    #
    #  Compute parameters for filling max-min over members 
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    #
    if (fill) { 
      par(new=TRUE)
      bordup=array(dim=nleadtime)
      borddown=array(dim=nleadtime)
      for (jt in 1:nleadtime) {
        bordup[jt]=max(exp_ano[jexp,,jdate,jt],na.rm=T)
        borddown[jt]=min(exp_ano[jexp,,jdate,jt],na.rm=T)
      }
      tmp=c(start:end)
      xout=is.na(bordup+borddown) 
      tmp=tmp[which(xout==F)]
      xx=c(tmp,rev(tmp))
      bordup=bordup[which(xout==F)]
      borddown=borddown[which(xout==F)]
      yy=c(bordup,rev(borddown))
    #
    #  Plotting 
    # ~~~~~~~~~~
    # 
      if (jdate==1) {matplot(t(var),type="l",lty=1,lwd=1,ylim=c(ll,ul),col=color[jdate],xlab="",ylab="",axes=FALSE)} 
      polygon(xx,yy,col=colorblock[jdate],border=NA)  # Max-min member range
    }
    if (ensmean) { # Ensemble-mean
      par(new=TRUE)
      if (points)
        { plot(CFU_mean1dim(t(var),2),type="p",lty=1,lwd=4,ylim=c(ll,ul),col=color[jdate],xlab="",ylab="",axes=FALSE) }
      else
        { plot(CFU_mean1dim(t(var),2),type="l",lty=1,lwd=4,ylim=c(ll,ul),col=color[jdate],xlab="",ylab="",axes=FALSE) }
    }
    if (memb) {
      par(new=TRUE) # All members
      if (points) 
        { matpoints(t(var),type="p",lty=1,lwd=1,pch=20,ylim=c(ll,ul),col=color[jdate],xlab="",ylab="",axes=FALSE) }
      else 
        { matplot(t(var),type="l",lty=1,lwd=1,ylim=c(ll,ul),col=color[jdate],xlab="",ylab="",axes=FALSE) }
    }
    if ( nobs > 0 ) {   
      for (jobs in 1:nobs) { 
        for (jmemb in 1:dim(obs_ano)[2]) {
          var=array(dim=length(empty_ts))
          var[start:end]=obs_ano[jobs,jmemb,jdate,]
          par(new=TRUE) # Observational datasets
          if (points) 
            { plot(var,type="p",lty=1,lwd=4,pch=20,ylim=c(ll,ul),col=1,ylab="",xlab="",axes=FALSE) }
          else 
            { plot(var,lty=type[jobs],lwd=thickness[jobs],type="l",ylim=c(ll,ul),col=1,ylab="",xlab="",axes=FALSE) }
        }
      }
    }
  }
  if (linezero) {
    abline(h=0, col = "black")
  }
  if (is.null(vlines)==F) {
    for ( x in vlines ) {
      abline(v=x, col = "black")
    }
  }
  if (is.null(legends)==F) {
    if (points) { legend(0,ul,legends[1:nobs],lty=3,lwd=10,col=1,cex=legsize) }
    else { legend(0,ul,legends[1:nobs],lty=type[1:nobs],lwd=thickness[1:nobs],col=1,cex=legsize) }
  }
  dev.off()
}
#
}
#
################################################################################
CFU_plotclim<-function(exp_clim, obs_clim=NULL, toptitle='', ytitle='', monini=1, freq=12, limits=NULL, listexp=c('exp1','exp2','exp3'), listobs=c('obs1', 'obs2', 'obs3'), biglab=F, leg=T, fileout='output_CFU_plotclim.eps',sizetit=1) {
#===============================================================================
#
#  Get some arguments
# ~~~~~~~~~~~~~~~~~~~~
#
if ( length(dim(exp_clim)) != 2 & length(dim(exp_clim)) != 3 ) {
  stop("2 or 3 dim needed : c(nexp, nltime) or c(nexp, nmemb, nltime)")
}
if ( length(dim(exp_clim)) < 3) { exp_clim=CFU_insertdim(exp_clim,2,1) }
nleadtime=dim(exp_clim)[3]
nexp=dim(exp_clim)[1]
if (is.null(obs_clim)){ 
  nobs = 0
}else{ 
  nobs = dim(obs_clim)[1]
  if ( length(dim(obs_clim)) != 2 & length(dim(obs_clim)) != 3 ) {
    stop("2 or 3 dim needed : c(nobs, nltime) or c(nobs, nmemb, nltime)")
  } 
  if ( length(dim(obs_clim)) < 3) { obs_clim=CFU_insertdim(obs_clim,2,1) }
  if ( dim(obs_clim)[3] != nleadtime ) {
    stop("obs and exp must have same number of ltimes")
  }
 }
if (is.null(limits)==T) {
  ll=min(min(exp_clim,na.rm=T),min(obs_clim,na.rm=T),na.rm=T)
  ul=max(max(exp_clim,na.rm=T),max(obs_clim,na.rm=T),na.rm=T)
  if (biglab) {ul=ul+0.3*(ul-ll)} else {ul=ul+0.2*(ul-ll)}
} else {
  ll=limits[1]
  ul=limits[2]
}
lastyear=(monini+(nleadtime-1)*12/freq-1)%/%12
lastmonth=(monini+(nleadtime-1)*12/freq-1)%%12+1
#
#  Define some plot parameters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
if (biglab) {labind=seq(1,nleadtime,max(nleadtime%/%5,1))} else {labind=seq(1,nleadtime,max(nleadtime%/%10,1))}
months=c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")
labyear=((labind-1)*12/freq + monini -1)%/%12
labmonth=months[( (labind-1)*12/freq + monini -1 )%%12 + 1]
for (jx in 1:length(labmonth)) {
  y2o3dig=paste("0",as.character(labyear[jx]),sep="") 
  labmonth[jx]=paste(labmonth[jx],"\nYr ",substr(y2o3dig,nchar(y2o3dig)-1,nchar(y2o3dig)),sep="")
}
empty_ts=ts(start=c(0000,(monini-1)%/%(12/freq)+1),end=c(lastyear,(lastmonth-1)%/%(12/freq)+1),frequency=freq)
empty=array(dim=length(empty_ts))
color=c("red1","dodgerblue1","green1","orange1","lightblue1","deeppink1","mediumpurple1","lightgoldenrod1","olivedrab1","mediumorchid1")
type=c(1,3,2,4)
thickness=c(1,3,1,2)
#
#  Define plot layout
# ~~~~~~~~~~~~~~~~~~~~
# 
postscript(fileout,width=550,height=300)
if (biglab) {
  par(mai=c(1.25,1.4,0.5,0),mgp=c(4,2.5,0))
  par(cex=1.3,cex.lab=2,cex.axis=1.8)
  cexmain=2.2
  legsize=1.5
}else{
  par(mai=c(1,1.1,0.5,0),mgp=c(3,1.8,0))
  par(cex=1.3,cex.lab=1.5,cex.axis=1.1)
  cexmain=1.5
  legsize=1
}
plot(empty,ylim=c(ll,ul),xlab="Time (months)",ylab=ytitle,main=toptitle,cex.main=cexmain*sizetit,axes=FALSE)
axis(1,at=labind,labels=labmonth)
axis(2)
box()
#
#  Loops on experimental and observational data
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
for (jexp in 1:nexp){
  for (jmemb in 1:dim(exp_clim)[2]) {
    par(new=TRUE)
    plot(exp_clim[jexp,jmemb,],type="l",lty=1,lwd=2,ylim=c(ll,ul),col=color[jexp],ylab="",xlab="",axes=FALSE)
  }
}
if ( nobs > 0 ) {
  for (jobs in 1:nobs){
    for (jmemb in 1:dim(obs_clim)[2]) {
      par(new=TRUE)
      plot(obs_clim[jobs,jmemb,],lty=type[jobs],lwd=thickness[jobs],type="l",ylim=c(ll,ul),col=1,ylab="",xlab="",axes=FALSE)
    }
  }
  if (leg) {legend(1,ul,c(listexp[1:nexp],listobs[1:nobs]),lty=c(array(1,dim=nexp),type[1:nobs]),lwd=c(array(2,dim=nexp),thickness[1:nobs]),col=c(color[1:nexp],array(1,dim=nobs)),cex=legsize)}
}else{
  if (leg) {legend(1,ul,listexp[1:nexp],lty=1,lwd=2,col=color[1:nexp],cex=legsize)}
}
#
dev.off()
}
#
################################################################################
CFU_spread <-function(var, posdim=2, narm=T) {
################################################################################
# 
#  Enlarge the size of var to 10 and move all posdim to first position 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimsvar=dim(var)
enlvar=CFU_enlarge(var,10)
outdim=c(dimsvar,array(1,dim=(10-length(dimsvar))))
posaperm=1:10
posaperm[(length(posdim)+1):10]=posaperm[-posdim]
posaperm[1:length(posdim)]=posdim
enlvar=aperm(enlvar,posaperm)
dimsaperm=outdim[posaperm]
outdim=1
for (jpos in 1:length(posdim) ) { outdim=outdim*dimsaperm[jpos] }
outdim=c(outdim,dimsaperm[(length(posdim)+1):10])
enlvar=array(enlvar,dim=outdim)
enlvar=CFU_enlarge(enlvar,10)
outdim=c(outdim,array(1,dim=(10-length(outdim))))
outdim[1]=3
#
#  IQR / Max-Min / STD / Median computation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
iqrvar=array(dim=outdim)
maxminvar=array(dim=outdim)
sdvar=array(dim=outdim)
medvar=array(dim=outdim)
#
for (j2 in 1:outdim[2]){
  for (j3 in 1:outdim[3]){
    for (j4 in 1:outdim[4]){
      for (j5 in 1:outdim[5]){
        for (j6 in 1:outdim[6]){
          for (j7 in 1:outdim[7]){
            for (j8 in 1:outdim[8]){ 
              for (j9 in 1:outdim[9]){
                for (j10 in 1:outdim[10]){
                  #
                  #  Compute spread along the posdim dimension 
                  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  whichspread=enlvar[,j2,j3,j4,j5,j6,j7,j8,j9,j10]
                  iqrvar[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]=IQR(whichspread,na.rm=narm)
                  maxminvar[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]=max(whichspread,na.rm=narm)-min(whichspread,na.rm=narm)
                  sdvar[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]=sd(whichspread,na.rm=narm)
                  medvar[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]=mad(whichspread,na.rm=narm)           
                  #
                  #  Bootstrapping and recomputing the spread
                  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  iqr_bs=c()
                  maxmin_bs=c()
                  sd_bs=c()
                  mad_bs=c()
                  Num=length(whichspread)
                  for (jmix in 1:100) {
                    drawings=round(runif(Num,0.5,Num+0.5))
                    iqr_bs=c(iqr_bs,IQR(whichspread[drawings],na.rm=narm))
                    maxmin_bs=c(maxmin_bs,max(whichspread[drawings],na.rm=narm)-min(whichspread[drawings],na.rm=narm))
                    sd_bs=c(sd_bs,sd(whichspread[drawings],na.rm=narm))
                    mad_bs=c(mad_bs,mad(whichspread[drawings],na.rm=narm))
                  }
                  #
                  #  95% confidence interval obtained from the bootstrapping results
                  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                  #  (This confidence interval is itself quite uncertain but it is not possible to produce miracle with 5 values ...)
                  #
                  iqrvar[1,j2,j3,j4,j5,j6,j7,j8,j9,j10]=quantile(iqr_bs,0.025,na.rm=narm)
                  iqrvar[3,j2,j3,j4,j5,j6,j7,j8,j9,j10]=quantile(iqr_bs,0.975,na.rm=narm)
                  maxminvar[1,j2,j3,j4,j5,j6,j7,j8,j9,j10]=maxminvar[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]+(quantile(maxmin_bs,0.025,na.rm=narm)-quantile(maxmin_bs,0.975,na.rm=narm))/2
                  maxminvar[3,j2,j3,j4,j5,j6,j7,j8,j9,j10]=maxminvar[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]-(quantile(maxmin_bs,0.025,na.rm=narm)-quantile(maxmin_bs,0.975,na.rm=narm))/2
                  sdvar[1,j2,j3,j4,j5,j6,j7,j8,j9,j10]=quantile(sd_bs,0.025,na.rm=narm)
                  sdvar[3,j2,j3,j4,j5,j6,j7,j8,j9,j10]=quantile(sd_bs,0.975,na.rm=narm)
                  medvar[1,j2,j3,j4,j5,j6,j7,j8,j9,j10]=medvar[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]+(quantile(mad_bs,0.025,na.rm=narm)-quantile(mad_bs,0.975,na.rm=narm))
                  medvar[3,j2,j3,j4,j5,j6,j7,j8,j9,j10]=medvar[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]-(quantile(mad_bs,0.025,na.rm=narm)-quantile(mad_bs,0.975,na.rm=narm))
                }
              }
            }
          }
        }
      }
    }
  }
}
#
#  Back to the original dimensions
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
posaperm=posdim[1]
dimsvar=dimsvar[-posdim]
if (posdim[1] > 1) { posaperm=c(posaperm,1:(posdim[1]-1)) }
if (posdim[1] <= length(dimsvar)) { posaperm=c(posaperm,(posdim[1]+1):(length(posdim)+length(dimsvar))) }
while ( length(posaperm) < 10 ) { posaperm=c(posaperm,length(posaperm)+1) }
outdim=outdim[posaperm]
outdim=outdim[1:(length(dimsvar)+1)]
tmpiqr=array(dim=outdim)
tmpmaxmin=array(dim=outdim)
tmpsd=array(dim=outdim)
tmpmed=array(dim=outdim)
tmpiqr[]=aperm(iqrvar,posaperm)
tmpmaxmin[]=aperm(maxminvar,posaperm)
tmpsd[]=aperm(sdvar,posaperm)
tmpmed[]=aperm(medvar,posaperm)
tmpmaxmin[which(tmpmaxmin==-Inf|tmpmaxmin==Inf)]=NA
tmpmed[which(tmpmed==-Inf|tmpmed==Inf)]=NA
#
#  Outputs
# ~~~~~~~~~
#
invisible(list(iqr=tmpiqr,maxmin=tmpmaxmin,sd=tmpsd,mad=tmpmed))
#
}
#
################################################################################
CFU_plotvsltime <-function(var, toptitle='', ytitle='', monini=1, freq=12, nticks=NULL, limits=NULL, listexp=c('exp1','exp2','exp3'), listobs=c('obs1','obs2','obs3'), biglab=F, hlines=NULL, leg=T, siglev=F, fileout='output_CFU_plotvsltime.eps',sizetit=1) {
#################################################################################
#
#  Get some arguments
# ~~~~~~~~~~~~~~~~~~~~
#
if (length(dim(var))==3) { var=CFU_insertdim(var,posdim=2,lendim=1)}
nleadtime=dim(var)[4]
nexp=dim(var)[1]
nobs=dim(var)[2]
if (is.null(limits)==T) {
  ll=min(var,na.rm=T)
  ul=max(var,na.rm=T)
  if (biglab) {ul=ul+0.4*(ul-ll)} else {ul=ul+0.3*(ul-ll)}
} else {
  ll=limits[1]
  ul=limits[2]
}
lastyear=(monini+(nleadtime-1)*12/freq-1)%/%12
lastmonth=(monini+(nleadtime-1)*12/freq-1)%%12+1
empty_ts=ts(start=c(0000,(monini-1)%/%(12/freq)+1),end=c(lastyear,(lastmonth-1)%/%(12/freq)+1),frequency=freq)
empty=array(dim=length(empty_ts))
#
#  Define some plot parameters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
if ( is.null(nticks) ) { if (biglab) {nticks=5} else {nticks=10} }
labind=seq(1,nleadtime,max(nleadtime%/%nticks,1))
months=c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")
labyear=((labind-1)*12/freq + monini -1)%/%12
labmonth=months[((labind-1)*12/freq + monini -1 )%%12 + 1]
for (jx in 1:length(labmonth)) {
  y2o3dig=paste("0",as.character(labyear[jx]),sep="")
  labmonth[jx]=paste(labmonth[jx],"\nYr ",substr(y2o3dig,nchar(y2o3dig)-1,nchar(y2o3dig)),sep="")
}
color=c("red1","dodgerblue1","green1","orange1","lightblue1","deeppink1","mediumpurple1","lightgoldenrod1","olivedrab1","mediumorchid1")
type=c(1,3,2,4)
thickness=array(dim=c(4,4))
thickness[,1]=c(1,2,1,1.5)
thickness[,2]=c(8,12,8,10)
thickness[,3]=thickness[,1]
thickness[,4]=c(4,6,4,5)
if (siglev==T) {
  lines=c("n","l","n","l")
}else{
  lines=c("l","l","l","n")
}
#
#  Define plot layout
# ~~~~~~~~~~~~~~~~~~~~
#
postscript(fileout,width=550,height=300)
if (biglab) {
 par(mai=c(1.25,1.4,0.5,1),mgp=c(4,2.5,0))
 par(cex=1.3,cex.lab=2,cex.axis=1.8)
 cexmain=2.2
 legsize=1.5
}else{
 par(mai=c(1,1.1,0.5,0),mgp=c(3,1.8,0))
 par(cex=1.3,cex.lab=1.5,cex.axis=1.1)
 cexmain=1.5
 legsize=1
}
plot(empty,ylim=c(ll,ul),xlab="Time (months)",ylab=ytitle,main=toptitle,cex.main=cexmain*sizetit,axes=FALSE)
axis(1,at=labind,labels=labmonth)
axis(2)
box()
if (is.null(hlines)!=T) { 
  for (jy in 1:length(hlines)) {
    par(new=TRUE) 
    abline(h=hlines[jy])
  }
}
#
#  Loop on experimental & observational data
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#                
legendnames=array(dim=nobs*nexp)
legendthick=array(dim=nobs*nexp)
legendsty=array(dim=nobs*nexp)
legendcol=array(dim=nobs*nexp)
ind=1
for (jt in seq(dim(var)[3],1,-1)){
  ind=1
  for (jexp in 1:nexp){
    for (jobs in 1:nobs){
      par(new=TRUE)
      plot(var[jexp,jobs,jt,],type=lines[jt],ylim=c(ll,ul),col=color[jexp],lty=type[jobs],lwd=thickness[jobs,jt],ylab="",xlab="",axes=FALSE)
      legendnames[ind]=paste(listexp[jexp],'vs',listobs[jobs])
      legendthick[ind]=thickness[jobs,1]*3
      legendsty[ind]=type[jobs]
      legendcol[ind]=color[jexp]
      ind=ind+1
    }
  }
}
if ( leg ) {
  if ( nobs==1 ) {legendnames=listexp[1:nexp]}  
  legend(1,ul,legendnames,lty=legendsty,lwd=legendthick,col=legendcol,cex=legsize)
}
#
dev.off()
#
}
#
################################################################################
CFU_plot2varsvsltime <-function(var1, var2, toptitle='', ytitle='', monini=1, freq=12, nticks=NULL, limits=NULL, listexp=c('exp1','exp2','exp3'), listvars=c('var1','var2'), biglab=F, hlines=NULL, leg=T, siglev=F, sizetit=1, fileout='output_CFU_plot2varsvsltime.eps', show_conf=T) {
#################################################################################
#
#  Get some arguments
# ~~~~~~~~~~~~~~~~~~~~
#
nvars = 2
#
if (length(dim(var1))!=length(dim(var2))) { 
    print("the two input variables should have the same dimensions")
    stop()
}
if (length(dim(var1))>=4) { 
    print("dimensions of input variables should be 3")
    stop()
}
nleadtime=dim(var1)[3]
nexp=dim(var1)[1]
var=array(dim=c(nvars,nexp,3,nleadtime))
for (jvar in 1:nvars) {
  varname=paste("var",as.character(jvar),sep="")
  var[jvar,,,] = get(varname)
  rm(varname)
}
if (is.null(limits)==T) {
  ll=min(var1,na.rm=T)
  ul=max(var1,na.rm=T)
  if (biglab) {ul=ul+0.4*(ul-ll)} else {ul=ul+0.3*(ul-ll)}
} else {
  ll=limits[1]
  ul=limits[2]
}
lastyear=(monini+(nleadtime-1)*12/freq-1)%/%12
lastmonth=(monini+(nleadtime-1)*12/freq-1)%%12+1
empty_ts=ts(start=c(0000,(monini-1)%/%(12/freq)+1),end=c(lastyear,(lastmonth-1)%/%(12/freq)+1),frequency=freq)
empty=array(dim=length(empty_ts))
#
#  Define some plot parameters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
if ( is.null(nticks) ) { if (biglab) {nticks=5} else {nticks=10} }
labind=seq(1,nleadtime,max(nleadtime%/%nticks,1))
months=c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")
labyear=((labind-1)*12/freq + monini -1)%/%12
labmonth=months[((labind-1)*12/freq + monini -1)%%12 + 1]
for (jx in 1:length(labmonth)) {
  y2o3dig=paste("0",as.character(labyear[jx]),sep="")
  labmonth[jx]=paste(labmonth[jx],"\nYr ",substr(y2o3dig,nchar(y2o3dig)-1,nchar(y2o3dig)),sep="")
}
color=c("red1","dodgerblue1","green1","orange1","lightblue1","deeppink1","mediumpurple1","lightgoldenrod1","olivedrab1","mediumorchid1")
type=c(1,3)
if (siglev==T) {
  lines=c("n","l","n")
}else{
  lines=c("l","l","l")
}
thickness=array(dim=c(3))
thickness[1]=c(1)
thickness[2]=c(8)
thickness[3]=thickness[1]
#
#  Define plot layout
# ~~~~~~~~~~~~~~~~~~~~
#
postscript(fileout,width=550,height=300)
if (biglab) {
 par(mai=c(1.25,1.4,0.5,1),mgp=c(4,2.5,0))
 par(cex=1.3,cex.lab=2,cex.axis=1.8)
 cexmain=2.2
 legsize=1.5
}else{
 par(mai=c(1,1.1,0.5,0),mgp=c(3,1.8,0))
 par(cex=1.3,cex.lab=1.5,cex.axis=1.1)
 cexmain=1.5
 legsize=1
}
plot(empty,ylim=c(ll,ul),xlab="Time (months)",ylab=ytitle,main=toptitle,cex.main=cexmain*sizetit,axes=FALSE)
axis(1,at=labind,labels=labmonth)
axis(2)
box()
if (is.null(hlines)!=T) { 
  for (jy in 1:length(hlines)) {
    par(new=TRUE) 
    abline(h=hlines[jy])
  }
}
#
#  Loop on experimental data
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#                
legendnames=array(dim=nexp*nvars)
legendthick=array(dim=nexp*nvars)
legendsty=array(dim=nexp*nvars)
legendcol=array(dim=nexp*nvars)
if (show_conf == T) {
    start_line = 3
    end_line = 1
} else {
    start_line = 2
    end_line = 2
}
for (jint in seq(start_line,end_line,-1)){
  ind=1
  for (jexp in 1:nexp){
    for (jvar in 1:nvars) {
      par(new=TRUE)
      plot(var[jvar,jexp,jint,],type=lines[jint],ylim=c(ll,ul),col=color[jexp],lty=type[jvar],lwd=thickness[jint],ylab="",xlab="",axes=FALSE)
      legendnames[ind]=paste(listexp[jexp],listvars[jvar])
      legendthick[ind]=2
      legendsty[ind]=type[jvar]
      legendcol[ind]=color[jexp]
      ind=ind+1
    }
  }
}
if ( leg ) {
  legend(1,ul,legendnames,lty=legendsty,lwd=legendthick,col=legendcol,cex=legsize)
}
dev.off()
}
#
#################################################################################
CFU_corr <-function(var_exp, var_obs, posloop=1, poscor=2, compROW=NULL, limits=NULL) {
#===============================================================================
#
#  Remove data along compROW dim if there is at least one NA between limits
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
if (is.null(compROW)==F) {
  if (is.null(limits)==T) { limits = c(1,dim(var_obs)[compROW]) }
  outrows=( is.na(CFU_mean1dim(var_obs,compROW,narm=F,limits)) ) 
  outrows=CFU_insertdim(outrows,compROW,dim(var_obs)[compROW])
  var_obs[which(outrows)]=NA
}
#
#  Enlarge var_exp & var_obs to 10 dim + move posloop & poscor to 1st & 2nd pos 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 
dimsvar=dim(var_exp)
for ( iind in 1:length(dimsvar) ) {
  if ( iind !=posloop & dim(var_obs)[iind] != dimsvar[iind] ) { 
    stop("var_exp & var_obs must have same dimensions except along posloop")
  }
}
if (dimsvar[poscor] < 3 ) {
  stop("At least 3 values required to compute correlation")
}
enlvarexp=CFU_enlarge(var_exp,10)
enlvarobs=CFU_enlarge(var_obs,10)
nexp=dimsvar[posloop]
nobs=dim(var_obs)[posloop]
posaperm=numeric(10)
posaperm[1]=posloop
posaperm[2]=poscor
posaperm[3:10]=seq(1,10)[-c(posloop,poscor)]
permvarexp=aperm(enlvarexp,posaperm)
permvarobs=aperm(enlvarobs,posaperm)
dimsaperm=dim(permvarexp)
#
#  Loop to compute correlation for each grid point
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
#
enlCORR=array(dim=c(nexp,nobs,4,dimsaperm[3:10]))
#
for (jexp in 1:nexp) {
  for (jobs in 1:nobs) {
    for (j3 in 1:dimsaperm[3]){
      for (j4 in 1:dimsaperm[4]){
        for (j5 in 1:dimsaperm[5]){
          for (j6 in 1:dimsaperm[6]){
            for (j7 in 1:dimsaperm[7]){
              for (j8 in 1:dimsaperm[8]){
                for (j9 in 1:dimsaperm[9]){
                  for (j10 in 1:dimsaperm[10]){
                    tmp1=permvarexp[jexp,,j3,j4,j5,j6,j7,j8,j9,j10]
                    tmp2=permvarobs[jobs,,j3,j4,j5,j6,j7,j8,j9,j10]
                    if ( length(sort(tmp1))>0 & length(sort(tmp2))>2) {
                      toto=cor(tmp1,tmp2,use="pairwise.complete.obs")
                      enlCORR[jexp,jobs,2,j3,j4,j5,j6,j7,j8,j9,j10]=toto
                      #eno=min(CFU_eno(tmp2,1),CFU_eno(tmp1,1))
                      eno=CFU_eno(tmp2,1)
                      t=qt(0.95, eno-2)
                      enlCORR[jexp,jobs,4,j3,j4,j5,j6,j7,j8,j9,j10]=sqrt((t*t)/((t*t)+eno-2))
                      enlCORR[jexp,jobs,1,j3,j4,j5,j6,j7,j8,j9,j10]=tanh(atanh(toto)+qnorm(0.975)/sqrt(eno-3))
                      enlCORR[jexp,jobs,3,j3,j4,j5,j6,j7,j8,j9,j10]=tanh(atanh(toto)+qnorm(0.025)/sqrt(eno-3))
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
#
CORR=array(dim=c(nexp,nobs,4,dimsvar[-c(posloop,poscor)]))
CORR[]=enlCORR
#  
#  Output
# ~~~~~~~~
#
CORR
#
}
#
################################################################################
CFU_RMS <-function(var_exp, var_obs, posloop=1, posRMS=2, compROW=NULL, limits=NULL) {
#===============================================================================
#
#  Remove data along compROW dim if there is at least one NA between limits
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
if (is.null(compROW)==F) {
  if (is.null(limits)==T) { limits = c(1,dim(var_obs)[compROW]) }
  outrows=( is.na(CFU_mean1dim(var_obs,compROW,narm=F,limits)) ) 
  outrows=CFU_insertdim(outrows,compROW,dim(var_obs)[compROW])
  var_obs[which(outrows)]=NA
}
#  Enlarge var_exp & var_obs to 10 dim + move posloop & posRMS to 1st & 2nd pos 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimsvar=dim(var_exp)
for ( iind in 1:length(dimsvar) ) {
  if ( iind !=posloop & dim(var_obs)[iind] != dimsvar[iind] ) { 
    stop("var_exp & var_obs must have same dimensions except along posloop")
  }
}
if (dimsvar[posRMS] < 2 ) {
  stop("At least 2 values required to compute RMSE")
}
enlvarexp=CFU_enlarge(var_exp,10)
enlvarobs=CFU_enlarge(var_obs,10)
nexp=dimsvar[posloop]
nobs=dim(var_obs)[posloop]
posaperm=numeric(10)
posaperm[1]=posloop
posaperm[2]=posRMS
posaperm[3:10]=seq(1,10)[-c(posloop,posRMS)]
permvarexp=aperm(enlvarexp,posaperm)
permvarobs=aperm(enlvarobs,posaperm)
dimsaperm=dim(permvarexp)
#
#  RMS & its confidence interval computation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
enlrms=array(dim=c(nexp,nobs,3,dimsaperm[3:10]))
#
for (jexp in 1:nexp) {
  for (jobs in 1:nobs) {
    dif=array(dim=dimsaperm[-1])
    dif[,,,,,,,,]=permvarexp[jexp,,,,,,,,,]-permvarobs[jobs,,,,,,,,,]
    enlrms[jexp,jobs,2,,,,,,,,]=CFU_mean1dim(dif**2,1,narm=T)**0.5
    eno=CFU_eno(dif,1)
    for (j3 in 1:dimsaperm[3]){
      for (j4 in 1:dimsaperm[4]){
        for (j5 in 1:dimsaperm[5]){
          for (j6 in 1:dimsaperm[6]){
            for (j7 in 1:dimsaperm[7]){
              for (j8 in 1:dimsaperm[8]){
                for (j9 in 1:dimsaperm[9]){
                  for (j10 in 1:dimsaperm[10]){
                    ndat=length(sort(dif[,j3,j4,j5,j6,j7,j8,j9,j10]))
                    enlrms[jexp,jobs,1,j3,j4,j5,j6,j7,j8,j9,j10]=(eno[j3,j4,j5,j6,j7,j8,j9,j10]*enlrms[jexp,jobs,2,j3,j4,j5,j6,j7,j8,j9,j10]**2/qchisq(0.975,eno[j3,j4,j5,j6,j7,j8,j9,j10]-1))**0.5
                    enlrms[jexp,jobs,3,j3,j4,j5,j6,j7,j8,j9,j10]=(eno[j3,j4,j5,j6,j7,j8,j9,j10]*enlrms[jexp,jobs,2,j3,j4,j5,j6,j7,j8,j9,j10]**2/qchisq(0.025,eno[j3,j4,j5,j6,j7,j8,j9,j10]-1))**0.5
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
#
rms=array(dim=c(nexp,nobs,3,dimsvar[-c(posloop,posRMS)]))
rms[]=enlrms
#  
#  Output
# ~~~~~~~~
#
rms
#
}
#
################################################################################
CFU_RMSSS <-function(var_exp, var_obs, posloop=1, posRMS=2) {
#===============================================================================
#
#  Enlarge var_exp & var_obs & clim to 10 dim + move posloop & posRMS  
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimsvar=dim(var_exp)
for ( iind in 1:length(dimsvar) ) {
  if ( iind !=posloop & dim(var_obs)[iind] != dimsvar[iind] ) { 
    stop("var_exp & var_obs must have same dimensions except along posloop")
  }
}
if (dimsvar[posRMS] < 2 ) {
  stop("At least 2 values required to compute RMSE")
}
enlvarexp=CFU_enlarge(var_exp,10)
enlvarobs=CFU_enlarge(var_obs,10)
nexp=dimsvar[posloop]
nobs=dim(var_obs)[posloop]
posaperm=numeric(10)
posaperm[1]=posloop
posaperm[2]=posRMS
posaperm[3:10]=seq(1,10)[-c(posloop,posRMS)]
permvarexp=aperm(enlvarexp,posaperm)
permvarobs=aperm(enlvarobs,posaperm)
dimsaperm=dim(permvarexp)
#
#  RMSSS and its pvalue computation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
enlRMSSS=array(dim=c(nexp,nobs,2,dimsaperm[3:10]))
#
for (jexp in 1:nexp) {
  for (jobs in 1:nobs) {
    dif1=array(dim=dimsaperm[-1])
    dif2=array(dim=dimsaperm[-1])
    dif1[,,,,,,,,]=permvarexp[jexp,,,,,,,,,]-permvarobs[jobs,,,,,,,,,]
    dif2[,,,,,,,,]=permvarobs[jobs,,,,,,,,,]
    rms1=CFU_mean1dim(dif1**2,1,narm=T)**0.5
    rms2=CFU_mean1dim(dif2**2,1,narm=T)**0.5
    rms2[which(abs(rms2)<=(max(abs(rms2),na.rm=T)/1000))]=max(abs(rms2),na.rm=T)/1000
    enlRMSSS[jexp,jobs,1,,,,,,,,]=1-(rms1/rms2)
    eno1=CFU_eno(dif1,1)
    eno2=CFU_eno(dif2,1)
    F=(eno2*(rms2)**2/(eno2-1))/(eno1*(rms1)**2/(eno1-1))
    for (j3 in 1:dimsaperm[3]){
      for (j4 in 1:dimsaperm[4]){
        for (j5 in 1:dimsaperm[5]){
          for (j6 in 1:dimsaperm[6]){
            for (j7 in 1:dimsaperm[7]){
              for (j8 in 1:dimsaperm[8]){
                for (j9 in 1:dimsaperm[9]){
                  for (j10 in 1:dimsaperm[10]){
                    l1=eno1[j3,j4,j5,j6,j7,j8,j9,j10]
                    l2=eno2[j3,j4,j5,j6,j7,j8,j9,j10]
                    if ( is.na(l1)==FALSE & is.na(l2)==FALSE & l1 > 2 & l2 > 2 ) {
                      enlRMSSS[jexp,jobs,2,j3,j4,j5,j6,j7,j8,j9,j10]=1-pf(F[j3,j4,j5,j6,j7,j8,j9,j10],l1-1,l2-1)
                    }else{
                      enlRMSSS[jexp,jobs,1,j3,j4,j5,j6,j7,j8,j9,j10]=NA
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
#
RMSSS=array(dim=c(nexp,nobs,2,dimsvar[-c(posloop,posRMS)]))
RMSSS[]=enlRMSSS
#
#  Output
# ~~~~~~~~
#
RMSSS
#
}
#
################################################################################
CFU_ratioRMS <-function(var_exp1, var_exp2, var_obs, posRMS=1) {
#===============================================================================
#
#  Enlarge var_exps & var_obs to 10 dim + move posRMS to 1st pos 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimsvar=dim(var_exp1)
for ( iind in 1:length(dimsvar) ) {
  if ( dim(var_exp2)[iind]!=dimsvar[iind] | dim(var_obs)[iind]!=dimsvar[iind] ) {
    stop("all input vars should have the same dimensions")
  }
} 
enlvarexp1=CFU_enlarge(var_exp1,10)
enlvarexp2=CFU_enlarge(var_exp2,10)
enlvarobs=CFU_enlarge(var_obs,10)
posaperm=1:10
posaperm[1]=posRMS
posaperm[posRMS]=1
permvarexp1=aperm(enlvarexp1,posaperm)
permvarexp2=aperm(enlvarexp2,posaperm)
permvarobs=aperm(enlvarobs,posaperm)
dimsaperm=dim(permvarexp1)
#
#  RMS ratio and its pvalue computation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
enlratiorms=array(dim=c(2,dimsaperm[2:10]))
dif1=permvarexp1-permvarobs
dif2=permvarexp2-permvarobs
rms1=CFU_mean1dim(dif1**2,1,narm=T)**0.5
rms2=CFU_mean1dim(dif2**2,1,narm=T)**0.5
rms2[which(abs(rms2)<=(max(abs(rms2),na.rm=T)/1000))]=max(abs(rms2),na.rm=T)/1000
enlratiorms[1,,,,,,,,,]=(rms1/rms2)
eno1=CFU_eno(dif1,1)
eno2=CFU_eno(dif2,1)
F=(eno1*(rms1)**2/(eno1-1))/(eno2*(rms2)**2/(eno2-1))
F[which(F<1)]=1/F[which(F<1)]
for (j2 in 1:dimsaperm[2]){
  for (j3 in 1:dimsaperm[3]){
    for (j4 in 1:dimsaperm[4]){
      for (j5 in 1:dimsaperm[5]){
        for (j6 in 1:dimsaperm[6]){
          for (j7 in 1:dimsaperm[7]){
            for (j8 in 1:dimsaperm[8]){
              for (j9 in 1:dimsaperm[9]){
                for (j10 in 1:dimsaperm[10]){
                  l1=eno1[j2,j3,j4,j5,j6,j7,j8,j9,j10]
                  l2=eno2[j2,j3,j4,j5,j6,j7,j8,j9,j10]
                  if ( is.na(l1)==FALSE & is.na(l2)==FALSE & l1 > 2 & l2 > 2 ) {
                    enlratiorms[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]=(1-pf(F[j2,j3,j4,j5,j6,j7,j8,j9,j10],l1-1,l2-1))*2
                  }else{
                    enlratiorms[1,j2,j3,j4,j5,j6,j7,j8,j9,j10]=NA
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
#
dimsvar[posRMS]=2
ratiorms=array(dim=dimsvar)
ratiorms[]=aperm(enlratiorms,posaperm)
#  
#  Output
# ~~~~~~~~
#
ratiorms
#
}
#
################################################################################
CFU_ratioSDRMS <-function(var_exp, var_obs) {
#===============================================================================
#
#  Enlarge the number of dimensions of var_exp and var_obs to 7 if necessary
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimexp=dim(var_exp)
dimobs=dim(var_obs)
if ( length(dimexp) < 4 | length(dimobs) < 4 ) {
  stop("At least 4 dim needed : c(nexp/nobs, nmemb, nsdates, nltime)")
}
for ( jn in 3:max(length(dimexp),length(dimobs)) )
  if ( dimexp[jn]!=dimobs[jn] ) { stop("Wrong input dimensions") }
var_exp=CFU_enlarge(var_exp,7)
var_obs=CFU_enlarge(var_obs,7)
#
#  Ratio RMSE / SD and its significance level
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
ensmeanexp=CFU_mean1dim(var_exp,2)
ensmeanobs=CFU_mean1dim(var_obs,2)
dimrms=c(dimexp[1],dimobs[1],dimexp[4:length(dimexp)])
dimratiormssd=c(dimexp[1],dimobs[1],2,dimexp[4:length(dimexp)])
if ( length(dimrms) < 6 ) { dimrms=c(dimrms,array(1,dim=(6-length(dimrms)))) }
if ( length(dimratiormssd) < 7 ) { dimenlratiormssd=c(dimratiormssd,array(1,dim=(7-length(dimratiormssd)))) } else { dimenlratiormssd=dimratiormssd }
dif=var_exp-CFU_insertdim(ensmeanexp,2,dimexp[2])
std=apply(array(dif,dim=c(dimexp[1],dimexp[2]*dimexp[3],dimrms[3:6])),c(1,3,4,5,6),sd,na.rm=T)
enosd=apply(CFU_eno(dif,3),c(1,3,4,5,6),sum,na.rm=T)
rms=array(dim=dimrms)
enlratiormssd=array(dim=dimenlratiormssd)
for (jexp in 1:dimexp[1]) {
  for (jobs in 1:dimobs[1]) {
    dif=ensmeanexp[jexp,,,,,]-ensmeanobs[jobs,,,,,]
    rms[jexp,jobs,,,,]=CFU_mean1dim(dif**2,1,narm=T)**0.5
    enorms=array(CFU_eno(dif,1),dim=dimrms[3:6])
    enlratiormssd[jexp,jobs,1,,,,]=std[jexp,,,,]/rms[jexp,jobs,,,,]
    for (jltime in 1:dimrms[3]) {
      for (jlev in 1:dimrms[4]) {
        for (jlat in 1:dimrms[5]) {
          for (jlon in 1:dimrms[6]) {
            l1=enosd[jexp,jltime,jlev,jlat,jlon]
            l2=enorms[jltime,jlev,jlat,jlon]
            F=(enosd[jexp,jltime,jlev,jlat,jlon]*(std[jexp,jltime,jlev,jlat,jlon])**2/(enosd[jexp,jltime,jlev,jlat,jlon]-1))/(enorms[jltime,jlev,jlat,jlon]*(rms[jexp,jobs,jltime,jlev,jlat,jlon])**2/(enorms[jltime,jlev,jlat,jlon]-1))
            if ( is.na(F)==FALSE & is.na(l1)==FALSE & is.na(l2)==FALSE & l1 > 2 & l2 > 2 ) {
              enlratiormssd[jexp,jobs,2,jltime,jlev,jlat,jlon]=1-pf(F,l1-1,l2-1)
            }else{
              enlratiormssd[jexp,jobs,1,jltime,jlev,jlat,jlon]=NA
            }
          }
        }
      }
    }
  }
}
#
ratiosdrms=array(dim=dimratiormssd)
ratiosdrms[]=enlratiormssd
#  
#  Output
# ~~~~~~~~
#
ratiosdrms
#
}
#
################################################################################
CFU_consist_trend<-function(var_exp, var_obs, interval=1 ) {
#===============================================================================
#
#  Enlarge the number of dimensions of var_exp and var_obs to 6 if necessary
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimexp=dim(var_exp)
dimobs=dim(var_obs)
if ( length(dimexp) < 3 | length(dimobs) < 3 ) {
  stop("At least 3 dim needed : c(nexp/nobs, nsdates, nltime)") 
}
for ( jn in 2:max(length(dimexp),length(dimobs)) )  
  if ( dimexp[jn]!=dimobs[jn] ) { stop("Wrong input dimensions") }
var_exp=CFU_enlarge(var_exp,6)
var_obs=CFU_enlarge(var_obs,6)
#
#  Find common points to compute trends 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
tmp=CFU_meanlistdim(var_obs,dims=4:6,narm=T)
tmp2=CFU_meanlistdim(var_exp,dims=4:6,narm=T)
nan=CFU_mean1dim(tmp,1,narm=F)+CFU_mean1dim(tmp2,1,narm=F)
for (jdate in 1:dimexp[2]) {
  for (jtime in 1:dimexp[3]) {
    if (is.na(nan[jdate,jtime])) {
      var_exp[,jdate,jtime,,,]=NA
      var_obs[,jdate,jtime,,,]=NA
    }
  }
}
#
#  Compute trends 
# ~~~~~~~~~~~~~~~~
#
trendcat=array(dim=c(dimobs[1]+dimexp[1],4,dim(var_obs)[3:6]))
detrendedmod=array(dim=dimexp)
detrendedobs=array(dim=dimobs)
tmp1=CFU_trend(var_exp,2,interval=interval)
tmp2=CFU_trend(var_obs,2,interval=interval)
trendcat[1:dimexp[1],,,,,]=tmp1$trend
trendcat[(dimexp[1]+1):dim(trendcat)[1],,,,,]=tmp2$trend
detrendedmod[]=tmp1$detrended
detrendedobs[]=tmp2$detrended
#
#
#  Back to the original dimensions
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
outtrendcat=array(dim=c(dimobs[1]+dimexp[1],4,dimobs[3:length(dimobs)]))
outtrendcat[]=trendcat
#
#  Outputs
# ~~~~~~~~~
#
invisible(list(trend=outtrendcat,detrendedmod=detrendedmod,detrendedobs=detrendedobs))
#
}
#
###############################################################################
CFU_trend<-function(var, posTR=2, interval=1 ) {
#===============================================================================
#
#  Enlarge the size of var to 10 and move posTR to first position 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 
dimsvar=dim(var)
if (is.null(dimsvar) ) { dimsvar=length(var) }
enlvar=CFU_enlarge(var,10)
outdim=c(dimsvar,array(1,dim=(10-length(dimsvar))))
outdim[posTR]=4
posaperm=1:10
posaperm[posTR]=1
posaperm[1]=posTR
enlvar=aperm(enlvar,posaperm)
dimsaperm=outdim[posaperm]
#
#  Loop on all dimensions to compute trends 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
enltrend=array(dim=dimsaperm)
enldetrend=array(dim=dim(enlvar))
for (j2 in 1:dimsaperm[2]){
  for (j3 in 1:dimsaperm[3]){
    for (j4 in 1:dimsaperm[4]){
      for (j5 in 1:dimsaperm[5]){
        for (j6 in 1:dimsaperm[6]){
          for (j7 in 1:dimsaperm[7]){
            for (j8 in 1:dimsaperm[8]){
              for (j9 in 1:dimsaperm[9]){
                for (j10 in 1:dimsaperm[10]){
                  tmp=enlvar[,j2,j3,j4,j5,j6,j7,j8,j9,j10]
                  if ( length(sort(tmp)) > 0 ) {
                    mon=seq(tmp)*interval
                    lm.out=lm(tmp ~ mon,na.action=na.omit)
                    enltrend[1,j2,j3,j4,j5,j6,j7,j8,j9,j10]=confint(lm.out)[2,1]
                    enltrend[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]=lm.out$coefficients[2]
                    enltrend[3,j2,j3,j4,j5,j6,j7,j8,j9,j10]=confint(lm.out)[2,2]
                    enltrend[4,j2,j3,j4,j5,j6,j7,j8,j9,j10]=lm.out$coefficients[1]
                    enldetrend[is.na(tmp)==F,j2,j3,j4,j5,j6,j7,j8,j9,j10]=tmp[is.na(tmp)==F]-lm.out$fitted.values  
                  }
                } 
              }
            }
          }
        }
      }
    }
  }
}
#
#  Back to the original dimensions
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
detrended=array(dim=dimsvar)
dimsvar[posTR]=4
trend=array(dim=dimsvar)
trend[]=aperm(enltrend,posaperm)
detrended[]=aperm(enldetrend,posaperm)
#
#  Outputs
# ~~~~~~~~~
#
invisible(list(trend=trend,detrended=detrended))
#
}
#
###############################################################################
CFU_regression<-function(vary, varx, posREG=2) {
#==============================================================================
#
#  Enlarge the size of varx and vary to 10
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 
dimsvar=dim(vary)
if (is.null(dimsvar) ) { dimsvar=length(vary) }
if (length(dimsvar)==1) { if (length(varx)!=dimsvar[1]) { stop("varx and vary should have the same dimensions") } }
else { for (jdim in 1:length(dimsvar)) { if (dim(varx)[jdim]!=dimsvar[jdim]) { stop("varx and vary should have the same dimensions") } } }
enlvarx=CFU_enlarge(varx,10)
enlvary=CFU_enlarge(vary,10)
outdim=dim(enlvarx)
#
#  Initialize intermediate and output matrices
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
posaperm=1:10
posaperm[1]=posREG
posaperm[posREG]=1
enlvarx=aperm(enlvarx,posaperm)
enlvary=aperm(enlvary,posaperm)
dimsaperm=outdim[posaperm]
#
enlfilt=array(dim=dimsaperm)
filtered=array(dim=dimsvar)
dimsaperm[1]=4
enlreg=array(dim=dimsaperm)
dimsvar[posREG]=4
regression=array(dim=dimsvar)
#
#  Loop on all dimensions to compute regressions 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
for (j2 in 1:dimsaperm[2]){
  for (j3 in 1:dimsaperm[3]){
    for (j4 in 1:dimsaperm[4]){
      for (j5 in 1:dimsaperm[5]){
        for (j6 in 1:dimsaperm[6]){
          for (j7 in 1:dimsaperm[7]){
            for (j8 in 1:dimsaperm[8]){
              for (j9 in 1:dimsaperm[9]){
                for (j10 in 1:dimsaperm[10]){
                  tmpy=enlvary[,j2,j3,j4,j5,j6,j7,j8,j9,j10]
                  tmpx=enlvarx[,j2,j3,j4,j5,j6,j7,j8,j9,j10]
                  if ( (length(sort(tmpy)) > 0) & (length(sort(tmpx)) > 0) ) {
                    lm.out=lm(tmpy ~ tmpx,na.action=na.omit)
                    enlreg[1,j2,j3,j4,j5,j6,j7,j8,j9,j10]=confint(lm.out)[2,1]
                    enlreg[2,j2,j3,j4,j5,j6,j7,j8,j9,j10]=lm.out$coefficients[2]
                    enlreg[3,j2,j3,j4,j5,j6,j7,j8,j9,j10]=confint(lm.out)[2,2]
                    enlreg[4,j2,j3,j4,j5,j6,j7,j8,j9,j10]=lm.out$coefficients[1]
                    enlfilt[which(is.na(tmpx)==F&is.na(tmpy)==F),j2,j3,j4,j5,j6,j7,j8,j9,j10]=tmpy[which(is.na(tmpx)==F&is.na(tmpy)==F)]-lm.out$fitted.values  
                  }
                } 
              }
            }
          }
        }
      }
    }
  }
}
#
#  Back to the original dimensions
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
regression[]=aperm(enlreg,posaperm)
filtered[]=aperm(enlfilt,posaperm)
#
#  Outputs
# ~~~~~~~~~
#
invisible(list(regression=regression,filtered=filtered))
#
}
################################################################################
CFU_plotequimap<-function(var, lon, lat, toptitle='', sizetit=1, units='', brks=NULL, cols=NULL, square=TRUE, filled.continents=TRUE, contours=NULL, brks2=NULL, dots=NULL, axelab=T, labW=F, intylat=20, intxlon=20, drawleg=T, subsampleg=1, numbfig=1, colNA='white' ) {
#===============================================================================
#
#  Some required packages 
# ~~~~~~~~~~~~~~~~~~~~~~~~
#
library(GEOmap)
library(geomapdata)
library(maps)
data(coastmap)
#
#  Input arguments 
# ~~~~~~~~~~~~~~~~~
#
dims=dim(var)
if ( length(dims) > 2 ) {
  stop("Only 2 dimensions expected for var : (lon,lat) ")
}
if ( dims[1] != length(lon) | dims[2] != length(lat) ) {
  if ( dims[1] == length(lat) & dims[2] == length(lon) ) {
    var=t(var)
    dims=dim(var)
  }else{
    stop("Inconsistent var dimensions / longitudes +  latitudes")
  }
}
latb=sort(lat,index.return=TRUE)
dlon=lon[2:dims[1]]-lon[1:(dims[1]-1)]
wher=which(dlon>(mean(dlon)+1))
if (length(wher)>0) { lon[(wher+1):dims[1]]=lon[(wher+1):dims[1]]-360 }
lonb=sort(lon,index.return=TRUE)
latmin=floor(min(lat)/10)*10
latmax=ceiling(max(lat)/10)*10
lonmin=floor(min(lon)/10)*10
lonmax=ceiling(max(lon)/10)*10
#
if ( is.null(brks) == T ) {
  ll=signif(min(var,na.rm=T),4)
  ul=signif(max(var,na.rm=T),4)
  if (is.null(cols) == T) { cols=c("dodgerblue4","dodgerblue1","forestgreen","yellowgreen","white","white","yellow","orange","red","saddlebrown") }
  nlev=length(cols)
  brks=signif(seq(ll,ul,(ul-ll)/nlev),4)
}else{
  if (is.null(cols) == T) {
    nlev=length(brks)-1
    cols=rainbow(nlev)
  }else{
    if ( length(cols) != (length(brks)-1) ){
      stop("Inconsistent colour levels / list of colours")
    }
  }
}

if ( is.null(brks2) == T ) {
  if ( is.null(contours) ) { 
    if ( square == F ) {
      brks2=brks
      contours=var 
    }
  }else{
    ll=signif(min(contours,na.rm=T),2)
    ul=signif(max(contours,na.rm=T),2)
    brks2=signif(seq(ll,ul,(ul-ll)/(length(brks)-1)),2)
  }
}
#
#  Plotting the map
# ~~~~~~~~~~~~~~~~~~
#
if (axelab==T) { 
  ypos=seq(latmin,latmax,intylat)
  xpos=seq(lonmin,lonmax,intxlon)
  letters=array('',length(ypos))
  letters[ypos<0]='S'
  letters[ypos>0]='N'
  ylabs=paste(as.character(abs(ypos)),letters,sep='')
  letters=array('',length(xpos))
  if (labW) {
    nlon <- length(xpos)
    xpos2=xpos  
    xpos2[xpos2>180]=360-xpos2[xpos2>180]
  }
  letters[xpos<0]='W'
  letters[xpos>0]='E'
  if (labW) {
    letters[xpos==0]=' '
    letters[xpos==180]=' '
    letters[xpos>180]='W'  
    xlabs=paste(as.character(abs(xpos2)),letters,sep='')
  }else{
    xlabs=paste(as.character(abs(xpos)),letters,sep='')
  }
  xmargin=1.2-(numbfig^0.2)*0.05
  ymargin=3-(numbfig^0.2)
  spaceticklab=1.3-(numbfig^0.2)*0.8
  topmargin=0.4
  ymargin2=1.5-(numbfig^0.2)*0.9
}else{
  xmargin=0.2
  ymargin=0.2+switch(as.character(square),'FALSE'=1.8,0)
  topmargin=0.2
  spaceticklab=1
  ymargin2=0.2
}
if ( toptitle != '' ) { topmargin=2.5-(numbfig^0.2)*0.6}
#
if (min(lon)<0) {continents='world'} else {continents='world2'}
if (square) {
  if (drawleg) {
    layout(matrix(1:2, ncol = 1, nrow=2), heights = c(5,1))
  }
  par(mar = c(xmargin, ymargin, topmargin, ymargin2), cex = 1.4, mgp=c(3,spaceticklab,0), las=0 )
  if( colNA != 'white') {
    blanks=array(0,dim=c(length(lonb$x),length(latb$x)))
    image(lonb$x,latb$x,blanks,col=c(colNA),breaks=c(-1,1),main=toptitle, cex.main=(1.5/numbfig^(0.2))*sizetit, axes = FALSE, xlab="",ylab="")
    flagadd=T
  }else{  
    flagadd=F
  }
  image(lonb$x,latb$x,var[lonb$ix,latb$ix],col=cols,breaks=brks,main=toptitle, axes = FALSE, xlab="",ylab="",cex.main=(1.5/numbfig^(0.2))*sizetit,add=flagadd)
  if (axelab==T) {
    axis(2,at=ypos,labels=ylabs,cex.axis=1/(numbfig^0.3),tck=-0.03)
    axis(1,at=xpos,labels=xlabs,cex.axis=1/(numbfig^0.3),tck=-0.03)
  }
  if (is.null(contours)==F) {
    contour(lonb$x,latb$x,contours[lonb$ix,latb$ix],levels=brks2,method="edge",add=TRUE,labcex = 1/numbfig,lwd=0.5/(numbfig^0.5))
  }
  map(continents, interior = F, add = T, lwd=1)
  box()
}else{
  par(mar = c(xmargin+5, ymargin+1.5, topmargin, ymargin2), cex.main=(1.6*numbfig^(0.3))*sizetit, cex.axis=1.4, cex.lab=1.6, mgp=c(3,spaceticklab+0.5,0), las=0 )
  if (axelab==T) {
    filled.contour(lonb$x,latb$x,var[lonb$ix,latb$ix],xlab="",levels=brks,col=cols,ylab="",main=toptitle,key.axes =axis(4,brks[seq(1,length(brks),subsampleg)],cex.axis=1/(numbfig^0.3)) , plot.axes = {axis(2,at=ypos,labels=ylabs,cex.axis=1/(numbfig^0.3),tck=-0.03 )
    axis(1,at=xpos,labels=xlabs,cex.axis=1/(numbfig^0.3),tck=-0.03)
    contour(lonb$x,latb$x,contours[lonb$ix,latb$ix],levels=brks2,method="edge",add=TRUE,labcex = 1,lwd=2)
    map(continents,interior=F,xlim=c(lonmin,lonmax),ylim=c(latmin,latmax),add=T) },
    key.title = title(main=units,cex.main=(1.2*numbfig^(0.3))*sizetit))
 }else{
    filled.contour(lonb$x,latb$x,var[lonb$ix,latb$ix],xlab="",levels=brks,col=cols,ylab="",main=toptitle,key.axes =axis(4,brks[seq(1,length(brks),subsampleg)],cex.axis=1/(numbfig^0.3)) , plot.axes = {contour(lonb$x,latb$x,contours[lonb$ix,latb$ix],levels=brks2,method="edge",add=TRUE,labcex = 1,lwd=2)
    map(continents,interior=F,xlim=c(lonmin,lonmax),ylim=c(latmin,latmax),add=T) },
    key.title = title(main=units,cex.main=(1.2*numbfig^(0.3))*sizetit))
 }
}
#
#  Adding black dots  
# ~~~~~~~~~~~~~~~~~~~
#
if ( is.null(dots)==F ) {
  for (ix in 1:length(lon)) {
    for (jy in 1:length(lat)) {
      if ( is.na(var[ix,jy]) == F ) {
        if ( dots[ix,jy] == T ) {
          text(x=lon[ix],y=lat[jy],".",cex = 12/(sqrt(sqrt(length(var)))*numbfig^0.5))
        }
      }
    }
  }
}
#
#  Filling continents
# ~~~~~~~~~~~~~~~~~~~~
# 
if (square == T & filled.continents == T) {
    if (min(lon)>=0) {
      ylat=latmin:latmax
      xlon=lonmin:lonmax
      proj=setPROJ(1,LON0=mean(xlon),LAT0=mean(ylat),LATS=ylat,LONS=xlon)
      coastmap$STROKES$col[which(coastmap$STROKES$col=="blue")]="white"
      par(new=TRUE)
      plotGEOmap(coastmap,PROJ=proj,border='black',add=TRUE)
      box()
    } else {
        map(continents,interior=F,wrap=TRUE,lwd=0.7,col=gray(0.5),fill=T,add=T,border=gray(0.5))
    }
}
#
#  Colorbar
# ~~~~~~~~~~
#
if (square & drawleg) {
  par(mar = c(1.5, ymargin+1.5, 2.5, ymargin2), mgp = c(1.5, 0.3, 0), las = 1, cex = 1.2)
  image(1:length(cols),1, t(t(1:length(cols))), axes = F, col = cols,xlab = '', ylab = '', main=units, cex.main=1.1)
  box()
  axis(1, at = seq(0.5, length(brks)-0.5, subsampleg), labels = brks[seq(1,length(brks),subsampleg)])
  #title(xlab = units)
}
#
}
################################################################################
CFU_plotsection<-function(var, horiz, depth, toptitle='', sizetit=1, units='', brks=NULL, cols=NULL, axelab=T, intydep=200, intxhoriz=20, drawleg=T) {
#===============================================================================
#
#  Input arguments 
# ~~~~~~~~~~~~~~~~~
#
dims=dim(var)
if ( length(dims) > 2 ) {
  stop("Only 2 dimensions expected for var : (lon,depth) or (lat,depth)")
}
if ( dims[1] != length(horiz) | dims[2] != length(depth) ) {
  if ( dims[1] == length(depth) & dims[2] == length(horiz) ) {
    var=t(var)
    dims=dim(var)
  }else{
    stop("Inconsistent var dimensions and longitudes/latitudes + depth")
  }
}
dhoriz=horiz[2:dims[1]]-horiz[1:(dims[1]-1)]
wher=which(dhoriz>(mean(dhoriz)+5))
if (length(wher)>0) { horiz[(wher+1):dims[1]]=horiz[(wher+1):dims[1]]-360 }
horizb=sort(horiz,index.return=TRUE)
depthb=sort(-abs(depth),index.return=TRUE)
horizmin=floor(min(horiz)/10)*10
horizmax=ceiling(max(horiz)/10)*10
depmin=min(depth)
depmax=max(depth)
#
if ( is.null(brks) == T ) {
  ll=signif(min(var,na.rm=T),4)
  ul=signif(max(var,na.rm=T),4)
  if (is.null(cols) == T) { cols=c("dodgerblue4","dodgerblue1","forestgreen","yellowgreen","white","white","yellow","orange","red","saddlebrown") }
  nlev=length(cols)
  brks=signif(seq(ll,ul,(ul-ll)/nlev),4)
}else{
  if (is.null(cols) == T) {
    nlev=length(brks)-1
    cols=rainbow(nlev)
  }else{
    if ( length(cols) != (length(brks)-1) ){
      stop("Inconsistent colour levels / list of colours")
    }
  }
}
#
#  Plotting the section
# ~~~~~~~~~~~~~~~~~~
#
xmargin=0.5
ymargin=0.5
topmargin=3
if (axelab) {
  ymargin=ymargin+2.5
  xmargin=xmargin+1.5
}
if (drawleg) {
  layout(matrix(1:2, ncol = 1, nrow=2), heights = c(5,1))
  xmargin=max(xmargin-1.8,0)
}
if ( toptitle=='' ) { 
  topmargin=topmargin-2.5 
} 
par(mar = c(xmargin, ymargin, topmargin, 0.5), cex = 1.4, mgp=c(2.5,0.5,0), las=1 )
image(horizb$x,depthb$x,array(0,dims),col='grey',breaks=c(-1,1),axes=FALSE,xlab="",ylab="",main=toptitle,cex.main=1.5*sizetit)
image(horizb$x,depthb$x,var[horizb$ix,depthb$ix],col=cols,breaks=brks,axes=FALSE,xlab="",ylab="",add=T)
if (axelab) {
  minhoriz=ceiling(round(min(horizb$x),0)/10)*10
  maxhoriz=floor(round(max(horizb$x),0)/10)*10
  axis(1,at=seq(minhoriz,maxhoriz,intxhoriz),tck=-0.02)
  maxdepth=floor(round(max(depthb$x),0)/10)*10
  axis(2,at=seq(-8000,0,intydep),tck=-0.015)
}
box()
#
#  Colorbar
# ~~~~~~~~~~
#
if (drawleg) {
  par(mar = c(1.5, ymargin, 2.5, 0.5), mgp = c(1.5, 0.3, 0), las = 1, cex = 1.2)
  image(1:length(cols),1, t(t(1:length(cols))), axes = F, col = cols,xlab = units, ylab = '')
  box()
  axis(1, at = seq(0.5, length(brks)-0.5, 1), labels = brks, cex.axis=1)
}

}
################################################################################
CFU_colorbar<-function(brks, cols=NULL, vert=TRUE, subsampleg=1){
#===============================================================================
#
#  Input arguments
# ~~~~~~~~~~~~~~~~~
#
if (is.null(cols) == T) {
  nlev=length(brks)-1
  cols=rainbow(nlev)
}else{
  if ( length(cols) != (length(brks)-1) ){
    stop("Inconsistent colour levels / list of colours")
  }
}
# 
#  Plotting colorbar
# ~~~~~~~~~~~~~~~~~~~
#
if (vert) {
  par(mar = c(1, 1, 1, 2.5), mgp = c(1, 1, 0), las = 1,cex=1.2)
  image(1,c(1:length(cols)),t(c(1:length(cols))), axes = F, col = cols, xlab = '', ylab = '')
  box()
  axis(4, at = seq(0.5, length(brks)-0.5, subsampleg), tick = T, labels = brks[seq(1,length(brks),subsampleg)] )
}else{
  par(mar = c(1.5, 1, 1, 1), mgp = c(1.5, 0.3, 0), las = 1, cex = 1.2)
  image(1:length(cols),1, t(t(1:length(cols))), axes = F, col = cols,xlab = '', ylab = '')
  box()
  axis(1, at = seq(0.5, length(brks)-0.5, subsampleg), labels = brks[seq(1,length(brks),subsampleg)])
}

}
#
################################################################################
CFU_animvsltime<-function(var, lat, lon, toptitle=c('','','','','','','','','','',''), units='', monini=1, freq=12, msk95lev=FALSE ,brk=NULL, col=NULL, lonmin=0, lonmax=360, latmin=-90, latmax=90, center=NULL, equi=TRUE, fileout=c('output1_CFU_animvsltime','output2_CFU_animvsltime','output3_CFU_animvsltime')) {
#===============================================================================
#
source("/cfu/pub/scripts/R/rclim.txt")
#
#  Get some arguments
# ~~~~~~~~~~~~~~~~~~~~
#
if (length(dim(var))==3) { var=CFU_insertdim(var,posdim=1,lendim=1)}
if (length(dim(var))==4) { var=CFU_insertdim(var,posdim=2,lendim=3)}
if (length(dim(var))==5) { var=CFU_insertdim(var,posdim=2,lendim=1)}
nleadtime=dim(var)[4]
nexp=dim(var)[1]
nobs=dim(var)[2]
nlat=dim(var)[5]
nlon=dim(var)[6]
if (is.null(brk)==T) {
  ll=min(var[,,2,,,],na.rm=T)
  ul=max(var[,,2,,,],na.rm=T)
  if (is.null(col)==T) { col=bluered(10) }
  nlev=length(col)
  brk=seq(ll,ul,(ul-ll)/nlev)
}else{
  if (is.null(col)==T) {
    nlev=length(brk)-1
    col=bluered(nlev)
  }else{nlev=length(col)}
}
lon[which(lon<lonmin)]=lon[which(lon<lonmin)]+360.
lon[which(lon>lonmax)]=lon[which(lon>lonmax)]-360.
latb=sort(lat[which(lat>=latmin & lat<=latmax)],index.return=TRUE)
lonb=sort(lon[which(lon>=lonmin & lon<=lonmax)],index.return=TRUE)
#
#  Define some plot parameters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
labind=1:nleadtime
months=c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")
years=((labind-1)*12/freq + monini -1)%/%12
suffixtit=months[((labind-1)*12/freq + monini -1 )%%12 + 1]
for (jx in 1:nleadtime) {
  y2o3dig=paste("0",as.character(years[jx]),sep="")
  suffixtit[jx]=paste(suffixtit[jx],"-",substr(y2o3dig,nchar(y2o3dig)-1,nchar(y2o3dig)),sep="")
}
#
#  Loop on experimental & observational data
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
for (jexp in 1:nexp) {
  for (jobs in 1:nobs) {
    postscript(paste(fileout[(jexp-1)*nobs+jobs],'.png',sep=""),width=550,height=300)
    for (jt in 1:nleadtime){ 
      title=paste(toptitle[(jexp-1)*nobs+jobs]," Time=",suffixtit[jt],sep="")
      varbis=var[jexp,jobs,2,jt,which(lat>=latmin & lat<=latmax),which(lon>=lonmin & lon<=lonmax)]
      varbis=varbis[latb$ix,lonb$ix]
      if (msk95lev) {
        varbis[which(var[jexp,jobs,1,jt,latb$ix,lonb$ix]<0 & var[jexp,jobs,3,jt,latb$ix,lonb$ix]>0)]=NA 
        varbis[which(var[jexp,jobs,1,jt,latb$ix,lonb$ix]>0 & var[jexp,jobs,3,jt,latb$ix,lonb$ix]<0)]=NA
      }
      varbis[which(varbis<=min(brk))]=min(brk)+(max(brk)-min(brk))/1000.0
      varbis[which(varbis>=max(brk))]=max(brk)-(max(brk)-min(brk))/1000.0
      plotmap(lonb$x,latb$x,t(varbis),maintit=title,legtit=units,equi=equi,lonlim=c(lonmin,lonmax),latlim=c(latmin,latmax),orientation=center,ymaplim=c(latmin,latmax),breaks=brk,n=nlev,colours=col)
    }
    dev.off()
    system(paste('convert -loop 10 -delay 50 ',fileout[(jexp-1)*nobs+jobs],'.png ',fileout[(jexp-1)*nobs+jobs],'.gif',sep=""))
    system(paste('rm -f ',fileout[(jexp-1)*nobs+jobs])) 
  }
}
#
}
#
################################################################################
CFU_eno<-function(obs, posdim){
#===============================================================================
#
#  Enlarge the size of obs to 10 and move posdim to first position 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 
dimsvar=dim(obs)
enlobs=CFU_enlarge(obs,10)
outdim=c(dimsvar,array(1,dim=(10-length(dimsvar))))
posaperm=1:10
posaperm[posdim]=1
posaperm[1]=posdim
enlobs=aperm(enlobs,posaperm)
dimsaperm=outdim[posaperm]
#
#  Loop on all dimensions to compute effective number of observations 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
enleno=array(dim=c(1,dimsaperm[2:10]))
for (j2 in 1:dimsaperm[2]){
  for (j3 in 1:dimsaperm[3]){
    for (j4 in 1:dimsaperm[4]){
      for (j5 in 1:dimsaperm[5]){
        for (j6 in 1:dimsaperm[6]){
          for (j7 in 1:dimsaperm[7]){
            for (j8 in 1:dimsaperm[8]){
              for (j9 in 1:dimsaperm[9]){
                for (j10 in 1:dimsaperm[10]){
                  tmp=enlobs[,j2,j3,j4,j5,j6,j7,j8,j9,j10]
                  if ( length(sort(tmp)) > 1 ) {
                    n=length(sort(tmp))
                    a=acf(tmp,lag.max=n-1,plot=FALSE,na.action=na.pass)$acf[2:n,1,1]
                    s=0
                    for ( k in 1:(n-1) ) {
                      s=s+(((n-k)/n)*a[k])
                    }
                    enleno[1,j2,j3,j4,j5,j6,j7,j8,j9,j10]=min(n/(1+(2*s)),n)
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
#
#  Back to the original dimensions
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimsvar=dimsvar[-posdim]
effnumobs=array(dim=dimsvar)
effnumobs[]=aperm(enleno,posaperm)
#
#  Outputs
# ~~~~~~~~~
#
effnumobs
#
}
#
################################################################################
CFU_histo2hindcast<-function(varin, sdatesin, sdatesout, nleadtimesout){
#===============================================================================
#
#  Input parameters
# ~~~~~~~~~~~~~~~~~~
#
ndims=length(dim(varin))
varin=CFU_enlarge(varin,7)
outvar=array(dim=c(dim(varin)[1:2],length(sdatesout),nleadtimesout,dim(varin)[5:7]))
yearsin=as.integer(substr(sdatesin,1,4))
yearsout=as.integer(substr(sdatesout,1,4))
monthin=as.integer(substr(sdatesin,5,6))
monthout=as.integer(substr(sdatesout,5,6))
#
#  Re-organization
# ~~~~~~~~~~~~~~~~~
#
for (indyear in 1:length(sdatesout)) {
  difmonths=(yearsin[1]-yearsout[indyear])*12+monthin[1]-monthout[1]
  if ( ( difmonths < nleadtimesout ) & ( (-difmonths) < dim(varin)[4] ) ) {
    outvar[,,indyear,max(difmonths+1,1):min(dim(varin)[4]+difmonths,nleadtimesout),,,]=varin[,,1,max(1-difmonths,1):min(nleadtimesout-difmonths,dim(varin)[4]),,,]
  }
}
#
#  Outputs
# ~~~~~~~~~
#
outvar=array(outvar,dim=dim(outvar)[1:ndims])
#
}
#
################################################################################
CFU_season<-function(var, posdim=4, monini, moninf, monsup){
#===============================================================================
#
while (monsup < moninf) { monsup=monsup + 12 }
#
#  Enlarge the size of var to 10 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 
dimsvar=dim(var)
if (is.null(dimsvar)) { dimsvar=length(var) }
ntime=dimsvar[posdim]
enlvar=CFU_enlarge(var,10)
outdim=c(dimsvar,array(1,dim=(10-length(dimsvar))))
u=CFU_inilistdims(outdim,10)
v=CFU_inilistdims(outdim,10)
#
#  Compute the seasonal means 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
ind=1:ntime
months=((ind-1) + monini -1 )%%12 + 1
years=((ind-1) + monini -1)%/%12
#
for (jmon in moninf:monsup) {
  u[[posdim]]=ind[which(months==((jmon-1)%%12+1))]
  ind0=u[[posdim]][1]
  indf=u[[posdim]][length(u[[posdim]])]
  if ( indf > (ntime-(monsup-jmon)) ) { u[[posdim]]=u[[posdim]][-which(u[[posdim]]==indf)] }
  if ( ind0 < (jmon-moninf+1) ) { u[[posdim]]=u[[posdim]][-which(u[[posdim]]==ind0)] } 
  if (jmon == moninf) { 
    nseas=length(u[[posdim]])
    dimsvar[posdim]=nseas
    outdim[posdim]=nseas
    enlvarout=array(0,dim=outdim)
  }
  v[[posdim]]=1:nseas
  enlvarout[v[[1]],v[[2]],v[[3]],v[[4]],v[[5]],v[[6]],v[[7]],v[[8]],v[[9]],v[[10]]]=enlvarout[v[[1]],v[[2]],v[[3]],v[[4]],v[[5]],v[[6]],v[[7]],v[[8]],v[[9]],v[[10]]]+enlvar[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]
}
varout=array(dim=dimsvar)
varout[]=enlvarout
varout=varout/(monsup-moninf+1)
#
#  Outputs
# ~~~~~~~~~
#
varout
#
}
#
################################################################################
CFU_selindices<-function(var, posdim, limits) {
#
#===============================================================================
#
#  A few security checks
# ~~~~~~~~~~~~~~~~~~~~~~~
#
dimsvar=dim(var)
if (is.null(dimsvar)) { dimsvar=length(var) }
if (posdim > length(dimsvar) ) { stop("posdim does not exist") }
if (length(limits) != 2) { stop("Need lower and upper limit") } 
if (dimsvar[posdim] < limits[2]) { stop("Check the consistency between limits and var dimensions") }
#
#  Select the correct indices 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
enlvar=CFU_enlarge(var,10)
u=CFU_inilistdims(dimsvar,10)
u[[posdim]]=limits[1]:limits[2]
enlvarout=enlvar[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]
#
#  Preparing the output matrice
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
if (limits[2]==limits[1]) {dimsvar=dimsvar[-posdim]} else {dimsvar[posdim]=limits[2]-limits[1]+1}
varout=array(dim=dimsvar)
varout[]=enlvarout
#
#  Output
# ~~~~~~~~
#
varout
#
}
################################################################################
CFU_enlarge<-function(var, numdims) {
#
#  Description
# ~~~~~~~~~~~~~
#
#  Extends the number of dimensions of var to numdims (the added dimensions have
#  length 1)
#
#  Author 
# ~~~~~~~~
#
#  CFUers <vguemas@ic3.cat> March 2011
#
#===============================================================================
#
#  Enlarge the number of dimensions to 20 --> enlvar
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimsvar=dim(var)
if (is.null(dimsvar)) { dimsvar=length(var) }
d=c(dimsvar,array(1,dim=20))
enlvar=array(dim=d[1:20])
enlvar[,,,,,,,,,,,,,,,,,,,]=var
#
#  Reduce the number of dimensions to the required one
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
outvar=array(dim=d[1:numdims])
outvar[]=enlvar
#
#  Outputs
# ~~~~~~~~~
#
outvar
#
}
################################################################################
CFU_insertdim<-function(var, posdim, lendim) {
#
#  Description
# ~~~~~~~~~~~~~
#  
#  Add one dimension to matrix var in position posdim with length lendim and
#  which correspond to ( lendim x var matrix ) 
#
#  Author
# ~~~~~~~~
#
#  CFUers <vguemas@ic3.cat> March 2011
#
#===============================================================================
#
#  Initialisation of the output var with the required dimension length 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimsvar=dim(var)
if (is.null(dimsvar)) { dimsvar=length(var) }
outdim=lendim
if (posdim > 1) { outdim=c(dimsvar[1:(posdim-1)],outdim) }
if (posdim <= length(dimsvar)) {outdim=c(outdim,dimsvar[posdim:length(dimsvar)])}
tmpvar=array(dim=c(outdim,array(1,dim=(10-length(outdim)))))
#
#  Duplicate the matrix along the required (posdim)th dimension
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
u=CFU_inilistdims(outdim,10)
#
for (jindex in 1:lendim){
  u[[posdim]]=jindex
  tmpvar[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]=var
}
#
#  Reduce the number of dimensions to the required one
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 
outvar=array(dim=outdim)
outvar[]=tmpvar
#
#  Outputs
# ~~~~~~~~~
#
outvar
#
}
#
################################################################################
CFU_mean1dim<-function(var, posdim, narm=T, limits=NULL) {
#
#  Description
# ~~~~~~~~~~~~~
#
#  Averages the matrix var along the posdim dimension between limits [1] and 
#  limits [2] if limits argument is given
#
#  Author
# ~~~~~~~~
#
#  CFUers <vguemas@ic3.cat>
#
#===============================================================================
#
if (is.null(limits)) { limits=c(1,dim(var)[posdim]) }
#
#  Initialisation of the output var with the required dimension length 
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
dimsvar=dim(var)
outdim=c()
if (posdim > 1) { outdim=c(dimsvar[1:(posdim-1)],outdim) }
if (posdim < length(dimsvar)) {outdim=c(outdim,dimsvar[(posdim+1):length(dimsvar)])}
tmpvar=array(0,dim=c(outdim,array(1,dim=(9-length(outdim)))))
#
#  Handling NA
# ~~~~~~~~~~~~~
#
weight=array(1,dim=dimsvar)
if (narm) {
  weight[is.na(var)]=0
  var[is.na(var)]=0
}
outweight=array(0,dim=c(outdim,array(1,dim=(9-length(outdim)))))
#
#  Average the matrix over the required (posdim)th dimension
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
u=CFU_inilistdims(dimsvar,10)
v=CFU_inilistdims(outdim,9)
enlvar=CFU_enlarge(var,10)
weight=CFU_enlarge(weight,10)
#
for (jindex in limits[1]:limits[2]){
  u[[posdim]]=jindex
  tmpvar[v[[1]],v[[2]],v[[3]],v[[4]],v[[5]],v[[6]],v[[7]],v[[8]],v[[9]]]=tmpvar[v[[1]],v[[2]],v[[3]],v[[4]],v[[5]],v[[6]],v[[7]],v[[8]],v[[9]]]+enlvar[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]
  outweight[v[[1]],v[[2]],v[[3]],v[[4]],v[[5]],v[[6]],v[[7]],v[[8]],v[[9]]]=outweight[v[[1]],v[[2]],v[[3]],v[[4]],v[[5]],v[[6]],v[[7]],v[[8]],v[[9]]]+weight[u[[1]],u[[2]],u[[3]],u[[4]],u[[5]],u[[6]],u[[7]],u[[8]],u[[9]],u[[10]]]
}
tmpvar=tmpvar/outweight
#
#  Reduce the number of dimensions to the required one
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  
outvar=array(dim=outdim)
outvar[]=tmpvar
#
#  Outputs
# ~~~~~~~~~
#
outvar
#  
}
#
################################################################################
CFU_inilistdims<-function(dims,lenlist){
#
#  Description
# ~~~~~~~~~~~~~
#
#  A detail : Ask Virginie for an explanation
#
#  Author
# ~~~~~~~~
#
# CFUers <vguemas@ic3.cat>
#
#===============================================================================
#
u=list()
for (jdim in 1:length(dims)) { u[[jdim]]=1:dims[jdim] }
for (jdim in (length(dims)+1):lenlist) { u[[jdim]]=1 }
#
#  Outputs
# ~~~~~~~~~
#
out=u
#
}
#
################################################################################
CFU_meanlistdim<-function(var,dims,narm=T){
#
#  Description
# ~~~~~~~~~~~~~
#
#  Averages the matrix var along a set of dimensions given as argument : dims 
#
#  Author
# ~~~~~~~~
#
#  CFUers <vguemas@ic3.cat>
#
#===============================================================================
#
whichdims=sort(dims,decreasing=T)
for (jdim in 1:length(whichdims)) {
  if (whichdims[jdim]<=length(dim(var))){
    if (length(dim(var))>1){
      var=CFU_mean1dim(var,posdim=whichdims[jdim],narm=narm)
    }else{
      var=mean(var,na.rm=narm)
    }
  }
}
# 
#  Outputs
# ~~~~~~~~~
# 
outvar=var
# 
}
#

