library(s2dverification)  # for the function Load()
library(abind)
library(Kendall)
source('/home/Earth/ncortesi/Downloads/scripts/Rfunctions.R') # for the calendar functions
workdir <- "/scratch/Earth/ncortesi/RESILIENCE/Regimes"    # working dir with the input files with the WT classifications for each MSLP grid point

# available reanalysis for the geopotential (g500) or the geopotential height (z500 = g500/9.81):
ERAint <- list(path = '/esnas/reconstructions/ecmwf/eraint/$STORE_FREQ$_mean/$VAR_NAME$_f6h/$VAR_NAME$_$YEAR$$MONTH$.nc')
ERAint.name <- "ERA-Interim"

JRA55 <- list(path = '/esnas/reconstructions/jma/jra-55/$STORE_FREQ$_mean/$VAR_NAME$_f6h/$VAR_NAME$_$YEAR$$MONTH$.nc')
JRA55.name <- "JRA-55"

rean <- ERAint #JRA55 #ERAint  # choose one of the two above reanalysis from where to load the input psl data
rean.name <- ERAint.name #JRA55.name #ERAint.name

# available forecast systems for the var data:
ECMWF_monthly <- list(path = paste0('/esnas/exp/ECMWF/monthly/ensforhc/6hourly/$VAR_NAME$/2014$MONTH$$DAY$00/$VAR_NAME$_$START_DATE$00.nc'))
ECMWF_monthly.name <- "ECMWF-Monthly"

forecast <- ECMWF_monthly
forecast.name <- ECMWF_monthly.name

fields <- rean #forecast  # put 'rean' to load pressure fields and var from reanalisis, put 'forecast' to load them from forecast systems
fields.name <- rean.name #forecast.name

year.start <- 1979 #1994 #1979 #1981
year.end <- 2013 #2010

leadtime <- 1:7 #5:11 #1                        # if fields=forecast, set the forecast time (in days) you want to compute the weather regimes.
startdate.shift <- 1                            # if leadtime=5:11, it's better to shift all startdates of the season 1 week in the past, to fit the exact season of obs.data
                                                # if leadtime=12:18, it's better to shift all startdates of the season 2 weeks in the past, and so on.
forecast.year <- year.end+1                     # if fields=forecast, set the forecast year (it is usually the year after year.end)
mes=1                                           # if fields=forecast, set the month of the first startdate of the forecast year
day=2                                           # if fields=forecast, set the day of the first startdate of the forecast year

psl <- "psl" #"g500"                            # pressure variable to use from the chosen reanalysis
psl.name <- "MSLP" # "Z500"                     # the name to show in the maps

var.data <- rean #ECMWF_monthly # ERAint              # chose a dataset from which to load the input var data (reanalysis or forecasts)
var.data.name <- rean.name #ECMWF_monthly.name # ERAint.name

lat.weighting=FALSE  # set it to true to weight psl data on latitude before applying the cluster analysis
sequences=FALSE  # set it to TRUE if you want to select only days beloning to sequences of at least 5 consecutive days belonging to the same regime.

PCA <- FALSE   # se to TRUE if you want to apply the PCA before the k-means cluster analysis, FALSE otherwise
variance.explained <- 0.8  # the user can set here the minimum % of variance explained by the PCs (typically 0.8 which is equal to 80%)

# Coordinates of the box enclosing the study region (the Northern Atlantic in this case):
lat.max <- 81 #81 #80 #70
lat.min <- 27 #30 #20 #30
lon.max <- 45 #36 #30 #40 
lon.min <- 274.5 #274.5 #270 #280 # put a positive number here because the geopotential has only positive values of longitud!

#############################################################################################################################
#ECMWF_monthly <- list(path = paste0('/esnas/exp/ECMWF/monthly/ensforhc/6hourly/psl/2014010200/1994_010200.nc'))
#ECMWF_monthly <- list(path = paste0('/esnas/exp/ECMWF/monthly/ensforhc/6hourly/$VAR_NAME$/2014$MONTH$$DAY$00/$VAR_NAME$_$START_DATE$00.nc'))
if(lat.min >= lat.max) stop("lat.min cannot be greater than lat.max")
n.years <- year.end - year.start + 1

days.period <- n.days.period <- period.length <- list()
for (p in 1:17){
    days.period[[p]] <- NA
    for(y in year.start:year.end) days.period[[p]] <- c(days.period[[p]], n.days.in.a.future.year(year.start, y) + pos.period(y,p))
    days.period[[p]] <- days.period[[p]][-1] # remove the NA at the begin that was introduced only to be able to execute the above command
    # number of days belonging to that period from year.start to year.end:
    n.days.period[[p]] <- length(days.period[[p]])
    # Number of days belonging to that period in a single year: 
    period.length[[p]] <- n.days.in.a.period(p,1999) #+ ifelse(period==13 | period==2, 1, 0)  # using year 1999 introduce a small error in winter season length because of bisestile years
}


# load only 1 day of pressure data to detect the minimum and maximum lat and lon values which identify only the North Atlantic area:
domain <- Load(var = psl, exp = NULL, obs = list(fields), paste0(year.start,'0102'), storefreq = 'daily', leadtimemax = 1, output = 'lonlat', nprocs=1)
n.lat <- length(domain$lat)
n.lon <- length(domain$lon)

pos.lat.max <- which(lat.max - round(domain$lat,4) >= 0)[1]           # select the first latitude of the domain below the maximum latitude
pos.lat.min <- tail(which(round(domain$lat,4) - lat.min >= 0),1)      # select the last latitude of the domain over the minumum latitude
pos.lon.max <- tail(which(lon.max - round(domain$lon,4) >= 0),1)
pos.lon.min <- which(round(domain$lon,4) - lon.min >= 0)[1]

pos.lat <- if(pos.lat.min < pos.lat.max) {pos.lat.min:pos.lat.max} else {pos.lat.max:pos.lat.min}
pos.lon <- c(1:pos.lon.max,pos.lon.min:length(domain$lon)) # beware that it only consider the case where the study area cross the meridian of Greenwhich!
n.pos.lat <- length(pos.lat)
n.pos.lon <- length(pos.lon)

lat <- domain$lat[pos.lat] # lat values of chosen area only (it is smaller than the whole spatial domain loaded by the data)
lon <- domain$lon[pos.lon] # lon values of chosen area only

lat.min.area <- domain$lat[pos.lat.min] # min and max lat/lon of the chosen area only (same as lat.max, but its values correspond to actual values in the lat vector)
lat.max.area <- domain$lat[pos.lat.max]
lon.min.area <- domain$lon[pos.lon.min]
lon.max.area <- domain$lon[pos.lon.max]

#rm(domain)

# Load psl data:
if(unlist(fields) == unlist(rean)){ # Load daily psl data in the reanalysis case:
    psleuFull <-array(NA,c(n.days.in.a.yearly.period(year.start,year.end), n.pos.lat, n.pos.lon))

    for (y in year.start:year.end){
        var <- Load(var = psl, exp = NULL, obs = list(fields), paste0(y,'0101'), storefreq = 'daily', leadtimemax = n.days.in.a.year(y), output = 'lonlat',
                    latmin = lat.min, latmax = lat.max, lonmin = lon.min, lonmax = lon.max)
        psleuFull[seq.days.in.a.future.year(year.start, y),,] <- var$obs
        rm(var)
        gc()
    }
    
} else {  # Load 6-hourly psl data in the forecast case:    
    psleuFull <-array(NA, c(n.sdates*n.years, n.leadtimes, n.pos.lat, n.pos.lon))  # daily order: 19940102 19950102 ... 20130102 19940109 19950109 ... 20130109 ...
    n.leadtimes <- length(leadtime)
    sdates <- weekly.seq(forecast.year,mes,day)
    n.sdates <- length(sdates)
    
    for (startdate in 1:n.sdates){
       for(lday in leadtime){
          var <- Load(var = psl, exp = NULL, obs = list(fields), paste0(year.start:year.end, substr(sdates[startdate],5,6), substr(sdates[startdate],7,8) ), storefreq = 'daily', leadtimemin = lday*4-3, leadtimemax = lday*4, output = 'lonlat', latmin = lat.min, latmax = lat.max, lonmin = lon.min, lonmax = lon.max)
          
          mean.lday <- apply(var$obs, c(3,5,6), mean, na.rm=T)
          rm(var)
          gc()
                           
          psleuFull[(1+(startdate-1)*n.years):(startdate*n.years), lday-leadtime[1]+1,,] <- mean.lday
          rm(mean.lday)
          gc()
       }
    }
    
}

if(psl=="g500") psleuFull <- psleuFull/9.81   # convert geopotential to geopotential height (in m)
if(psl=="psl") psleuFull <- psleuFull/100   # convert MSLP in Pascal to MSLP in hPa
gc()

save.image(file=paste0(workdir,"/weather_regimes_",fields.name,"_",year.start,"-",year.end,".RData"))
load(file=paste0(workdir,"/weather_regimes_",fields.name,"_",year.start,"-",year.end,".RData"))

# compute the cluster analysis:
my.PCA <- list()
my.cluster <- list()
tot.variance <- list()
n.pcs <- my.cluster <- c()

for(period in 13:16){ 
    if(unlist(fields) == unlist(rean)){    

    } else {
        my.startdates.period <- months.period(forecast.year,mes,day,period) # get which startdates belong to the chosen period

        days.period <- list() # get which days inside psleuFull belong to the chosen period
        for(startdate in my.startdates.period){
           days.period[[p]] <- c(days.period[[p]], (1+(startdate-1)*n.years):(startdate*n.years))
        }        
    }
    
    
    pslPeriod <- psleuFull[days.period[[p]],,] # select only days in the chosen period (i.e: winter)

    # weight the pressure fields based on latitude:
    if(lat.weighting){
       lat.weighted <- cos(lat*pi/180)^0.5
       lat.weighted.array <- InsertDim(InsertDim(lat.weighted,2,n.pos.lon), 1, n.days.period[[p]])
       pslPeriod.weighted <- pslPeriod * lat.weighted.array
       rm(lat.weighted.array)
       gc()
    } else {
       pslPeriod.weighted <- pslPeriod
    }
    
    pslmat <- pslPeriod.weighted
    dim(pslmat) <- c(n.days.period[[p]], n.pos.lat*n.pos.lon) # convert array in a matrix!
    rm(pslPeriod, pslPeriod.weighted)
    gc()

    # # if you are using the monthly forecast system, in winter you must remove the 2nd startdate (20140109) because its data is bad, as you can see with: plot(pslmat[,1:2])
    #if(unlist(fields) == unlist(forecast) && period == 13) pslmat[21:40,] <- NA
        
    if(PCA){ # compute the PCs:
       my.seq <- seq(1, n.pos.lat*n.pos.lon, 9) # select only 1 point of 9
       pslcut <- pslmat[,my.seq]
  
       my.PCA[[period]] <- princomp(pslcut,cor=FALSE)
       tot.variance[[period]] <- head(cumsum(my.PCA[[period]]$sdev^2/sum(my.PCA[[period]]$sdev^2)),50)  # check how many PCAs to keep basing on the sum of their expl. variance
       n.pcs[period] <- head(as.numeric(which(tot.variance[[period]] > variance.explained)),1) # select only the pcs that explains at least 80% of variance
       my.cluster[[period]] <- kmeans(my.PCA[[period]]$scores[,1:n.pcs[period]], centers=4, iter.max=100, nstart=30)  # 4 is the number of clusters
       rm(pslcut)
    } else { # remove from matpsl the years with NA:
       my.cluster[[period]] <- kmeans(pslmat[which(!is.na(pslmat[,1])),], centers=4, iter.max=100, nstart=30)  # 4 is the number of clusters
    }
    
    rm(pslmat)
    gc()
}

var.num <- 2                       # Choose a variable. 1: sfcWind  2: tas

var.name <- c("sfcWind","tas")     # name of the 'predictand' variable of the chosen reanalysis
var.name.full <- c("Wind Speed","Temperature")    # full name of the 'predictand' variable to put in the title of the graphs
var.unit <- c("m/s", "ºC")                        # unit of measure of var (for drawing color scales)

# Load var data:
if(unlist(fields) == unlist(rean)){ # Load daily var data in the reanalysis case:
    vareuFull <-array(NA,c(n.days.in.a.yearly.period(year.start,year.end), n.pos.lat, n.pos.lon))

    for (y in year.start:year.end){
        var <- Load(var = var.name[var.num], exp = NULL, obs = list(var.data), paste0(y,'0101'), storefreq = 'daily', leadtimemax = n.days.in.a.year(y), output = 'lonlat',
                    latmin = lat.min, latmax = lat.max, lonmin = lon.min, lonmax = lon.max)
        vareuFull[seq.days.in.a.future.year(year.start, y),,] <- var$obs
        rm(var)
        gc()
    }
    
} else {  # Load 6-hourly var data in the forecast case:    
    sdates <- weekly.seq(forecast.year,mes,day)
    vareuFull <-array(NA,c(length(sdates)*(year.end-year.start+1), n.pos.lat, n.pos.lon))
    
    for (startdate in 1:length(sdates)){
       var <- Load(var = var.name[var.num], exp = NULL, obs = list(var.data), paste0(year.start:year.end, substr(sdates[startdate],5,6), substr(sdates[startdate],7,8) ), storefreq = 'daily', leadtimemin=leadtime*4-3, leadtimemax=leadtime*4, output = 'lonlat', latmin = lat.min, latmax = lat.max, lonmin = lon.min, lonmax = lon.max)
       temp <- apply(var$obs, c(1,3,5,6), mean, na.rm=T)
       vareuFull[(1+(startdate-1)*(year.end-year.start+1)):(startdate*(year.end-year.start+1)),,] <- temp
       rm(temp,var)
       gc()
    }
    
}

#my.grid<-paste0('r',n.lon,'x',n.lat)
#coord <- Load(var = 'sfcWind', exp = list(ECMWF_monthly), obs = NULL, sdates=paste0(2013,'0102'), leadtimemin = 1, leadtimemax=1,  output = 'lonlat', nprocs=1, grid=my.grid, method='bilinear')

save.image(file=paste0(workdir,"/weather_regimes_",fields.name,"_",var.name[var.num],"_",year.start,"-",year.end,".RData"))
load(file=paste0(workdir,"/weather_regimes_",fields.name,"_",var.name[var.num],"_",year.start,"-",year.end,".RData"))

WR.period <- 1:12 #13:16  # 1-12: Jan-Dec; 13-16: Winter-Spring-Summer-Autumn

# if you want to study WRs at monhly level but using their seasonal time series, you have to copy the WRs time series to the months from 1 to 12:
if(WR.period <- 1:12){
    my.cluster[[1]] <- my.cluster[[2]] <- my.cluster[[3]] <- my.cluster[[4]] <- my.cluster[[5]] <- my.cluster[[6]] <- list()
    my.cluster[[7]] <- my.cluster[[8]] <- my.cluster[[9]] <- my.cluster[[10]] <- my.cluster[[11]] <- my.cluster[[12]] <- list()
    
    ss <- match(days.period[[13]],days.period[[1]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[13]]$cluster; my.cluster[[1]]$cluster <- qq[!is.na(qq)]
    ss <- match(days.period[[13]],days.period[[2]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[13]]$cluster; my.cluster[[2]]$cluster  <- qq[!is.na(qq)]
    ss <- match(days.period[[13]],days.period[[12]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[13]]$cluster; my.cluster[[12]]$cluster <- qq[!is.na(qq)]
    ss <- match(days.period[[14]],days.period[[3]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[14]]$cluster; my.cluster[[3]]$cluster <- qq[!is.na(qq)]
    ss <- match(days.period[[14]],days.period[[4]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[14]]$cluster; my.cluster[[4]]$cluster <- qq[!is.na(qq)]
    ss <- match(days.period[[14]],days.period[[5]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[14]]$cluster; my.cluster[[5]]$cluster <- qq[!is.na(qq)]
    ss <- match(days.period[[15]],days.period[[6]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[15]]$cluster; my.cluster[[6]]$cluster <- qq[!is.na(qq)]
    ss <- match(days.period[[15]],days.period[[7]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[15]]$cluster; my.cluster[[7]]$cluster  <- qq[!is.na(qq)]
    ss <- match(days.period[[15]],days.period[[8]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[15]]$cluster; my.cluster[[8]]$cluster <- qq[!is.na(qq)]
    ss <- match(days.period[[16]],days.period[[9]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[16]]$cluster; my.cluster[[9]]$cluster <- qq[!is.na(qq)]
    ss <- match(days.period[[16]],days.period[[10]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[16]]$cluster; my.cluster[[10]]$cluster <- qq[!is.na(qq)]
    ss <- match(days.period[[16]],days.period[[11]]); ss[which(!is.na(ss))] <- 1; qq <- ss*my.cluster[[16]]$cluster; my.cluster[[11]]$cluster <- qq[!is.na(qq)]
}

for(period in WR.period){ # 1-12: Jan-Dec; 13-16: Winter-Spring-Summer-Autumn; 17: Year
    if(unlist(fields) == unlist(rean)){    
      
       
    } else {
       my.startdates.period <- months.period(forecast.year,mes,day,period)

       #if(period == 13) my.startdates.period <- my.startdates.period[-2]  # remove the second startdate because it is broken
       
       days.period <- list()
       for(startdate in my.startdates.period){
          days.period[[p]] <- c(days.period[[p]], (1+(startdate-1)*(year.end-year.start+1)):(startdate*(year.end-year.start+1)))
       }
       period.length <- length(my.startdates.period) # number of Thusdays in the period
    }
    
    varPeriod <- vareuFull[days.period[[p]],,] # select only var data during the chosen period

    varPeriodClim <- apply(varPeriod, c(2,3), mean, na.rm=T)
    varPeriodClim2 <- InsertDim(varPeriodClim, 1, n.days.period[[p]])
    varPeriodAnom <- varPeriod - varPeriodClim2
    rm(varPeriod, varPeriodClim, varPeriodClim2)
    gc()

    #PlotEquiMap2(varPeriodClim[,EU], lon[EU], lat, filled.continents = FALSE, cols=my.cols.var, intxlon=10, intylat=10, cex.lab=1.5) # plot the climatology of the period    
    
    if(sequences){
        # for each of the 4 clusters, remove the days not belonging to sequences of at least 5 days:
        # warning: first 4 days and last 4 days are not take into account y the algorithm and are treated as not belonging to any sequence (sequ=FALSE)    
        wrdiff <- diff(my.cluster[[period]]$cluster)

        sequ <- rep(FALSE, n.days.period[[p]])
        for(i in 5:(n.days.period[[p]]-5)){
            sequ[i] <- TRUE
            if(wrdiff[i] != 0 & wrdiff[i+1] != 0) sequ[i] = FALSE
            if(wrdiff[i] != 0 & wrdiff[i+2] != 0) sequ[i] = FALSE
            if(wrdiff[i] != 0 & wrdiff[i+3] != 0) sequ[i] = FALSE
            if(wrdiff[i] != 0 & wrdiff[i+4] != 0) sequ[i] = FALSE
            if(wrdiff[i-1] != 0 & wrdiff[i] != 0) sequ[i] = FALSE
            if(wrdiff[i-1] != 0 & wrdiff[i+1] != 0) sequ[i] = FALSE
            if(wrdiff[i-1] != 0 & wrdiff[i+2] != 0) sequ[i] = FALSE
            if(wrdiff[i-1] != 0 & wrdiff[i+3] != 0) sequ[i] = FALSE
            if(wrdiff[i-2] != 0 & wrdiff[i] != 0) sequ[i] = FALSE
            if(wrdiff[i-2] != 0 & wrdiff[i+1] != 0) sequ[i] = FALSE
            if(wrdiff[i-2] != 0 & wrdiff[i+2] != 0) sequ[i] = FALSE
            if(wrdiff[i-3] != 0 & wrdiff[i] != 0) sequ[i] = FALSE
            if(wrdiff[i-3] != 0 & wrdiff[i+1] != 0) sequ[i] = FALSE
            if(wrdiff[i-4] != 0 & wrdiff[i] != 0) sequ[i] = FALSE
        } # close for loop on i
        
        # sequence of daily cluster numbers without the days that doesn't belong to sequences of 5 or more days:
        cluster.sequence <- my.cluster[[period]]$cluster * sequ
        rm(wrdiff, sequ)
    } else{ 
        cluster.sequence <- my.cluster[[period]]$cluster
    }
    
    gc()

    # Replace the days belonging to a regime with the days belonging to a sequence of at least 5 days of that regime:
    wr1 <- which(cluster.sequence == 1)
    wr2 <- which(cluster.sequence == 2)
    wr3 <- which(cluster.sequence == 3)
    wr4 <- which(cluster.sequence == 4)
    
    # yearly frequency of each regime:
    wr1y <- wr2y <- wr3y <-wr4y <- c()
    for(y in year.start:year.end){
       
        if(unlist(fields) == unlist(rean)){    
           wr1y[y-year.start+1] <- length(which(cluster.sequence[(y-year.start)*period.length+(1:period.length)] == 1))
           wr2y[y-year.start+1] <- length(which(cluster.sequence[(y-year.start)*period.length+(1:period.length)] == 2))
           wr3y[y-year.start+1] <- length(which(cluster.sequence[(y-year.start)*period.length+(1:period.length)] == 3))
           wr4y[y-year.start+1] <- length(which(cluster.sequence[(y-year.start)*period.length+(1:period.length)] == 4))
        } else {
           wr1y[y-year.start+1] <- length(which(cluster.sequence[seq((y-year.start+1),length(cluster.sequence), n.years)] == 1))
           wr2y[y-year.start+1] <- length(which(cluster.sequence[seq((y-year.start+1),length(cluster.sequence), n.years)] == 2))
           wr3y[y-year.start+1] <- length(which(cluster.sequence[seq((y-year.start+1),length(cluster.sequence), n.years)] == 3))
           wr4y[y-year.start+1] <- length(which(cluster.sequence[seq((y-year.start+1),length(cluster.sequence), n.years)] == 4))
        }
    }

    rm(cluster.sequence)
    gc()
    
    # convert to frequencies in %:
    wr1y <- wr1y/period.length
    wr2y <- wr2y/period.length
    wr3y <- wr3y/period.length
    wr4y <- wr4y/period.length

    varPeriodAnom1 <- varPeriodAnom[wr1,,]
    varPeriodAnom2 <- varPeriodAnom[wr2,,]
    varPeriodAnom3 <- varPeriodAnom[wr3,,]
    varPeriodAnom4 <- varPeriodAnom[wr4,,]

    varPeriodAnom1mean <- apply(varPeriodAnom1,c(2,3),mean,na.rm=T)
    varPeriodAnom2mean <- apply(varPeriodAnom2,c(2,3),mean,na.rm=T)
    varPeriodAnom3mean <- apply(varPeriodAnom3,c(2,3),mean,na.rm=T)
    varPeriodAnom4mean <- apply(varPeriodAnom4,c(2,3),mean,na.rm=T)
    
    varPeriodAnomBoth1 <- abind(varPeriodAnom, varPeriodAnom1, along = 1)
    pvalue1 <- apply(varPeriodAnomBoth1, c(2,3), function(x) t.test(x[1:n.days.period[[p]]],x[(n.days.period[[p]]+1):length(x)])$p.value)
    rm(varPeriodAnomBoth1, varPeriodAnom1)
    gc()
    
    varPeriodAnomBoth2 <- abind(varPeriodAnom, varPeriodAnom2, along = 1)
    pvalue2 <- apply(varPeriodAnomBoth2, c(2,3), function(x) t.test(x[1:n.days.period[[p]]],x[(n.days.period[[p]]+1):length(x)])$p.value)
    rm(varPeriodAnomBoth2, varPeriodAnom2)
    gc()
    
    varPeriodAnomBoth3 <- abind(varPeriodAnom, varPeriodAnom3, along = 1)
    pvalue3 <- apply(varPeriodAnomBoth3, c(2,3), function(x) t.test(x[1:n.days.period],x[(n.days.period+1):length(x)])$p.value)
    rm(varPeriodAnomBoth3, varPeriodAnom3)
    gc()
    
    varPeriodAnomBoth4 <- abind(varPeriodAnom, varPeriodAnom4, along = 1)
    pvalue4 <- apply(varPeriodAnomBoth4, c(2,3), function(x) t.test(x[1:n.days.period],x[(n.days.period+1):length(x)])$p.value)
    rm(varPeriodAnomBoth4, varPeriodAnom4)
    
    rm(varPeriodAnom)
    gc()

    pslPeriod <- psleuFull[days.period,,]
    pslPeriodClim <- apply(pslPeriod, c(2,3), mean, na.rm=T)
    pslPeriodClim2 <- InsertDim(pslPeriodClim, 1, n.days.period)
    pslPeriodAnom <- pslPeriod - pslPeriodClim2
    
    rm(pslPeriod, pslPeriodClim, pslPeriodClim2)
    gc()

    pslwr1 <- pslPeriodAnom[wr1,,]
    pslwr2 <- pslPeriodAnom[wr2,,]
    pslwr3 <- pslPeriodAnom[wr3,,]
    pslwr4 <- pslPeriodAnom[wr4,,]
    rm(pslPeriodAnom)
    gc()
    
    pslwr1mean <- apply(pslwr1,c(2,3),mean,na.rm=T)
    pslwr2mean <- apply(pslwr2,c(2,3),mean,na.rm=T)
    pslwr3mean <- apply(pslwr3,c(2,3),mean,na.rm=T)
    pslwr4mean <- apply(pslwr4,c(2,3),mean,na.rm=T)

    rm(pslwr1,pslwr2,pslwr3,pslwr4)
    
    # save all the data necessary to redraw the graphs when we know the right regime:
    save(workdir,rean.name,fields.name,var.num,var.name,var.name.full,var.unit,year.start,year.end,period,WR.period,lon,lat,pslwr1mean,pslwr2mean,pslwr3mean,pslwr4mean, varPeriodAnom1mean, varPeriodAnom2mean, varPeriodAnom3mean,varPeriodAnom4mean,wr1y,wr2y,wr3y,wr4y,pvalue1,pvalue2,pvalue3,pvalue4,file=paste0(workdir,"/",fields.name,"_",var.name[var.num],"_",my.period[period],"_mapdata.RData"))
    
    rm(pvalue1,pvalue2,pvalue3,pvalue4)
    rm(pslwr1mean,pslwr2mean,pslwr3mean,pslwr4mean)
    rm(varPeriodAnom1mean,varPeriodAnom2mean,varPeriodAnom3mean,varPeriodAnom4mean)
    gc()    

} # close the for loop on 'period' 


# run it twice: once, with ordering <- FALSE to look only at the cartography and find visually the right regime names of the four clusters;
# and the second time, to save the ordered cartography:
ordering <- TRUE    # If TRUE, order the clusters following the regimes listed in the 'orden' vector (after you manually insert the names).
save.names <- FALSE  # if TRUE, also save the cluster names (i.e: the association between clusters and weather regimes); if FALSE, the cluster names are loaded from the file
as.pdf <- FALSE # FALSE: save results as one .png file for each season, TRUE: save only 1 .pdf file with all seasons

# position of long values of Europe only (without the Atlantic Sea and America):
#if(fields.name == "ERA-Interim") EU <- c(1:which(lon >= lon.max)[1], (length(lon)-30):length(lon))  # restrict area to continental europe only
EU <- c(1:which(lon >= lon.max)[1], (which(lon >= 337)[1]:length(lon)))  # restrict area to continental europe only

# choose an order to give to the cartography, from top to bottom:
orden <- c("NAO+","NAO-","Blocking","Atl.Ridge")
    
regime1.name <- orden[1]
regime2.name <- orden[2]
regime3.name <- orden[3]
regime4.name <- orden[4]

if(save.names){cluster1.name.period <- cluster2.name.period <- cluster3.name.period <- cluster4.name.period <- c()}

# breaks and colors of the geopotential fields:
if(psl == "g500"){
    #my.brks <- c(-300,-199:200,300) # % Mean anomaly of a WR
    my.brks <- c(-300,seq(-200,200,10),300) # % Mean anomaly of a WR
    my.brks2 <- c(-300,seq(-200,200,10),300) # % Mean anomaly of a WR for the contour lines
    #my.cols <- colorRampPalette((brewer.pal(9,"PuBu")))(length(my.brks)-1)
    values.to.plot <- c(-200, -100, 0, 100, 200)  # values we want to show in the labels
}

if(psl == "psl"){
    my.brks <- c(seq(-19,-1,2),0,seq(1,19,2)) # % Mean anomaly of a WR
    my.brks2 <- my.brks #c(seq(-20,20,2)) # % Mean anomaly of a WR for the contour lines
    values.to.plot <- my.brks #c(-17,-15,-13,-11,-9,-7,-5,-3,-1,0,1,3,5,7,9,11,13,15,17)
}

my.cols <- colorRampPalette(rev(brewer.pal(11,"RdBu")))(length(my.brks)-1)    # blue--white--red colors
my.cols[floor(length(my.cols)/2)] <- my.cols[floor(length(my.cols)/2)+1] <- "white"
    
# breaks and colors of the impact maps (valid both for Wind speed anomalies and Temperature anomalies):
#my.brks.var <- c(-20,seq(-10,-3,1),seq(-2.9,2.9,0.1),seq(3,10,1),20) # % Mean anomaly of a WR
#my.brks.var <- c(-20,-2,-1.5,-1,-0.5,-0.2,0.2,0.5,1,1.5,2,20) # % Mean anomaly of a WR
#my.brks.var <- c(-20,seq(-3,3,0.5),20) # % Mean anomaly of a WR
if(var.name[var.num] == "sfcWind") {
    my.brks.var <- seq(-3,3,0.5)
    values.to.plot2 <- c(-3,-2,-1,0,1,2,3)
}
if(var.name[var.num] == "tas") {
    my.brks.var <- seq(-5,5,1) 
    values.to.plot2 <- my.brks.var #c(-5,-3,-1,0,1,3,5)
}
 
#my.cols <-  colorRampPalette(as.character(read.csv("/home/Earth/vtorralb/rgbhex.csv",header=F)[,1]))(length(my.brks)-1)  # blue--yellow-red colors
my.cols.var <- colorRampPalette(rev(brewer.pal(11,"RdBu")))(length(my.brks.var)-1)    # blue--white--red colors
#my.cols.var[floor(length(my.cols.var)/2)] <- my.cols.var[floor(length(my.cols.var)/2)+1] <- "white"

if(as.pdf)(pdf(file=paste0(workdir,"/",fields.name,"_",var.name[var.num],".pdf"),width=40, height=60))

for(period in WR.period){    
    load(file=paste0(workdir,"/",fields.name,"_",var.name[var.num],"_",my.period[period],"_mapdata.RData"))

    if(save.names){
        if(period == 1){ # January
            cluster2.name="NAO+"
            cluster1.name="NAO-"
            cluster4.name="Blocking"
            cluster3.name="Atl.Ridge"
        }
        if(period == 2){ # February
            cluster3.name="NAO+"
            cluster2.name="NAO-"
            cluster4.name="Blocking"
            cluster1.name="Atl.Ridge"
        }
        if(period == 3){ # March
            cluster3.name="NAO+"
            cluster2.name="NAO-"
            cluster4.name="Blocking"
            cluster1.name="Atl.Ridge"
        }
        if(period == 4){ # April
            cluster2.name="NAO+"
            cluster1.name="NAO-"
            cluster3.name="Blocking"
            cluster4.name="Atl.Ridge"  
        }
        if(period == 5){ # May
            cluster4.name="NAO+"
            cluster2.name="NAO-"
            cluster3.name="Blocking"
            cluster1.name="Atl.Ridge"
        }
        if(period == 6){ # June
            cluster4.name="NAO+"
            cluster1.name="NAO-"
            cluster2.name="Blocking"
            cluster3.name="Atl.Ridge"
        }
        if(period == 7){ # July
            cluster4.name="NAO+"
            cluster2.name="NAO-"
            cluster1.name="Blocking"
            cluster3.name="Atl.Ridge"
        }
        if(period == 8){ # August
            cluster2.name="NAO+"
            cluster4.name="NAO-"
            cluster3.name="Blocking"
            cluster1.name="Atl.Ridge"  
        }
        if(period == 9){ # September
            cluster4.name="NAO+"
            cluster3.name="NAO-"
            cluster1.name="Blocking"
            cluster2.name="Atl.Ridge"
        }
        if(period == 10){ # October
            cluster1.name="NAO+"
            cluster4.name="NAO-"
            cluster2.name="Blocking"
            cluster3.name="Atl.Ridge"
        }
        if(period == 11){ # November
            cluster2.name="NAO+"
            cluster3.name="NAO-"
            cluster1.name="Blocking"
            cluster4.name="Atl.Ridge"
        }
        if(period == 12){ # December
            cluster2.name="NAO+"
            cluster4.name="NAO-"
            cluster1.name="Blocking"
            cluster3.name="Atl.Ridge"  
        }
        if(period == 13){ # Winter
            cluster3.name="NAO+"
            cluster4.name="NAO-"
            cluster1.name="Blocking"
            cluster2.name="Atl.Ridge"
        }
        if(period == 14){ # Spring
            cluster1.name="NAO+"
            cluster3.name="NAO-"
            cluster2.name="Blocking"
            cluster4.name="Atl.Ridge"
        }
        if(period == 15){ # Summer
            cluster2.name="NAO+"
            cluster3.name="NAO-"
            cluster4.name="Blocking"
            cluster1.name="Atl.Ridge"
        }
        if(period == 16){ # Autumn
            cluster4.name="NAO+"
            cluster1.name="NAO-"
            cluster2.name="Blocking"
            cluster3.name="Atl.Ridge"  
        }
                
        cluster1.name.period[period] <- cluster1.name
        cluster2.name.period[period] <- cluster2.name
        cluster3.name.period[period] <- cluster3.name
        cluster4.name.period[period] <- cluster4.name
        
        save(cluster1.name.period, cluster2.name.period, cluster3.name.period, cluster4.name.period, file=paste0(workdir,"/",fields.name,"_ClusterNames.RData"))
        
    } else { # in this case, we load the cluster names from the file already saved:
        load(paste0(workdir,"/",fields.name,"_ClusterNames.RData"))
        cluster1.name <- cluster1.name.period[period]
        cluster2.name <- cluster2.name.period[period]
        cluster3.name <- cluster3.name.period[period]
        cluster4.name <- cluster4.name.period[period]
    }
    
    # assign to each cluster its regime:
    if(ordering == FALSE){
       cluster1 <- 1; cluster2 <- 2; cluster3 <- 3; cluster4 <- 4
    } else {
       cluster1 <- which(orden == cluster1.name)
       cluster2 <- which(orden == cluster2.name)
       cluster3 <- which(orden == cluster3.name)
       cluster4 <- which(orden == cluster4.name)
    }
    
    assign(paste0("map",cluster1), pslwr1mean)
    assign(paste0("map",cluster2), pslwr2mean)
    assign(paste0("map",cluster3), pslwr3mean)
    assign(paste0("map",cluster4), pslwr4mean)
       
    assign(paste0("imp",cluster1), varPeriodAnom1mean)
    assign(paste0("imp",cluster2), varPeriodAnom2mean)
    assign(paste0("imp",cluster3), varPeriodAnom3mean)
    assign(paste0("imp",cluster4), varPeriodAnom4mean)

    assign(paste0("sig",cluster1), pvalue1)
    assign(paste0("sig",cluster2), pvalue2)
    assign(paste0("sig",cluster3), pvalue3)
    assign(paste0("sig",cluster4), pvalue4)

    assign(paste0("fre",cluster1), wr1y)
    assign(paste0("fre",cluster2), wr2y)
    assign(paste0("fre",cluster3), wr3y)
    assign(paste0("fre",cluster4), wr4y)
       
    # Visualize the composition with the 3 graphs for all the 4 regimes: its pressure fields, its impact on var and its frequency series:
    if(!as.pdf) png(filename=paste0(workdir,"/",fields.name,"_",var.name[var.num],"_",my.period[period],".png"),width=3000,height=3700)
    
    plot.new()

    # Sheet title:
    par(fig=c(0, 1, 0.94, 0.98), new=TRUE)
    mtext(paste0("Weather Regimes for ",my.period[period]," season (",year.start,"-",year.end,"). Source: ",fields.name), cex=6, font=2)
            
    # Centroid maps:
    map.xpos <- 0
    map.width <- 0.46
    par(fig=c(map.xpos + 0.003, map.xpos + map.width - 0.003, 0.745, 0.925), new=TRUE)
    PlotEquiMap2(rescale(map1,my.brks[1],tail(my.brks,1)), lon, lat, filled.continents=FALSE, brks=my.brks, cols=my.cols, sizetit=1.2, contours=t(map1), brks2=my.brks2, intxlon=10, intylat=10, drawleg=F, cex.lab=1.5, xlabel.dist=1.5, contours.lty="F1FF1F")
    par(fig=c(map.xpos, map.xpos + map.width, 0.51, 0.69), new=TRUE)
    PlotEquiMap2(rescale(map2,my.brks[1],tail(my.brks,1)), lon, lat, filled.continents=FALSE, brks=my.brks, cols=my.cols, sizetit=1.2, contours=t(map2), brks2=my.brks2, intxlon=10, intylat=10, drawleg=F, cex.lab=1.5, contours.lty="F1FF1F")
    par(fig=c(map.xpos, map.xpos + map.width, 0.275, 0.455), new=TRUE)
    PlotEquiMap2(rescale(map3,my.brks[1],tail(my.brks,1)), lon, lat, filled.continents=FALSE, brks=my.brks, cols=my.cols, sizetit=1.2, contours=t(map3), brks2=my.brks2, intxlon=10, intylat=10, drawleg=F, cex.lab=1.5, contours.lty="F1FF1F")
    par(fig=c(map.xpos, map.xpos + map.width, 0.04, 0.22), new=TRUE)
    PlotEquiMap2(rescale(map4,my.brks[1],tail(my.brks,1)), lon, lat, filled.continents=FALSE, brks=my.brks, cols=my.cols, sizetit=1.2, contours=t(map4), brks2=my.brks2, intxlon=10, intylat=10, drawleg=F, cex.lab=1.5, contours.lty="F1FF1F")

    # Title Centroid Maps:
    map.title.xpos <- 0.76
    map.title.width <- 0.2
    par(fig=c(map.title.xpos, map.title.xpos + map.title.width, 0.728, 0.729), new=TRUE)
    mtext("year", cex=3)
    par(fig=c(map.title.xpos, map.title.xpos + map.title.width, 0.494, 0.495), new=TRUE)
    mtext("year", cex=3)
    par(fig=c(map.title.xpos, map.title.xpos + map.title.width, 0.260, 0.261), new=TRUE)
    mtext("year", cex=3)
    par(fig=c(map.title.xpos, map.title.xpos + map.title.width, 0.026, 0.027), new=TRUE)
    mtext("year", cex=3)

    # Impact maps:
    impact.xpos <- 0.47
    impact.width <- 0.26    
    par(fig=c(impact.xpos, impact.xpos + impact.width, 0.745, 0.925), new=TRUE)
    PlotEquiMap2(rescale(imp1[,EU],my.brks.var[1],tail(my.brks.var,1)), lon[EU], lat, filled.continents = FALSE, brks=my.brks.var, cols=my.cols.var, intxlon=10, intylat=10, drawleg=F, dots=t(sig1[,EU] < 0.05), cex.lab=1.5)
    par(fig=c(impact.xpos, impact.xpos + impact.width, 0.51, 0.69), new=TRUE)
    PlotEquiMap2(rescale(imp2[,EU],my.brks.var[1],tail(my.brks.var,1)), lon[EU], lat, filled.continents = FALSE, brks=my.brks.var, cols=my.cols.var, intxlon=10, intylat=10, drawleg=F, dots=t(sig2[,EU] < 0.05), cex.lab=1.5)
    par(fig=c(impact.xpos, impact.xpos + impact.width, 0.275, 0.455), new=TRUE)
    PlotEquiMap2(rescale(imp3[,EU],my.brks.var[1],tail(my.brks.var,1)), lon[EU], lat, filled.continents = FALSE, brks=my.brks.var, cols=my.cols.var, intxlon=10, intylat=10, drawleg=F, dots=t(sig3[,EU] < 0.05), cex.lab=1.5)
    par(fig=c(impact.xpos, impact.xpos + impact.width, 0.04, 0.22), new=TRUE)
    PlotEquiMap2(rescale(imp4[,EU],my.brks.var[1],tail(my.brks.var,1)), lon[EU], lat, filled.continents = FALSE, brks=my.brks.var, cols=my.cols.var, intxlon=10, intylat=10, drawleg=F, dots=t(sig4[,EU] < 0.05), cex.lab=1.5)
    
    # Frequency plots:
    barplot.xpos <- 0.75
    barplot.width <- 0.25
    par(fig=c(barplot.xpos, barplot.xpos + barplot.width, 0.745, 0.915), new=TRUE)
    barplot.freq(100*fre1, year.start, year.end, cex.y=2, cex.x=2, freq.max=60, ylab="", mgp=c(3,1.5,0))
    par(fig=c(barplot.xpos, barplot.xpos + barplot.width,0.510,0.680), new=TRUE)
    barplot.freq(100*fre2, year.start, year.end, cex.y=2, cex.x=2, freq.max=60, ylab="", mgp=c(3,1.5,0))
    par(fig=c(barplot.xpos, barplot.xpos + barplot.width,0.275,0.445), new=TRUE)
    barplot.freq(100*fre3, year.start, year.end, cex.y=2, cex.x=2, freq.max=60, ylab="", mgp=c(3,1.5,0)) 
    par(fig=c(barplot.xpos, barplot.xpos + barplot.width,0.040,0.210), new=TRUE)
    barplot.freq(100*fre4, year.start, year.end, cex.y=2, cex.x=2, freq.max=60, ylab="", mgp=c(3,1.5,0))

    # % on Frequency plots:
    symbol.xpos <- 0.735
    symbol.width <- 0.01
    par(fig=c(symbol.xpos, symbol.xpos + symbol.width, 0.83, 0.84), new=TRUE)
    mtext("%", cex=3.3)
    par(fig=c(symbol.xpos, symbol.xpos + symbol.width, 0.60, 0.61), new=TRUE)
    mtext("%", cex=3.3)
    par(fig=c(symbol.xpos, symbol.xpos + symbol.width, 0.36, 0.37), new=TRUE)
    mtext("%", cex=3.3)
    par(fig=c(symbol.xpos, symbol.xpos + symbol.width, 0.13, 0.14), new=TRUE)
    mtext("%", cex=3.3)

    # Title 1:
    title1.xpos <- 0.02
    title1.width <- 0.4
    par(fig=c(title1.xpos, title1.xpos + title1.width, 0.930, 0.935), new=TRUE)
    mtext(paste0(regime1.name,": ", psl.name, " Anomaly"), font=2, cex=4)
    par(fig=c(title1.xpos, title1.xpos + title1.width, 0.695, 0.700), new=TRUE)
    mtext(paste0(regime2.name,": ", psl.name, " Anomaly"), font=2, cex=4)
    par(fig=c(title1.xpos, title1.xpos + title1.width, 0.460, 0.465), new=TRUE)
    mtext(paste0(regime3.name,": ", psl.name, " Anomaly"), font=2, cex=4)
    par(fig=c(title1.xpos, title1.xpos + title1.width, 0.225, 0.230), new=TRUE)
    mtext(paste0(regime4.name,": ", psl.name, " Anomaly"), font=2, cex=4)
    
    # Title 2:
    title2.xpos <- 0.42
    title2.width <- 0.35
    par(fig=c(title2.xpos, title2.xpos + title2.width, 0.930, 0.935), new=TRUE)
    mtext(paste0(regime1.name, ": Impact on ", var.name.full[var.num]), font=2, cex=4)
    par(fig=c(title2.xpos, title2.xpos + title2.width, 0.695, 0.700), new=TRUE)
    mtext(paste0(regime2.name, ": Impact on ", var.name.full[var.num]), font=2, cex=4)
    par(fig=c(title2.xpos, title2.xpos + title2.width, 0.460, 0.465), new=TRUE)
    mtext(paste0(regime3.name, ": Impact on ", var.name.full[var.num]), font=2, cex=4)
    par(fig=c(title2.xpos, title2.xpos + title2.width, 0.225, 0.230), new=TRUE)
    mtext(paste0(regime4.name, ": Impact on ", var.name.full[var.num]), font=2, cex=4)
    
    # Title 3:
    title3.xpos <- 0.75
    title3.width <-0.25
    par(fig=c(title3.xpos, title3.xpos + title3.width, 0.930, 0.935), new=TRUE)
    mtext(paste0(regime1.name, ": Frequency (", round(100*mean(fre1),1), "%)"), font=2, cex=4)
    par(fig=c(title3.xpos, title3.xpos + title3.width, 0.695, 0.700), new=TRUE)
    mtext(paste0(regime2.name, ": Frequency (", round(100*mean(fre2),1), "%)"), font=2, cex=4)
    par(fig=c(title3.xpos, title3.xpos + title3.width, 0.460, 0.465), new=TRUE)
    mtext(paste0(regime3.name, ": Frequency (", round(100*mean(fre3),1), "%)"), font=2, cex=4)
    par(fig=c(title3.xpos, title3.xpos + title3.width, 0.225, 0.230), new=TRUE)
    mtext(paste0(regime4.name, ": Frequency (", round(100*mean(fre4),1), "%)"), font=2, cex=4)
    
    # Legend 1:
    legend1.xpos <- 0.01
    legend1.width <- 0.44
    legend1.cex <- 1.8
    my.subset <- match(values.to.plot, my.brks)
    
    par(fig=c(legend1.xpos, legend1.xpos + legend1.width, 0.719, 0.744), new=TRUE)  # syntax fig=c(xmin, xmax, ymin, ymax)
    ColorBar3(my.brks, cols=my.cols, vert=FALSE, cex=legend1.cex, subset=my.subset)
    if(psl=="g500") {mtext(side=4," m", cex=2.5)} else {mtext(side=4," hPa", cex=legend1.cex)}
    par(fig=c(legend1.xpos, legend1.xpos + legend1.width, 0.485, 0.508), new=TRUE)
    ColorBar3(my.brks, cols=my.cols, vert=FALSE, cex=legend1.cex, subset=my.subset)
    if(psl=="g500") {mtext(side=4," m", cex=2.5)} else {mtext(side=4," hPa", cex=legend1.cex)}
    par(fig=c(legend1.xpos, legend1.xpos + legend1.width, 0.250, 0.273), new=TRUE)
    ColorBar3(my.brks, cols=my.cols, vert=FALSE, cex=legend1.cex, subset=my.subset)
    if(psl=="g500") {mtext(side=4," m", cex=2.5)} else {mtext(side=4," hPa", cex=legend1.cex)
    par(fig=c(legend1.xpos, legend1.xpos + legend1.width, 0.015, 0.038), new=TRUE)
    ColorBar3(my.brks, cols=my.cols, vert=FALSE, cex=legend1.cex, subset=my.subset)
    if(psl=="g500") {mtext(side=4," m", cex=2.5)} else {mtext(side=4," hPa", cex=legend1.cex)}

    # Legend 2:
    legend2.xpos <- 0.48
    legend2.width <- 0.25
    legend2.cex <- 1.8
    my.subset2 <- match(values.to.plot2, my.brks.var)
    
    par(fig=c(legend2.xpos, legend2.xpos + legend2.width, 0.719 + 0.001, 0.744), new=TRUE)
    ColorBar3(my.brks.var, cols=my.cols.var, vert=FALSE, cex=legend2.cex, subset=my.subset2)
    mtext(side=4,paste0(" ",var.unit[var.num]), cex=legend2.cex)
    par(fig=c(legend2.xpos, legend2.xpos + legend2.width, 0.485, 0.508), new=TRUE)
    ColorBar3(my.brks.var, cols=my.cols.var, vert=FALSE, cex=legend2.cex, subset=my.subset2)
    mtext(side=4,paste0(" ",var.unit[var.num]), cex=legend2.cex)  
    par(fig=c(legend2.xpos, legend2.xpos + legend2.width, 0.250, 0.273), new=TRUE)
    ColorBar3(my.brks.var, cols=my.cols.var, vert=FALSE, cex=legend2.cex, subset=my.subset2)}
    mtext(side=4,paste0(" ",var.unit[var.num]), cex=legend2.cex)  
    par(fig=c(legend2.xpos, legend2.xpos + legend2.width, 0.015, 0.038), new=TRUE)
    ColorBar3(my.brks.var, cols=my.cols.var, vert=FALSE, cex=legend2.cex, subset=my.subset2)
    mtext(side=4,paste0(" ",var.unit[var.num]), cex=legend2.cex)  

    if(!as.pdf) dev.off() # for saving 4 png
    
} # close for loop on 'period'

if(as.pdf) dev.off() # for saving a single pdf with all seasons











